Iptables

From Christoph's Personal Wiki
Revision as of 19:51, 14 September 2016 by Christoph (Talk | contribs) (Stateful filtering)

Jump to: navigation, search

Stateful filtering

  • TCP states: NEW, RELATED, ESTABLISHED, INVALID
  • Connection states (to match in the conntrack module): INVALID, NEW, ESTABLISHED, RELATED, UNTRACKED, SNAT, DNAT
  • Chain types (this option can either be the name of a user defined chain or any of the builtin chains): INPUT, FORWARD, OUTPUT, PREROUTING, POSTROUTING, SECMARK, CONNSECMARK
  • Jump types: ACCEPT, DROP, REJECT
  • Basic ruleset:
*filter
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [241:19144]
-A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT 
-A INPUT -p icmp -j ACCEPT 
-A INPUT -i lo -j ACCEPT
-A INPUT -p tcp -m state --state NEW -m tcp --dport 22 -j ACCEPT
-A INPUT -p tcp -m state --state NEW -m tcp --dport 80 -j ACCEPT
-A INPUT -p tcp -m state --state NEW -m tcp --dport 443 -j ACCEPT
-A INPUT -p tcp -m state --state NEW -m tcp --dport 53 -j ACCEPT
-A INPUT -p udp -m state --state NEW -m udp --dport 53 -j ACCEPT
-A INPUT -j REJECT --reject-with icmp-host-prohibited 
-A FORWARD -j REJECT --reject-with icmp-host-prohibited 
COMMIT
-A INPUT -p tcp -m state --state NEW -m tcp --dport 22 --sport 63636 -s 10.0.0.2 -j ACCEPT
  • Get a list of ICMP type names:
$ iptables -p icmp -h
  • The REJECT target rejects the packet. If you do not specify which ICMP message to reject with, by default, the server will send back "ICMP port unreachable" (type 3, code 3).
REJECT
This is used to send back an error packet in response to the matched packet: otherwise it is equivalent to DROP so it is a terminating TARGET, ending rule traversal. This target is only valid in the INPUT, FORWARD, and OUTPUT chains, and user-defined chains which are only called from those chains. The following option controls the nature of the error packet returned:
--reject-with type
The type given can be:
icmp-net-unreachable
icmp-host-unreachable
icmp-port-unreachable
icmp-proto-unreachable
icmp-net-prohibited
icmp-host-prohibited
icmp-admin-prohibited (*)
which return the appropriate ICMP error message (port-unreachable is the default). The option tcp-reset can be used on rules which only match the TCP protocol: this causes a TCP RST packet to be sent back. This is mainly useful for blocking ident (113/tcp) probes, which frequently occur when sending mail to broken mail hosts (which will not accept your mail otherwise).
(*) Using icmp-admin-prohibited with kernels that do not support it will result in a plain DROP instead of REJECT

Examples

  • Sample `iptables` ruleset:
*filter

# Dropping incoming connections that don't have explecit rules bellow
:INPUT DROP [68:4456]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [1628:151823]

# Allow established connections for both public and private connections
-A INPUT -i eth0 -m state --state RELATED,ESTABLISHED -j ACCEPT
-A INPUT -i eth1 -m state --state RELATED,ESTABLISHED -j ACCEPT

# Opening ports wide open
-A INPUT -p tcp -m tcp --dport 22 -j ACCEPT
-A INPUT -p tcp -m tcp --dport 80 -j ACCEPT
-A INPUT -p tcp -m tcp --dport 443 -j ACCEPT
-A INPUT -p tcp -m tcp --dport 21 -j ACCEPT
-A INPUT -p tcp -m tcp --dport 3306 -j ACCEPT
-A INPUT -p tcp -m tcp --dport 53 -j ACCEPT
-A INPUT -p udp -m udp --dport 53 -j ACCEPT

# Opening a port to a specific IP
-A INPUT -p tcp -m tcp --dport 10000 -s 192.168.1.1 -j ACCEPT

