背景
在部署了docker容器的环境中,要在防火墙开通22端口,即ssh服务,以便在终端可以正常登陆。使用firewall-cmd在docker区域添加了22端口,但是没有起作用。后再public区域添加22端口才起作用。为什么docker区域不起作用,而public区域起作用呢?
分析
防护墙使用的是firewall管理的,使用下面的命令添加的规则:
firewall-cmd --add-service=ssh --zone=docker
firewall-cmd --reload
添加完后,查看:
firewall-cmd --list-service --zone=docker
结果已经有了ssh,表示添加成功。
但是尝试ssh登陆服务器时,还是不行。
通过iptables查看:
iptables -nL
看到这样一条:
这个链是IN_docker_allow。从这个名字可以推测是INPUT链的子链。从docker可以推测出这是firewall的docker区的规则。最后的allow表示允许。这个说明刚才使用firewall添加的规则是生效了的。但是就是无法ssh登陆。
查看当前使用的区:
firewall-cmd --get-active-zone
结果为:
是我们指定的zone=docker区,那到底是哪里出问题了呢?
为了验证问题,我在zone=public中加了同样的规则:
这个时候就可以ssh登陆了。
现在来分析一下iptables的规则链。
从INPUT开始,找到了INPUT_ZONES为入口的子链。
INPUT_ZONES下有IN_docker和IN_public。按理说IN_docker在前,优先级高,所以在IN_docker上加规则是可以生效的。实际上却是后面的IN_public规则生效了。
通过 iptables -nL查看到的规则里,其实并没有看到网卡的信息。所以,我换了一种方法查询:
iptables -S INPUT_ZONES
结果:
从原始的规则里可以看出,IN_docker绑定了docker0和br-开头的虚拟网桥,而IN_public没有绑定即默认绑定的是eth0。前面之所以看到有两个IN_docker,是因为这里绑定了两个虚拟网桥。
所以ssh到宿主机,经过的是eth0,而不是走虚拟网桥,所以IN_docker规则是不会匹配的,ssh到宿主机需要在IN_public里添加规则,也就是firewall的public区添加规则。如果要ssh到容器中,则需要在对应的虚拟网桥添加。不过因为docker区域已经绑定了两个虚拟网桥,所以只要在docker区中添加规则即可。
总结
firewall管理的防火墙规则虽然复杂,但是也不过就是将区域和网卡进行了绑定,然后再建立一系列的子链进行关联。如果发现规则无效,则需要直接查看原始的规则信息,以区分不同的网卡。
来源: http://www.yu7s.com/article/20240326175659891.html