问题
昨天在新买的一台VPS上配置QD框架,采用的是基于Docker的容器化部署,发现了一个问题:本机的Docker关闭iptables
的情况下,容器内部无网络连接,为此排查了半天,结果发现在iptables
启用时容器内部就能正常访问网络。
探索
经过一番搜索,得出了以下结论:
Docker和UFW都是基于
iptables
操作的,两共存会存在问题QD框架默认是通过是通过iptables 转发的,在禁用掉
iptables
后网络必须通过 Host 网络模式创建容器
禁用 Docker 的 iptables
功能,也意味着放弃了 docker 的网络管理功能,很典型的现象就是容器将无法访问外部网络。因此尽量在开启iptables
的情况下,去修改UFW的规则来实现共存是最佳选择,毕竟我们无法左右镜像打包者的想法
解决方法
修改 UFW 的配置文件 /etc/ufw/after.rules
,在最后添加上如下规则:
# BEGIN UFW AND DOCKER
*filter
:ufw-user-forward - [0:0]
:ufw-docker-logging-deny - [0:0]
:DOCKER-USER - [0:0]
-A DOCKER-USER -j ufw-user-forward
-A DOCKER-USER -j RETURN -s 10.0.0.0/8
-A DOCKER-USER -j RETURN -s 172.16.0.0/12
-A DOCKER-USER -j RETURN -s 192.168.0.0/16
-A DOCKER-USER -p udp -m udp --sport 53 --dport 1024:65535 -j RETURN
-A DOCKER-USER -j ufw-docker-logging-deny -p tcp -m tcp --tcp-flags FIN,SYN,RST,ACK SYN -d 192.168.0.0/16
-A DOCKER-USER -j ufw-docker-logging-deny -p tcp -m tcp --tcp-flags FIN,SYN,RST,ACK SYN -d 10.0.0.0/8
-A DOCKER-USER -j ufw-docker-logging-deny -p tcp -m tcp --tcp-flags FIN,SYN,RST,ACK SYN -d 172.16.0.0/12
-A DOCKER-USER -j ufw-docker-logging-deny -p udp -m udp --dport 0:32767 -d 192.168.0.0/16
-A DOCKER-USER -j ufw-docker-logging-deny -p udp -m udp --dport 0:32767 -d 10.0.0.0/8
-A DOCKER-USER -j ufw-docker-logging-deny -p udp -m udp --dport 0:32767 -d 172.16.0.0/12
-A DOCKER-USER -j RETURN
-A ufw-docker-logging-deny -m limit --limit 3/min --limit-burst 10 -j LOG --log-prefix "[UFW DOCKER BLOCK] "
-A ufw-docker-logging-deny -j DROP
COMMIT
# END UFW AND DOCKER
重启 UFWsudo systemctl restart ufw
或者重启服务器即可生效
如果希望允许外部网络访问 Docker 容器提供的服务,比如有一个容器的服务端口是 80
。那就可以用以下命令来允许外部网络访问这个服务:
ufw route allow proto tcp from any to any port 80
请注意,这个端口
80
是容器的端口,而非使用-p 0.0.0.0:8080:80
选项发布在服务器上的8080
端口
如果有多个容器的服务端口为 80,但只希望外部网络访问某个特定的容器。比如该容器的私有地址为 172.17.0.2
,就用类似下面的命令:
ufw route allow proto tcp from any to 172.17.0.2 port 80
如果一个容器的服务是 UDP 协议,假如是 DNS 服务,可以用下面的命令来允许外部网络访问所有发布出来的 DNS 服务:
ufw route allow proto udp from any to any port 53
同样的,如果只针对一个特定的容器,比如 IP 地址为 172.17.0.2
:
ufw route allow proto udp from any to 172.17.0.2 port 53