无法理解Docker的iptables规则

4
当使用Docker时,我们首先需要一个镜像。我使用Docker创建了一个容器。
docker run --name register -d -p 1180:5000 registry

您可以通过运行iptables-save命令列出iptables规则:

# Generated by iptables-save v1.4.21 on Mon Oct 16 14:01:03 2017
*nat
:PREROUTING ACCEPT [129:14002]
:INPUT ACCEPT [129:14002]
:OUTPUT ACCEPT [25:1792]
:POSTROUTING ACCEPT [25:1792]
:DOCKER - [0:0]
-A PREROUTING -m addrtype --dst-type LOCAL -j DOCKER
-A OUTPUT ! -d 127.0.0.0/8 -m addrtype --dst-type LOCAL -j DOCKER
-A POSTROUTING -s 172.17.0.0/16 ! -o docker0 -j MASQUERADE
-A POSTROUTING -s 172.17.0.2/32 -d 172.17.0.2/32 -p tcp -m tcp --dport 5000 -j MASQUERADE
-A DOCKER -i docker0 -j RETURN
-A DOCKER ! -i docker0 -p tcp -m tcp --dport 1180 -j DNAT --to-destination 172.17.0.2:5000
COMMIT
# Completed on Mon Oct 16 14:01:03 2017
# Generated by iptables-save v1.4.21 on Mon Oct 16 14:01:03 2017
*filter
:INPUT ACCEPT [2721358:1990060388]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [2726902:1992988803]
:DOCKER - [0:0]
:DOCKER-ISOLATION - [0:0]
-A FORWARD -j DOCKER-ISOLATION
-A FORWARD -o docker0 -j DOCKER
-A FORWARD -o docker0 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A FORWARD -i docker0 ! -o docker0 -j ACCEPT
-A FORWARD -i docker0 -o docker0 -j ACCEPT
-A DOCKER -d 172.17.0.2/32 ! -i docker0 -o docker0 -p tcp -m tcp --dport 5000 -j ACCEPT
-A DOCKER-ISOLATION -j RETURN
COMMIT
# Completed on Mon Oct 16 14:01:03 2017

我不理解这个规则。

-A POSTROUTING -s 172.17.0.2/32 -d 172.17.0.2/32 -p tcp -m tcp --dport 5000 -j MASQUERADE

这可能是一个适合 https://unix.stackexchange.com 的问题。 - Matt
2个回答

3
最好的猜测是该规则用于修复一个边缘情况,当您的iptables POSTROUTING表默认为DENY时,任何不符合规则的数据包都会被拒绝,这允许容器通过映射端口连接到自身。在正常操作中,规则不起实际作用。
我认为这可能是拉取请求(#7003)添加MASQ规则的原因,但没有说明为什么要添加它。提交被标记为"为pkg/iptables创建测试"。这项工作主要是围绕修复在具有默认DENY表的发行版上的Docker问题。 问题#12632中有一种建议,即除非关闭用户端口映射代理,否则不会触及该规则。

似乎比我的答案更精确。+1 - VonC

1
这在 "将容器端口绑定到主机" 中有说明。
默认情况下,Docker容器可以与外部世界建立连接,但外部世界无法连接到容器。每个外向连接似乎来自于主机的一个IP地址,这归功于Docker服务器启动时在主机上创建的iptables伪装规则。
$ sudo iptables -t nat -L -n

...
Chain POSTROUTING (policy ACCEPT)
target     prot opt source               destination
MASQUERADE  all  --  172.17.0.0/16       0.0.0.0/0
...

Docker服务器创建伪装规则,使容器可以连接外部世界的IP地址。
您可以在此线程中看到当这些规则没有生成时会发生什么。(它们需要恢复
您可以在“构建自己的桥接”中学习相同的选项。

问题中的规则有些不同,出站连接的标准MASQUERADE规则在ops输出中是上面的规则。这个规则特别针对容器连接到自身,在端口映射的目标端口上。我不确定为什么要在那里使用MASQ规则,除非它想改变这些连接的源IP。显然,只有当关闭用户空间代理时才会触发它。 - Matt
@Matt感谢您参考moby issue 33726。我也不确定。 - VonC
@Matt 好的,我会关注并查看是否有新的回答。 - VonC
我认为那个规则是无用的,即使它被触发了。我相信MASQ会选择出站接口IP作为新的源地址,而这已经是源地址了。 - Matt

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接