# Opening a port to a range of IPs
-A INPUT -p tcp -m tcp --dport 20000 -s 192.168.0.0/24 -j ACCEPT

# Commmiting the rules to the firewall
COMMIT
#!/bin/bash
# Set INPUT chain default policy to DROP
iptables -P INPUT DROP
# Flushes all rule in the filter table
iptables -F
# ACCEPT all packets from loopback interface
iptables -A INPUT -i lo -j ACCEPT
# ACCEPT all ESTABLISHED,RELATED packets
iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
# ACCEPT all NEW connections to tcp port 22
iptables -A INPUT -m state --state NEW -p tcp --dport 22 -j ACCEPT
# REJECT all packets from 192.168.1.0/24 network
iptables -A INPUT -s 192.168.1.0/24 -j REJECT
# ACCEPT all icmp traffic from 192.168.0.0/24
iptables -A INPUT -p icmp -s 192.168.0.0/24 -j ACCEPT
# save rules
iptables-save > /etc/sysconfig/iptables
# print out saved rules
iptables-save
iptables -nvL

Network Address Translation (NAT)

  • The chains available in the filter table are: INPUT, FORWARD, OUTPUT
  • The chains available in the nat table are: PREROUTING, POSTROUTING, OUTPUT
  • Example:
$ iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
$ iptables -t nat -A POSTROUTING -o eth0 -j SNAT --to-source 192.168.0.1
$ iptables -t nat -A PREROUTING -i eth0 -m tcp -p tcp --dport 80 -j DNAT --to-destination 192.168.0.100:8080
  • The DNAT target can only be used in the PREROUTING chain and the OUTPUT chain of the nat table.
  • To enable forwarding persistently across reboots, add net.ipv4.ip_forward=1 to /etc/sysctl.conf then run sysctl -p, or:
sysctl -w net.ipv4.ip_forward=1

Basic command options

Chain manipulation (three default chains, INPUT, FORWARD, OUTPUT, are always present):

  • Create a new chain (-N, --new-chain chain)
  • Delete an empty chain (-X, --delete-chain [chain])
  • Change the policy for a built-in chain (-P, --policy chain target)
  • List the rules in a chain (-L, --list [chain])
  • Flush the rules out of a chain (-F, --flush [chain])
  • Zero the packet and byte counters in all chains (-Z, --zero) (note: It is legal to specify the -L, --list (list) option as well, to see the counters immediately before they are cleared.)

Rule manipulation:

  • Append a new rule to a chain (-A, --append chain rule-specification)
  • Delete a rule at some position in a chain (-D, --delete chain rule-specification)
NEW 
packet starts a new communication, adds a rule to the state tracking table
ESTABLISHED 
any packet that matches a rule in the state tracking table
RELATED 
traffic "related" in some way to ESTABLISHED traffic; protocols like SSH, FTP, etc.
INVALID 
packet cannot be identified; normally these should be rejected or dropped

NOTE: Running the `iptables` command changes the netfilter kernel module rules in memory, but will not persist across a reboot.

Running `service iptables save` will take the current rules in memory and write them to /etc/sysconfig/iptables which is read during system boot. Run instead:

service iptables restart

Help (-h)

Usage

iptables -[AD] chain rule-specification [options]
iptables -[RI] chain rulenum rule-specification [options]
iptables -D chain rulenum [options]
iptables -[LFZ] [chain] [options]
iptables -[NX] chain
iptables -E old-chain-name new-chain-name
iptables -P chain target [options]
iptables -h (print this help information)

Commands

Either long or short options are allowed.

