创建自定义 iptables 链

来自:How to create iptables firewall using custom chains

使用自定义链创建iptables防火墙,该自定义链将用于控制传入和传出流量。

创建iptables防火墙,该防火墙将允许已建立的连接,给定源地址的传入ssh,传出icmpntpdnssshhttphttps

# Flush rules and delete custom chains
iptables -F
iptables -X

# Define chain to allow particular source addresses
iptables -N chain-incoming-ssh
iptables -A chain-incoming-ssh -s 192.168.1.148 -j ACCEPT
iptables -A chain-incoming-ssh -s 192.168.1.149 -j ACCEPT
iptables -A chain-incoming-ssh -j DROP

# Define chain to allow particular services
iptables -N chain-outgoing-services
iptables -A chain-outgoing-services -p tcp --dport 53  -j ACCEPT
iptables -A chain-outgoing-services -p udp --dport 53  -j ACCEPT
iptables -A chain-outgoing-services -p tcp --dport 123 -j ACCEPT
iptables -A chain-outgoing-services -p udp --dport 123 -j ACCEPT
iptables -A chain-outgoing-services -p tcp --dport 80  -j ACCEPT
iptables -A chain-outgoing-services -p tcp --dport 443 -j ACCEPT
iptables -A chain-outgoing-services -p tcp --dport 22  -j ACCEPT
iptables -A chain-outgoing-services -p icmp            -j ACCEPT
iptables -A chain-outgoing-services -j DROP

# Define chain to allow established connections
iptables -N chain-states
iptables -A chain-states -p tcp  -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
iptables -A chain-states -p udp  -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
iptables -A chain-states -p icmp -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
iptables -A chain-states -j RETURN

# Drop invalid packets
iptables -A INPUT -m conntrack --ctstate INVALID -j DROP

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

# Accept incoming/outgoing packets for established connections
iptables -A INPUT  -j chain-states
iptables -A OUTPUT -j chain-states

# Accept incoming ICMP
iptables -A INPUT -p icmp -j ACCEPT

# Accept incoming SSH
iptables -A INPUT -p tcp --dport 22 -j chain-incoming-ssh

# Accept outgoing 
iptables -A OUTPUT -j chain-outgoing-services

## Drop everything else
iptables -P INPUT   DROP
iptables -P FORWARD DROP
iptables -P OUTPUT  DROP

列出所有防火墙规则,以验证是否按需应用了执行的命令。

$ sudo iptables -L -v -n

Chain INPUT (policy DROP 2 packets, 92 bytes)
 pkts bytes target              prot opt in     out     source               destination         
    0     0 DROP                all  --  *      *       0.0.0.0/0            0.0.0.0/0            ctstate INVALID
    1    29 ACCEPT              all  --  lo     *       0.0.0.0/0            0.0.0.0/0           
  190 15639 chain-states        all  --  *      *       0.0.0.0/0            0.0.0.0/0           
    0     0 ACCEPT              icmp --  *      *       0.0.0.0/0            0.0.0.0/0           
    1    60 chain-incoming-ssh  tcp  --  *      *       0.0.0.0/0            0.0.0.0/0            tcp dpt:22

