警惕docker本身iptables规则对网络的影响
警惕1:k8s环境下,独立拉取docker容器时,进行端口映射会有问题
场景:
在k8s节点由于某种原因,比如:需要拉起一个docker环境来制作镜像,需要拉起一些不由k8s管理的容器,这些容器需要有网络通信,但是在通信时出现网络不通,比如:将容器的80端口映射到8080去对外暴露,但是实际不通
原因:
在k8s环境下,kube-proxy会下发iptables规则来管理网络流量,此时我们启动docker daemon时,一般会禁止docker下发iptables规则,以避免互相影响,但是此时在k8s外直接拉起容器时,容器需要进行网络通信,但是docker不会单独去下发这部分规则,比如:端口的nat规则,就会导致网络不通
典型的k8s环境下的docker配置: 设置禁止下发iptables规则,但开启ip-forward
{
“data-root”: “/data/kubernetes/docker”,
“bridge”: “none”,
“experimental”: true,
“debug”: false,
“ip-forward”: true,
“ip-masq”: false,
“iptables”: false,
“ipv6”: false,
“live-restore”: true,
“log-driver”: “json-file”,
“log-level”: “warn”,
“log-opts”: {
“max-file”: “10”,
“max-size”: “100m”
}
}
警惕2:默认环境下,docker的网络隔离规则可能会影响你的其它服务
场景: 默认安装了docker之后,机器上的一些网络代理服务,比如:vpn受到了影响
原因: docker本身默认对于forward链上有drop规则,由于隔离网络设备间的流量
这个其实是官方给出的已知问题,不算缺陷,是一种安全的权衡设计,
细节参考:docker-on-a-router
官方提示:
Docker also sets the policy for the FORWARD chain to DROP. If your Docker host also acts as a router, this will result in that router not forwarding any traffic anymore. If you want your system to continue functioning as a router, you can add explicit ACCEPT rules to the DOCKER-USER chain to allow it:
官方解决方法:
iptables -I DOCKER-USER -i src_if -o dst_if -j ACCEPT
docker bridge隔离分析:
docker下发的默认iptables如下:
iptables -N DOCKER
iptables -N DOCKER-ISOLATION-STAGE-1
iptables -N DOCKER-ISOLATION-STAGE-2
iptables -N DOCKER-USER
iptables -A FORWARD -j DOCKER-USER
iptables -A FORWARD -j DOCKER-ISOLATION-STAGE-1
iptables -A FORWARD -o docker0 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
iptables -A FORWARD -o docker0 -j DOCKER
iptables -A FORWARD -i docker0 ! -o docker0 -j ACCEPT
iptables -A FORWARD -i docker0 -o docker0 -j ACCEPT
iptables -A DOCKER-ISOLATION-STAGE-1 -i docker0 ! -o docker0 -j DOCKER-ISOLATION-STAGE-2
iptables -A DOCKER-ISOLATION-STAGE-1 -j RETURN
iptables -A DOCKER-ISOLATION-STAGE-2 -o docker0 -j DROP
iptables -A DOCKER-ISOLATION-STAGE-2 -j RETURN
iptables -A DOCKER-USER -j RETURN
其中DOCKER-ISOLATION相关的是为了实现网络设备间的流量隔离:
为了隔离在不同的bridge网络之间的容器,Docker提供了两个DOCKER-ISOLATION阶段实现。
1、DOCKER-ISOLATION-STAGE-1作用分析:
相关规则:
-A FORWARD -j DOCKER-ISOLATION-STAGE-1
-A DOCKER-ISOLATION-STAGE-1 -i docker0 ! -o docker0 -j DOCKER-ISOLATION-STAGE-2
-A DOCKER-ISOLATION-STAGE-1 -j RETURN
分析:
-A FORWARD -j DOCKER-ISOLATION-STAGE-1:
表示所有经过FORWARD链转发的数据包都要经过DOCKER-ISOLATION-STAGE-1的过滤。
-A DOCKER-ISOLATION-STAGE-1 -i docker0 ! -o docker0 -j DOCKER-ISOLATION-STAGE-2:
表示源接口是docker0但是目标接口不是docker0的数据包进入DOCKER-ISOLATION-STAGE-2链中
进一步处理。
-A DOCKER-ISOLATION-STAGE-1 -j RETURN:
表示从DOCKER-ISOLATION-STAGE-1链中返回。
2、DOCKER-ISOLATION-STAGE-2作用分析:
相关规则:
-A DOCKER-ISOLATION-STAGE-2 -o docker0 -j DROP
-A DOCKER-ISOLATION-STAGE-2 -j RETURN
分析:
-A DOCKER-ISOLATION-STAGE-2 -o docker0 -j DROP表示如果数据包的目标接口是docker0,直接丢弃。
3、综合分析:
数据包从docker0上的容器发出,但是目的地址不是docker0上的其它容器,此时这样的流量如果要从docker0网桥发出则会被丢弃,实现了docker0网桥上的容器和其它网桥的容器的流量隔离
注意: 这里的规则里的-i和-o匹配的是指流量进出时通过的网桥设备
Docker的DOCKER-USER链:
Docker启动时,会加载DOCKER链和DOCKER-ISOLATION(现在是DOCKER-ISOLATION-STAGE-1)链中的过滤规则,并使之生效。绝对禁止修改这里的过滤规则。
如果用户要补充Docker的过滤规则,强烈建议追加到DOCKER-USER链。DOCKER-USER链中的过滤规则,将先于Docker默认创建的规则被加载,从而能够覆盖Docker在DOCKER链和DOCKER-ISOLATION链中的默认过滤规则。例如,Docker启动后,默认任何外部source IP都被允许转发,从而能够从该source IP连接到宿主机上的任何Docker容器实例。如果只允许一个指定的IP访问容器实例,可以插入路由规则到DOCKER-USER链中,从而能够在DOCKER链之前被加载。
Docker的DOCKER-USER链使用示例如下:
只允许192.168.1.1访问容器:
iptables -A DOCKER-USER -i docker0 ! -s 192.168.1.1 -j DROP
只允许192.168.1.0/24网段中的IP访问容器:
iptables -A DOCKER-USER -i docker0 ! -s 192.168.1.0/24 -j DROP
只允许192.168.1.1-192.168.1.3网段中的IP访问容器(需要借助于iprange模块):
iptables -A DOCKER-USER -m iprange -i docker0 ! --src-range 192.168.1.1-192.168.1.3 -j DROP