docker和iptables
        【摘要】 我们先建1个自定义桥接网络,然后运行2个容器,连接到自定义桥接网络inetwork(而不是默认桥接网络、1个容器也可以连接到多个桥接网络),观察一下iptables的相关规则。默认桥接网络叫bridge,自定义的叫inetwork接口名称默认的是docker0,自定义的是br-xxxbr-b5a3f4778f2a: flags=4099<UP,BROADCAST,MULTICAST>  mt...
    
    
    
    我们先建1个自定义桥接网络,然后运行2个容器,连接到自定义桥接网络inetwork(而不是默认桥接网络、1个容器也可以连接到多个桥接网络),观察一下iptables的相关规则。
默认桥接网络叫bridge,自定义的叫inetwork
 接口名称默认的是docker0,自定义的是br-xxx
br-b5a3f4778f2a: flags=4099<UP,BROADCAST,MULTICAST>  mtu 1500
        inet 172.19.0.1  netmask 255.255.0.0  broadcast 172.19.255.255
        ether 02:42:a2:d5:85:76  txqueuelen 0  (Ethernet)
        RX packets 29  bytes 1695 (1.6 KiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 42  bytes 3724 (3.6 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
docker0: flags=4099<UP,BROADCAST,MULTICAST>  mtu 1500
        inet 172.17.0.1  netmask 255.255.0.0  broadcast 172.17.255.255
        inet6 fe80::42:5eff:fe8d:a3d2  prefixlen 64  scopeid 0x20<link>
        ether 02:42:5e:8d:a3:d2  txqueuelen 0  (Ethernet)
        RX packets 29  bytes 1695 (1.6 KiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 42  bytes 3724 (3.6 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
来看iptables的NAT规则:
 POSTROUTING是SNAT 让容器内去访问外部网络的
 PREROUTING是DNAT 让外部网络来的访问转换/映射到容器内
[root@ecs-d589 ~]# iptables -t nat -S
#Policy
-P PREROUTING ACCEPT
-P INPUT ACCEPT
-P POSTROUTING ACCEPT
-P OUTPUT ACCEPT
#建立一个自定义链
-N DOCKER
#下面这条自用的,与docker无关
-A PREROUTING -d 10.0.0.27/32 -i eth0 -p tcp -m tcp --dport 24 -j DNAT --to-destination 10.0.0.97:22
#使用-m addrtype模块,目的是本地网络的,用DOCKER链处理,只是做了框架,无实质处理
-A PREROUTING -m addrtype --dst-type LOCAL -j DOCKER
#下面2个规则是说,来自于容器内2个桥接网络内的数据包,要出去的,都做SNAT(源地址转换为出口网卡的IP)
#要出去,就是由! -o指定,即出口网卡接口不是br-xx和docker0
-A POSTROUTING -s 172.19.0.0/16 ! -o br-b5a3f4778f2a -j MASQUERADE
-A POSTROUTING -s 172.17.0.0/16 ! -o docker0 -j MASQUERADE
-A POSTROUTING -o eth0 -j MASQUERADE #这条自用的,与docker无关
#
-A OUTPUT ! -d 127.0.0.0/8 -m addrtype --dst-type LOCAL -j DOCKER
#自定义链DOCKER的规则 无实际处理
-A DOCKER -i br-b5a3f4778f2a -j RETURN
-A DOCKER -i docker0 -j RETURN
我们启动2个容器
docker run -d -i -p 1234:1234 --name daemon1 --network inetwork ubuntu:14.04 nc -l 1234
docker run -d -i -p 1235:1235 --name daemon2 --network inetwork ubuntu:14.04 nc -l 1235
再看一下规则
[root@ecs-d589 ~]# iptables -t nat -S
#不变的规则去掉了一些
-A PREROUTING -m addrtype --dst-type LOCAL -j DOCKER
-A POSTROUTING -s 172.19.0.0/16 ! -o br-b5a3f4778f2a -j MASQUERADE
-A POSTROUTING -s 172.17.0.0/16 ! -o docker0 -j MASQUERADE
#下面2条难以理解,原因就是source和dest一样,不过不理解不影响我们继续
-A POSTROUTING -s 172.19.0.2/32 -d 172.19.0.2/32 -p tcp -m tcp --dport 1234 -j MASQUERADE
-A POSTROUTING -s 172.19.0.3/32 -d 172.19.0.3/32 -p tcp -m tcp --dport 1235 -j MASQUERADE
-A OUTPUT ! -d 127.0.0.0/8 -m addrtype --dst-type LOCAL -j DOCKER
-A DOCKER -i br-b5a3f4778f2a -j RETURN
-A DOCKER -i docker0 -j RETURN
#做DNAT,将外来的数据包访问1234端口的,转到对应的容器内
-A DOCKER ! -i br-b5a3f4778f2a -p tcp -m tcp --dport 1234 -j DNAT --to-destination 172.19.0.2:1234
-A DOCKER ! -i br-b5a3f4778f2a -p tcp -m tcp --dport 1235 -j DNAT --to-destination 172.19.0.3:1235
[root@ecs-d589 ~]# route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
0.0.0.0         10.0.0.1        0.0.0.0         UG    100    0        0 eth0
10.0.0.0        0.0.0.0         255.255.255.0   U     100    0        0 eth0
169.254.169.254 10.0.0.254      255.255.255.255 UGH   100    0        0 eth0
172.17.0.0      0.0.0.0         255.255.0.0     U     0      0        0 docker0
172.19.0.0      0.0.0.0         255.255.0.0     U     0      0        0 br-b5a3f4778f2a
对于每一个映射的端口,都会启动一个docker-proxy进程来处理访问容器的流量。下图可以做个参考

docker port 可以查看容器的端口映射情况
启动docker后会添加iptables规则,停止docker服务后一些基本规则不会删除。重启机器后会还原为最初的样子
再看一下filter表,启动docker后
[root@ecs-d589 ~]# iptables -S
-P INPUT ACCEPT
-P FORWARD DROP  #默认是DROP!!!
-P OUTPUT ACCEPT
-N DOCKER
-N DOCKER-ISOLATION-STAGE-1 #STAGE1里会再跳转STAGE2
-N DOCKER-ISOLATION-STAGE-2
-N DOCKER-USER #只是框架 无实际规则
#好像就状态跟踪conntrack有点用处
-A FORWARD -j DOCKER-USER
-A FORWARD -j DOCKER-ISOLATION-STAGE-1
-A FORWARD -o docker0 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A FORWARD -o docker0 -j DOCKER
-A FORWARD -i docker0 ! -o docker0 -j ACCEPT
-A FORWARD -i docker0 -o docker0 -j ACCEPT
-A FORWARD -o br-b5a3f4778f2a -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A FORWARD -o br-b5a3f4778f2a -j DOCKER
-A FORWARD -i br-b5a3f4778f2a ! -o br-b5a3f4778f2a -j ACCEPT
-A FORWARD -i br-b5a3f4778f2a -o br-b5a3f4778f2a -j ACCEPT
-A DOCKER-ISOLATION-STAGE-1 -i docker0 ! -o docker0 -j DOCKER-ISOLATION-STAGE-2
-A DOCKER-ISOLATION-STAGE-1 -i br-b5a3f4778f2a ! -o br-b5a3f4778f2a -j DOCKER-ISOLATION-STAGE-2
-A DOCKER-ISOLATION-STAGE-1 -j RETURN
-A DOCKER-ISOLATION-STAGE-2 -o docker0 -j DROP
-A DOCKER-ISOLATION-STAGE-2 -o br-b5a3f4778f2a -j DROP
-A DOCKER-ISOLATION-STAGE-2 -j RETURN
-A DOCKER-USER -j RETURN
启动2个容器后
#添加了2条规则 外面网络来的到容器的访问,到达主机,PREROUTING后,路由,会走FORWARD,而不是INPUT本地处理
-A DOCKER -d 172.19.0.2/32 ! -i br-b5a3f4778f2a -o br-b5a3f4778f2a -p tcp -m tcp --dport 1234 -j ACCEPT
-A DOCKER -d 172.19.0.3/32 ! -i br-b5a3f4778f2a -o br-b5a3f4778f2a -p tcp -m tcp --dport 1235 -j ACCEPT
docker不会动mangle表
            【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱:
                cloudbbs@huaweicloud.com
                
            
        
        
        
        
        
        
        - 点赞
- 收藏
- 关注作者
 
             
           
评论(0)