docker和iptables

举报
黄生 发表于 2022/09/24 15:35:27 2022/09/24
【摘要】 我们先建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进程来处理访问容器的流量。下图可以做个参考

image.png

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

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。