docker下iptables的一点心得
docker默认是通过DOCKER链处理forward等规则,因此,系统的常规(input)链对它限制是无效的,简单说就是docker突破了iptables,docker开放的端口不受iptables的限制。(当然,仅仅是input链,但常规我们也只处理input)
我以前是简单的/etc/docker/daemon.json中禁用docker的iptables自动规则管理来解决问题,不过最近遇到一个情况,因为docker应用需要对访问者ip做dns反向解析,因此,禁用了iptables自动规则后,docker无法访问外网(缺乏相应的转发和nat规则),引起反向解析失败。解析失败没事,但一直要到超时错,就是整整60秒才能响应,这个就无法接受了。 * 以前似乎这么做没问题,就这次不行,而且是多台机器上都一样,不知道是不是docker升级了啥的。
既然不能简单关闭docker的iptables托管,那就只能是在系统的iptables层级上想办法了。
查了资料,docker提供了一个DOCKER-USER链,它是前置于docker的,因此,在它上面打主意就可以了。
下面的例子就是,允许特定ip(1.1.1.1)访问docker上的nginx的80端口,除此之外的所有docker端口的访问均被拒绝。(本机,即input不受影响)
root@xxxxxxxx:~# cat /etc/iptables/rules.v4
*filter
:INPUT DROP [0:0]
:FORWARD DROP [0:0]
:OUTPUT ACCEPT [1039:304535]
:DOCKER-USER DROP [0:0] #docker-user链,它运行于docker链之前,因此可过滤docker的流量。
#常规的规则(input链),根据情况自己写了。这里的话是开放22的访问。
-A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A INPUT -i lo -j ACCEPT
-A INPUT -p tcp -m tcp --dport 22 -j ACCEPT
#DOCK-USER链规则开始
-A DOCKER-USER -o eth0 -p tcp -j ACCEPT #允许docker的向外访问。 eth0需要改成外网网卡的实际名称。
-A DOCKER-USER -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT #允许已建立的连接继续通信
-A DOCKER-USER -i docker0 -o docker0 -j ACCEPT #允许各个docker间的通信
-A DOCKER-USER -i br-+ -o br-+ -j ACCEPT #允许各个docker间的通信
-A DOCKER-USER ! -i docker0 -s 1.1.1.1 -p tcp -m tcp --dport 80 -j ACCEPT #默认规则为禁止,所以这个是白名单,允许1.1.1.1访问本地的80端口。
.... 对外开放的服务规则一直加在这里就好了
-A DOCKER-USER ! -i docker0 -p tcp -m tcp -j DROP #禁止除白名单外的所有请求
COMMIT