Docker和iptables
预计阅读时间:4分钟
在Linux上,Docker操纵iptables
规则以提供网络隔离。尽管这是实现的详细信息,并且您不应修改Docker在iptables
策略中插入的规则,但是如果您想要拥有自己的策略(而不是由Docker管理的策略),它确实会对您需要执行的操作产生一些影响。
如果您在暴露于Internet的主机上运行Docker,则可能需要适当的iptables策略,以防止未经授权访问您主机上运行的容器或其他服务。此页面描述了如何实现此目标以及需要注意的注意事项。
在Docker的规则之前添加iptables策略
Docker安装了两个名为DOCKER-USER
和的自定义iptables链DOCKER
,它确保始终由这两个链首先检查传入的数据包。
Docker的所有iptables
规则都已添加到DOCKER
链中。请勿手动操作此链条。如果您需要添加在Docker规则之前加载的规则,则将它们添加到DOCKER-USER
链中。在Docker自动创建任何规则之前,将应用这些规则。
在这些链之后,FORWARD
将评估添加到链中的规则(手动添加或通过另一个基于iptables的防火墙)。这意味着,如果您通过Docker公开端口,则无论防火墙配置了什么规则,该端口都会公开。如果您希望即使在通过Docker公开端口时也要应用这些规则,则必须将这些规则添加到
链中。DOCKER-USER
限制与Docker主机的连接
默认情况下,允许所有外部源IP连接到Docker主机。要仅允许特定的IP或网络访问容器,请在DOCKER-USER
过滤器链的顶部插入一个否定的规则。例如,以下规则限制从以下所有IP地址进行的外部访问192.168.1.1
:
$ iptables -I DOCKER-USER -i ext_if ! -s 192.168.1.1 -j DROP
请注意,您将需要更改ext_if
以与主机的实际外部接口相对应。您可以改为允许来自源子网的连接。以下规则仅允许从子网进行访问192.168.1.0/24
:
$ iptables -I DOCKER-USER -i ext_if ! -s 192.168.1.0/24 -j DROP
最后,您可以指定要接受的IP地址范围--src-range
(请记住-m iprange
在使用--src-range
或时也要添加--dst-range
):
$ iptables -I DOCKER-USER -m iprange -i ext_if ! --src-range 192.168.1.1-192.168.1.3 -j DROP
您可以结合使用-s
或--src-range
与-d
或--dst-range
一起控制源和目标。例如,如果Docker守护程序同时监听
192.168.1.99
和10.1.2.3
,则可以制定特定于10.1.2.3
并保持
192.168.1.99
打开的规则。
iptables
是复杂的,更复杂的规则超出了此主题的范围。有关
更多信息,请参见Netfilter.org HOWTO。
路由器上的Docker
Docker还将FORWARD
链的策略设置为DROP
。如果您的Docker主机也充当路由器,这将导致该路由器不再转发任何流量。如果希望系统继续充当路由器,则可以ACCEPT
向DOCKER-USER
链中添加明确的规则以允许它:
$ iptables -I DOCKER-USER -i src_if -o dst_if -j ACCEPT
防止Docker操作iptables
可以在Docker引擎的配置文件中将iptables
密钥设置false
为/etc/docker/daemon.json
,但是此选项不适用于大多数用户。完全阻止Docker创建iptables
规则是不可能的,事后创建规则非常复杂,超出了这些说明的范围。设置iptables
为false
很有可能会破坏Docker引擎的容器网络。
对于希望将Docker运行时构建到其他应用程序中的系统集成商,请探索moby
项目。
设置容器的默认绑定地址
默认情况下,Docker守护程序将公开0.0.0.0
地址上的端口,即主机上的任何地址。如果要更改该行为以仅公开内部IP地址上的端口,则可以使用该--ip
选项指定其他IP地址。但是,设置--ip
仅更改
默认值,它不会将服务限制为该IP。
与防火墙集成
如果您运行的Docker版本为20.10.0或更高版本,并且已在系统上启用Firewalld--iptables
,则Docker会自动创建一个firewalld
名为的区域docker
,并将其创建的所有网络接口(例如docker0
)插入该docker
区域,以实现无缝联网。
考虑运行以下firewalld
命令以从区域中删除docker接口。
# Please substitute the appropriate zone and docker interface
$ firewall-cmd --zone=trusted --remove-interface=docker0 --permanent
$ firewall-cmd --reload
重新启动dockerd
守护程序会将接口插入到docker
区域中。