--append -A chain 
append to chain
--delete -D chain 
delete matching rule from chain
--delete -D chain rulenum 
delete rule rulenum (1 = first) from chain
--insert -I chain [rulenum] 
insert in chain as rulenum (default 1=first)
--replace -R chain rulenum 
replace rule rulenum (1 = first) in chain
--list -L [chain] 
list the rules in a chain or all chains
--flush -F [chain] 
delete all rules in chain or all chains
--zero -Z [chain] 
zero counters in chain or all chains
--new -N chain 
create a new user-defined chain
--delete-chain -X [chain] 
delete a user-defined chain
--policy -P chain target 
change policy on chain to target
--rename-chain -E old-chain new-chain 
change chain name, (moving any references)

Options

--proto -p [!] proto 
protocol: by number or name, eg. 'tcp'
--source -s [!] address[/mask] 
source specification
--destination -d [!] address[/mask] 
destination specification
--in-interface -i [!] input name[+] 
network interface name ([+] for wildcard)
--jump -j target 
target for rule (may load target extension)
--goto -g chain 
jump to chain with no return
--match -m match 
extended match (may load extension)
--numeric -n 
numeric output of addresses and ports
--out-interface -o [!] output name[+] 
network interface name ([+] for wildcard)
--table -t table 
table to manipulate (default: 'filter')
--verbose -v 
verbose mode
--line-numbers 
print line numbers when listing
--exact -x 
expand numbers (display exact values)
[!] --fragment -f 
match second or further fragments only
--modprobe=<command> 
try to insert modules using this command
--set-counters PKTS BYTES 
set the counter during insert/append
[!] --version -V 
print package version.

Netmask

Netmask Bit Values
Addrs Bits Pref Class Mask
0 /32 255.255.255.255
2 1 /31 255.255.255.254
4 2 /30 255.255.255.252
8 3 /29 255.255.255.248
16 4 /28 255.255.255.240
32 5 /27 255.255.255.224
64 6 /26 255.255.255.192
128 7 /25 255.255.255.128
256 8 /24 1C 255.255.255.0
512 9 /23 2C 255.255.254.0
1K 10 /22 4C 255.255.252.0
2K 11 /21 8C 255.255.248.0
4K 12 /20 16C 255.255.240.0
8K 13 /19 32C 255.255.224.0
16K 14 /18 64C 255.255.192.0
32K 15 /17 128C 255.255.128.0
64K 16 /16 1B 255.255.0.0
128K 17 /15 2B 255.254.0.0
256K 18 /14 4B 255.252.0.0
512K 19 /13 8B 255.248.0.0
1M 20 /12 16B 255.240.0.0
2M 21 /11 32B 255.224.0.0
4M 22 /10 64B 255.192.0.0
8M 23 /9 128B 255.128.0.0
16M 24 /8 1A 255.0.0.0
32M 25 /7 2A 254.0.0.0
64M 26 /6 4A 252.0.0.0
128M 27 /5 8A 248.0.0.0
256M 28 /4 16A 240.0.0.0
512M 29 /3 32A 224.0.0.0
1024M 30 /2 64A 192.0.0.0
2048M 31 /1 128A 128.0.0.0
4096M 32 /0 256A 0.0.0.0


ICMP datagram types

see: RFC 1700 (Assigned Numbers)
/usr/include/netinet/ip_icmp.h
ICMP Datagram Types
Type number iptables mnemonic Type description
0 echo-reply Echo Reply
3 destination-unreachable Destination Unreachable
4 source-quench Source Quench
5 redirect Redirect
8 echo-request Echo Request
11 time-exceeded Time Exceeded
12 parameter-problem Parameter Problem
13 timestamp-request Timestamp Request
14 timestamp-reply Timestamp Reply
15 none Information Request
16 none Information Reply
17 address-mask-request Address Mask Request
18 address-mask-reply Address Mask Reply


Type Of Service (TOS)

Suggested Uses for TOS Bitmasks
TOS ANDmask XORmask Suggested Use
Minimum Delay 0x01 0x10 ftp, telnet, ssh
Maximum Throughput 0x01 0x08 ftp-data, www
Maximum Reliability 0x01 0x04 snmp, dns
Minimum Cost 0x01 0x02 nntp, smtp


Example script

#!/bin/bash

