iptables
WIP
Basic operations
List the rules
iptables -L -n --line-numbers
iptables -t nat -L -v -n
Remove a rule
iptables -D INPUT -p tcp -m tcp --dport 22 -m conntrack --ctstate NEW -j ACCEPT
iptables -D INPUT 12
Insert a rule
iptables -I INPUT 1 -s 192.168.1.20 -j ACCEPT
Network range
iptables -A OUTPUT -p tcp -d 192.168.100.0/24 --dport 22 -j ACCEPT
IP Address
iptables -A INPUT -s 192.168.1.20 -j ACCEPT
MAC Address
iptables -A INPUT -m mac --mac-source 00:00:00:00:00:00 -j DROP
Limit connections
iptables -A FORWARD -m state --state NEW -p tcp -m multiport --dport http,https -o eth0 -i eth1 -m limit --limit 50/hour --limit-burst 5 -j ACCEPT
Limit concurrent connections
iptables -A INPUT -p tcp --syn --dport 22 -m connlimit --connlimit-above 3 -j REJECT
Limit concurrent connections per IP
iptables -A INPUT -p tcp -m state --state NEW --dport http -m iplimit --iplimit-above 5 -j DROP
Time based connections
iptables -A INPUT -p tcp -m tcp --dport 443 -i enp3s0 -m time --timestart 12:30 --timestop 13:30 --days Mon,Tue,Wed,Thu,Fri -j ACCEPT
Multiple ports
iptables -A INPUT -i eth0 -p tcp -m state --state NEW -m multiport --dports ssh,smtp,http,https -j ACCEPT
Replace a rule
iptables -R INPUT 1 -s 192.168.1.30 -j ACCEPT
Default chain policy
iptables -P INPUT DROP
Log rules
iptables -A INPUT -p tcp --dport 22 -m conntrack --ctstate NEW -j LOG --log-prefix="iptables-ssh: "
/var/log/messages
or journalctl
.
Aug 15 05:30:58 server kernel: iptables-ssh: IN=eth0 OUT= MAC=52:54:00:16:56:7f:52:54:00:0f:b2:e4:08:00 SRC=192.168.1.229 DST=192.168.1.129 LEN=60 TOS=0x00 PREC=0x00 TTL=64 ID=57381 DF PROTO=TCP SPT=45910 DPT=22 WINDOW=29200 RES=0x00 SYN URGP=0
Filter by owner
iptables -A OUTPUT -d 192.168.1.100 -m owner --uid-owner bob -j DROP
iptables -A OUTPUT -d 192.168.1.100 -m owner --gid-owner bob -j DROP
Saving the rules
iptables-save > /etc/iptables/iptables.rules
ip6tables-save > /etc/iptables/ip6tables.rules
conntrack
or state
for connection tracking (new, invalid, established, ...)
conntrack
is much more complete than state
; state
only matches INVALID
, NEW
, ESTABLISHED
, RELATED
or UNTRACKED
; conntrack
can match ip orig/src, port orig/src, direction, status, expire time, and some others (see man iptables-extensions
).
Example:
iptables -A INPUT -p tcp -m tcp --dport 22 -m state --state NEW -i enp3s0 -s 192.168.1.15 -j ACCEPT
The same rule with conntrack
:
iptables -A INPUT -m conntrack --ctstate NEW --ctproto tcp --ctorigsrc 192.168.1.15 --ctorigdstport 22 -i enp3s0 -j ACCEPT
Maybe state
is obsolete and you should use conntrack
but they both do the same.
Example script
#!/usr/bin/env sh
## Flush all chains
iptables -F
iptables -t nat -F
iptables -t mangle -F
## Delete all chains
iptables -X
## Default chain policy
iptables -P INPUT DROP
iptables -P FORWARD DROP
iptables -P OUTPUT ACCEPT
## Rest of the rules
[...]
## Save
iptables-save > /etc/iptables/iptables.rules
ip6tables-save > /etc/iptables/ip6tables.rules
Example rules
## Drop all invalid connections
iptables -A INPUT -m conntrack --ctstate INVALID -j DROP
## Refuse connections without SYN flag
iptables -A INPUT -p tcp ! --syn -m conntrack --ctstate NEW -j DROP
iptables -A INPUT -p tcp -m conntrack --ctstate NEW -m tcp ! --tcp-flags FIN,SYN,RST,ACK SYN -j DROP
## Drop Christmas tree packets
iptables -A INPUT -p tcp -m tcp --tcp-flags ALL FIN,PSH,URG -j DROP
## Drop other invalid packets
iptables -A INPUT -p tcp -m tcp --tcp-flags SYN,FIN SYN,FIN -j DROP
## Allows all loopback (lo0) traffic and reject all traffic to 127/8 that doesn't use lo0
iptables -A INPUT -i lo -j ACCEPT
iptables -A INPUT ! -i lo -d 127.0.0.0/8 -j REJECT
## Allow established connections
iptables -A INPUT -m conntrack --ctstate INVALID -j DROP
iptables -A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
iptables -A FORWARD -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
## Enable routing.
echo 1 > /proc/sys/net/ipv4/ip_forward
## Enable routing permanently
sysctl -w net.ipv4.ip_forward=1
## Ping with rate limit
iptables -A INPUT -p icmp -m limit --limit 1/sec --limit-burst 1 -j ACCEPT
## SSH
ssh="192.168.1.15,192.168.1.20"
iptables -A INPUT -p tcp --dport 22 -m conntrack --ctstate NEW -i enp3s0 -s "$ssh" -j ACCEPT
Links
https://www.booleanworld.com/depth-guide-iptables-linux-firewall/