Docker与iptables:网络隔离与防火墙配置指南
编辑Docker网络隔离基础
在Linux系统上,Docker使用iptables
和ip6tables
规则来实现网络隔离、端口发布和过滤功能。
重要提示:
这些规则是Docker桥接网络正常运行所必需的,不应修改Docker创建的规则
如果Docker主机暴露在互联网上,应该添加iptables策略来防止对容器或主机上其他服务的未授权访问
Docker仅为桥接网络创建iptables规则,不会为ipvlan、macvlan或主机网络创建规则
Docker的iptables链结构
在filter表中,Docker将默认策略设置为DROP,并创建以下自定义iptables链:
DOCKER-USER:用户定义规则的占位符,会在DOCKER-FORWARD和DOCKER链之前处理
DOCKER-FORWARD:Docker网络处理的第一阶段
DOCKER:决定是否应接受非已建立连接的包
DOCKER-ISOLATION-STAGE-1/2:隔离不同Docker网络的规则
DOCKER-INGRESS:与Swarm网络相关的规则
在FORWARD链中,Docker添加无条件跳转到DOCKER-USER、DOCKER-FORWARD和DOCKER-INGRESS链的规则。
在nat表中,Docker创建DOCKER链并添加规则来实现伪装和端口映射。
在Docker规则前添加iptables策略
要过滤这些数据包,应在DOCKER-USER链中添加额外规则,因为:
被这些自定义链接受或拒绝的数据包不会被附加到FORWARD链的用户定义规则看到
附加到FORWARD链的规则会在Docker规则之后处理
匹配原始IP和端口
当数据包到达DOCKER-USER链时,它们已经通过了目标网络地址转换(DNAT)过滤器。这意味着iptables标志只能匹配容器的内部IP地址和端口。
如果要基于网络请求中的原始IP和端口匹配流量,必须使用conntrack iptables扩展:
sudo iptables -I DOCKER-USER -p tcp -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
sudo iptables -I DOCKER-USER -p tcp -m conntrack --ctorigdst 198.51.100.2 --ctorigdstport 80 -j ACCEPT
注意:使用conntrack扩展可能会导致性能下降。
端口发布与映射
默认情况下,守护程序会阻止访问未发布的端口。发布的容器端口会映射到主机IP地址,Docker使用iptables执行:
网络地址转换(NAT)
端口地址转换(PAT)
伪装
例如,docker run -p 8080:80 [...]
会在Docker主机的任何地址上的8080端口与容器的80端口之间创建映射。
限制容器外部连接
默认情况下,允许所有外部源IP连接到已发布到Docker主机地址的端口。
要限制访问,可在DOCKER-USER过滤器链顶部插入否定规则:
只允许特定IP(192.0.2.2)访问:
iptables -I DOCKER-USER -i ext_if ! -s 192.0.2.2 -j DROP
只允许子网(192.0.2.0/24)访问:
iptables -I DOCKER-USER -i ext_if ! -s 192.0.2.0/24 -j DROP
使用IP范围:
iptables -I DOCKER-USER -m iprange -i ext_if ! --src-range 192.0.2.1-192.0.2.3 -j DROP
直接路由
端口映射确保发布的端口可在主机的网络地址上访问。但特别是对于IPv6,您可能希望避免使用NAT,而是为容器地址设置外部路由("直接路由")。
要从Docker主机外部访问桥接网络上的容器,必须通过Docker主机上的地址设置到桥接网络的路由。
网关模式
桥接网络驱动程序有以下选项:
com.docker.network.bridge.gateway_mode_ipv6
com.docker.network.bridge.gateway_mode_ipv4
每种模式可设置为以下之一:
nat
(默认):为每个发布的容器端口设置NAT和伪装规则nat-unprotected
:未发布的容器端口也可通过直接路由访问routed
:不设置NAT或伪装规则,但iptables仍设置为仅可访问发布的容器端口isolated
:只能与--internal
标志一起使用
设置容器默认绑定地址
默认情况下,当映射容器端口而未指定特定主机地址时,Docker守护程序会将发布的容器端口绑定到所有主机地址(0.0.0.0和[::])。
要更改默认绑定地址,可以配置守护程序使用环回地址(127.0.0.1):
docker network create mybridge -o "com.docker.network.bridge.host_binding_ipv4=127.0.0.1"
对于默认桥接网络,在daemon.json中配置:
{
"ip": "127.0.0.1"
}
路由器上的Docker
在Linux上,Docker需要主机启用"IP转发"。因此,如果未启用,它会在启动时启用net.ipv4.ip_forward
和net.ipv6.conf.all.forwarding
sysctl设置。
要防止Docker将FORWARD链的策略设置为DROP,可以在/etc/docker/daemon.json
中包含"ip-forward-no-drop": true
,或者向dockerd命令行添加--ip-forward-no-drop
选项。
防止Docker操作iptables
可以将daemon配置中的iptables或ip6tables键设置为false,但此选项不适合大多数用户,因为它可能会破坏Docker引擎的容器网络。
与firewalld集成
如果在iptables选项设置为true的情况下运行Docker,并且系统上启用了firewalld,Docker会自动创建一个名为docker的firewalld区域,目标为ACCEPT。
Docker与ufw
Uncomplicated Firewall(ufw)是Debian和Ubuntu附带的前端,可让您管理防火墙规则。Docker和ufw以不兼容的方式使用iptables。
当您使用Docker发布容器端口时,进出该容器的流量会在通过ufw防火墙设置之前被转移。
- 0
- 0
-
分享