LOOPBACK="127.0.0.0/8"
CLASS_A="10.0.0.0/8"
CLASS_B="172.16.0.0/12"
CLASS_C="192.168.0.0/16"
CLASS_D="224.0.0.0/4"
CLASS_E="240.0.0.0/5"
BROADCAST_SRC="0.0.0.0"
BROADCAST_DEST="255.255.255.255"

########
# flush iptables
iptables -F
iptables -t nat -F
iptables -t mangle -F

########
# loopback
iptables -A INPUT -i lo -j ACCEPT
iptables -A OUTPUT -o lo -j ACCEPT

########
# policies
iptables -P INPUT DROP
iptables -P OUTPUT ACCEPT
iptables -P FORWARD DROP

iptables -t nat -P PREROUTING ACCEPT
iptables -t nat -P OUTPUT ACCEPT
iptables -t nat -P POSTROUTING ACCEPT

iptables -t mangle -P PREROUTING ACCEPT
iptables -t mangle -P OUTPUT ACCEPT

########
# allow related incoming
iptables -I INPUT 1 -m state --state ESTABLISHED,RELATED -j ACCEPT

########
# programs and stuff (add a line for each service you want to allow)

# SSH on local network
iptables -A INPUT -s $CLASS_A -p tcp --destination-port 22 -j ACCEPT

# apache server (on all interfaces/networks)
iptables -A INPUT -p tcp --destination-port 80 -j ACCEPT

# samba + network share
iptables -A INPUT -s $CLASS_A -p tcp --destination-port 137 -j ACCEPT
iptables -A INPUT -s $CLASS_A -p udp --destination-port 137 -j ACCEPT
iptables -A INPUT -s $CLASS_A -p tcp --destination-port 138 -j ACCEPT
iptables -A INPUT -s $CLASS_A -p udp --destination-port 138 -j ACCEPT
iptables -A INPUT -s $CLASS_A -p tcp --destination-port 139 -j ACCEPT
iptables -A INPUT -s $CLASS_A -p udp --destination-port 139 -j ACCEPT
iptables -A INPUT -s $CLASS_A -p tcp --destination-port 445 -j ACCEPT
iptables -A INPUT -s $CLASS_A -p udp --destination-port 445 -j ACCEPT

Map external IP address onto an internal one

Let's say your external IP address is 128.65.225.10 and your internal IP address is 10.0.17.10, then:

-A PREROUTING -d 128.65.225.10 -j DNAT --to-destination 10.0.17.10
-A POSTROUTING -s 10.0.17.10 -j SNAT --to-source 128.65.225.10

You can then view the results with

iptables --list -n -t nat -v

Scripts

Tips

  • Find your external interface:
$ ip route ls
10.0.213.56 via 10.0.27.5e dev eth0  metric 10
192.168.27.0/24 dev eth0  proto kernel  scope link  src 192.168.27.63  metric 10
10.0.27.0/24 dev eth0  proto kernel  scope link  src 10.0.27.63  metric 10
169.254.0.0/16 dev eth0  scope link  metric 10
127.0.0.0/8 dev lo  scope link
default via 10.0.27.153 dev eth0  metric 10

The last line shows eth0 to be your external interface.

  • Determine the IP address of your external interface:
$ ip addr ls dev eth0
2: eth0: <BROADCAST,MULTICAST,UP,10000> mtu 1500 qdisc pfifo_fast qlen 100
   link/ether 00:19:d1:4f:22:60 brd ff:ff:ff:ff:ff:ff
   inet 128.95.27.63/24 brd 10.0.27.255 scope global eth0
   inet 192.168.27.63/24 brd 192.168.27.255 scope global eth0:0
   inet6 fe80::219:d1ff:fe4f:2260/64 scope link
      valid_lft forever preferred_lft forever
  • So, the IP address of the external interface is 128.95.27.63.

See also

External links

Free firewall software

Tutorials / Howtos / Examples / etc.