Featured image of post Linux上nftables和Docker默认iptables规则冲突问题记录📝

Linux上nftables和Docker默认iptables规则冲突问题记录📝

由于docker上默认使用iptables,使用需要更换一下iptables的后端实现

最近把我的Hugo博客从原来的x86_64服务器的Docker上迁移到macOS的qemu虚拟机里面的Docker了,之前的服务器因为没有什么重要数据,一直没开防火墙,裸奔中,但是 现在我准备All-In-One了,把所有的服务都整合在qemu里面的虚拟化,现在要注意安全🔐了,但是我又不想使用iptables了,所以就改用更好用的nftables。

但是我启动docker容器的时候,oh吼~

1
2
~$ docker start hugo
Error response from daemon: driver failed programming external connectivity on endpoint hugo (5cf48cfcd4d592fc2fc599781dbfb98eb176f3841949c6a75ad97c56dd36be17): Unable to enable DNAT rule:  (iptables failed: iptables --wait -t nat -A DOCKER -p tcp -d 0/0 --dport 1313 -j DNAT --to-destination 172.17.0.2:1313 ! -i docker0: iptables: No chain/target/match by that name.

报错了。。。

iptables的规则不能生效,Nat&Forward 规则不生效。那怎么可能生效啊,iptables我已经不用了,改用nftables了。

然后问了一下哎GPT,它就说。哎~,Dockeriptables这两个锁死的,你要是想用Docker,那你要不然就放弃nftables,改回iptables,要不然,你就别用了,别的方法都很折腾,至少我觉得很麻烦。

然后还有一种方法就是转换一下,把iptables的规则转成nftables的后端实现,命令很简单,如下:

1
2
sudo update-alternatives --set iptables /usr/sbin/iptables-nft
sudo update-alternatives --set ip6tables /usr/sbin/ip6tables-nft

这样转换一下实现就可以正常启动docker容器了。

还有就是后续docker在开机启动时可能还会启动失败,这个没有关系的,重启一下docker,让他重新写一下iptables的规则就行了

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
sudo nft list ruleset#验证一下,看看是不是有自动生成的规则

... ...
# Warning: table ip filter is managed by iptables-nft, do not touch!
table ip filter {
        chain DOCKER {
                ip daddr 172.17.0.2 iifname != "docker0" oifname "docker0" tcp dport 1313 counter packets 0 bytes 0 accept
        }

        chain DOCKER-ISOLATION-STAGE-1 {
                iifname "docker0" oifname != "docker0" counter packets 0 bytes 0 jump DOCKER-ISOLATION-STAGE-2
                counter packets 0 bytes 0 return
        }

        chain DOCKER-ISOLATION-STAGE-2 {
                oifname "docker0" counter packets 0 bytes 0 drop
                counter packets 0 bytes 0 return
        }

        chain FORWARD {
                type filter hook forward priority filter; policy accept;
                counter packets 0 bytes 0 jump DOCKER-USER
                counter packets 0 bytes 0 jump DOCKER-ISOLATION-STAGE-1
                oifname "docker0" ct state related,established counter packets 0 bytes 0 accept
                oifname "docker0" counter packets 0 bytes 0 jump DOCKER
                iifname "docker0" oifname != "docker0" counter packets 0 bytes 0 accept
                iifname "docker0" oifname "docker0" counter packets 0 bytes 0 accept
        }

        chain DOCKER-USER {
                counter packets 0 bytes 0 return
        }
}