Chain FORWARD (policy DROP 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         

Chain OUTPUT (policy DROP 0 packets, 0 bytes)
 pkts bytes target        prot opt in     out     source               destination         
    1    29 ACCEPT        all  --  *      lo      0.0.0.0/0            0.0.0.0/0           
  150 39893 chain-states  all  --  *      *       0.0.0.0/0            0.0.0.0/0           
    1    62 chain-outgoing-services  all  --  *      *       0.0.0.0/0            0.0.0.0/0           

Chain chain-incoming-ssh (1 references)
 pkts bytes target     prot opt in     out     source               destination         
    0     0 ACCEPT     all  --  *      *       192.168.1.148        0.0.0.0/0           
    1    60 ACCEPT     all  --  *      *       192.168.1.149        0.0.0.0/0           
    0     0 DROP       all  --  *      *       0.0.0.0/0            0.0.0.0/0           

Chain chain-outgoing-services (1 references)
 pkts bytes target     prot opt in     out     source               destination         
    0     0 ACCEPT     tcp  --  *      *       0.0.0.0/0            0.0.0.0/0            tcp dpt:53
    1    62 ACCEPT     udp  --  *      *       0.0.0.0/0            0.0.0.0/0            udp dpt:53
    0     0 ACCEPT     tcp  --  *      *       0.0.0.0/0            0.0.0.0/0            tcp dpt:123
    0     0 ACCEPT     udp  --  *      *       0.0.0.0/0            0.0.0.0/0            udp dpt:123
    0     0 ACCEPT     tcp  --  *      *       0.0.0.0/0            0.0.0.0/0            tcp dpt:80
    0     0 ACCEPT     tcp  --  *      *       0.0.0.0/0            0.0.0.0/0            tcp dpt:443
    0     0 ACCEPT     tcp  --  *      *       0.0.0.0/0            0.0.0.0/0            tcp dpt:22
    0     0 ACCEPT     icmp --  *      *       0.0.0.0/0            0.0.0.0/0           
    0     0 DROP       all  --  *      *       0.0.0.0/0            0.0.0.0/0           

Chain chain-states (2 references)
 pkts bytes target     prot opt in     out     source               destination         
  335 55240 ACCEPT     tcp  --  *      *       0.0.0.0/0            0.0.0.0/0            ctstate RELATED,ESTABLISHED
    1    78 ACCEPT     udp  --  *      *       0.0.0.0/0            0.0.0.0/0            ctstate RELATED,ESTABLISHED
    0     0 ACCEPT     icmp --  *      *       0.0.0.0/0            0.0.0.0/0            ctstate RELATED,ESTABLISHED
    4   214 RETURN     all  --  *      *       0.0.0.0/0            0.0.0.0/0           

我已经使用了RETURNtarget,chain-states因此数据包将继续通过防火墙。

编辑地址清单

在源地址列表中列出防火墙规则。

$ sudo iptables -n --list chain-incoming-ssh --line-numbers

Chain chain-incoming-ssh (1 references)
num  target     prot opt source               destination         
1    ACCEPT     all  --  192.168.1.148        0.0.0.0/0           
2    ACCEPT     all  --  192.168.1.149        0.0.0.0/0           
3    DROP       all  --  0.0.0.0/0            0.0.0.0/0           

删除第一个条目。

$ sudo iptables -D chain-incoming-ssh  1

在链的开头添加新规则。

$ sudo iptables -I chain-incoming-ssh 1 -s 192.168.1.140 -j ACCEPT 

在上一个条目之前添加一个新规则。

$ sudo iptables -I chain-incoming-ssh 3 -s 192.168.1.150 -j ACCEPT 

在源地址列表中列出防火墙规则。

$ sudo iptables -n --list chain-incoming-ssh --line-numbers
Chain chain-incoming-ssh (1 references)
num  target     prot opt source               destination         
1    ACCEPT     all  --  192.168.1.140        0.0.0.0/0           
2    ACCEPT     all  --  192.168.1.149        0.0.0.0/0           
3    ACCEPT     all  --  192.168.1.150        0.0.0.0/0           
4    DROP       all  --  0.0.0.0/0            0.0.0.0/0           

补充说明

您可以使用以下命令检查特定的链条。

$ sudo iptables -n --list chain-outgoing-services

Chain chain-outgoing-services (1 references)
target     prot opt source               destination         
ACCEPT     tcp  --  0.0.0.0/0            0.0.0.0/0            tcp dpt:53
ACCEPT     udp  --  0.0.0.0/0            0.0.0.0/0            udp dpt:53
ACCEPT     tcp  --  0.0.0.0/0            0.0.0.0/0            tcp dpt:123
ACCEPT     udp  --  0.0.0.0/0            0.0.0.0/0            udp dpt:123
ACCEPT     tcp  --  0.0.0.0/0            0.0.0.0/0            tcp dpt:80
ACCEPT     tcp  --  0.0.0.0/0            0.0.0.0/0            tcp dpt:443
ACCEPT     tcp  --  0.0.0.0/0            0.0.0.0/0            tcp dpt:22
ACCEPT     icmp --  0.0.0.0/0            0.0.0.0/0           
DROP       all  --  0.0.0.0/0            0.0.0.0/0  

您还可以在shell脚本中使用它根据其存在来执行不同的操作。

iptables --list chain-outgoing-services &>/dev/null
if [ "$?" -eq "0" ]; then
  iptables -F chain-outgoing-services
else
  iptables -N chain-outgoing-services
fi

我在国际AI开源组织LFAI当董事的200天 - 肖涵 善用 nsenter 命令,更好地 debug 容器网络