当使用“-p <端口>:<端口>”时,Docker忽略iptable规则

就在几天前才意识到,Docker似乎绕过了我的iptable规则。 对于Docker和iptables,我并不是很难过。 过去几天尝试了很多不同的东西。 也看到,最近的docker版本有一个特殊的DOCKER链,应该允许我这样做有很大的变化。 但不知道我做错了什么,但它从来没有做我期望的事情。

所以我想要的很简单。 我希望它的行为像预期的一样。 如果我有一个接受规则,如果没有,它会被阻止。

我的iptable原本是这样的(所以在我的许多不成功的尝试之前):

*filter :INPUT ACCEPT [0:0] :FORWARD ACCEPT [0:0] :OUTPUT ACCEPT [779:162776] -A INPUT -i lo -j ACCEPT -A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT -A INPUT -p tcp -m tcp --dport 22 -j ACCEPT -A INPUT -p tcp -m tcp --dport 80 -j ACCEPT -A INPUT -s 1.2.3.4 -p tcp -m tcp --dport 123 -j ACCEPT -A INPUT -j DROP COMMIT 

希望它正是我想要的。 只要允许访问端口22和80,并允许来自IP 1.2.3.4的端口123。 但是,如果我创build一个“-p 123:123”的容器,每个人都可以访问它。 任何人都可以帮助我,告诉我如何改变上述文件?

谢谢!

Docker-Version:1.6.2

编辑:

最初留下我不同的尝试,不要过分复杂的问题。 但是,至less添加其中一个可能会有所帮助。

 *nat :PREROUTING ACCEPT [319:17164] :INPUT ACCEPT [8:436] :OUTPUT ACCEPT [0:0] :POSTROUTING ACCEPT [16:960] :DOCKER - [0:0] COMMIT *filter :INPUT ACCEPT [0:0] :FORWARD ACCEPT [0:0] :OUTPUT ACCEPT [779:162776] :DOCKER - [0:0] -A INPUT -i lo -j ACCEPT -A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT -A INPUT -p tcp -m tcp --dport 22 -j ACCEPT -A INPUT -p tcp -m tcp --dport 80 -j ACCEPT -A DOCKER -s 1.2.3.4 -p tcp -m tcp --dport 123 -j ACCEPT -A DOCKER -j DROP -A INPUT -j DROP COMMIT 

以上种类的作品。 然而,那么很多其他问题。 例如,我是否遇到容器链接问题,DNS不再工作,等等。 所以最后join了很多额外的规则来解决这个问题,但是我从来没有进入正确运行的状态。 所以我想最好有更好,更容易的解决scheme。

解:

结束了或多或less正确的说法。 只是没有把它添加到FORWARD链,我把它添加到DOCKER链而不是。 FORWARD链的问题在于Docker在第一个位置重启时添加了它的东西。 这导致我的规则被推下来,没有任何效果。 但是对于DOCKER链来说,Docker看起来似乎只附加了额外的规则,所以我保持有效。 所以,当我保存我的规则,然后重新启动服务器,一切仍然正常工作。

所以现在看起来或多或less是这样的:

 *filter :INPUT ACCEPT [0:0] :FORWARD ACCEPT [0:0] :OUTPUT ACCEPT [779:162776] :DOCKER - [0:0] # That I can access from IP 1.2.3.4 -A DOCKER -s 1.2.3.4/32 -p tcp -m tcp --dport 123 -j ACCEPT # That I can access from other Docker containers -A DOCKER -o docker0 -p tcp -m tcp --dport 123 -j ACCEPT # Does not allow it for anything else -A DOCKER -p tcp --dport 123 -j DROP -A INPUT -i lo -j ACCEPT -A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT -A INPUT -p tcp -m tcp --dport 22 -j ACCEPT -A INPUT -p tcp -m tcp --dport 80 -j ACCEPT -A INPUT -j DROP COMMIT 

你的iptablesconfiguration现在看起来有点坏,就好像你在不重新启动Docker的情况下清除了它。 例如,在filter表和nat表中都有一个DOCKER链,但没有引用它的规则,因此放置在该链中的规则将不会产生任何影响。

一般来说,如果你想实现影响Docker容器的iptables规则,他们需要进入filter table. Each container has it's *own* ip address, which means that your host is simply accepting packets and thenFORWARDfilter table. Each container has it's *own* ip address, which means that your host is simply accepting packets and then filter table. Each container has it's *own* ip address, which means that your host is simply accepting packets and then将它们filter table. Each container has it's *own* ip address, which means that your host is simply accepting packets and then到容器地址。

INPUT链中的规则仅适用于主机全局networking命名空间中接口上具有最终目标地址的数据包。

但是,我不确定iptables实际上是你的问题。

如果您尝试在容器中公开服务以使其他系统可用,则需要使用-p标志将这些端口发布到docker run 。 你可以在文档的这一部分 (Dockumentation?)阅读更多的内容。

如果你想用你正在努力完成的具体事例来更新你的问题,我可以提供一个更有针对性的答案。

更新

确实,当你使用-p发布一个容器端口时,它通常可以被任何源IP地址使用。 为了限制对已发布端口的访问,您需要将新规则添加到FORWARD链中。 例如,如果我启动一个Web服务器:

 docker run --name web -p 80:8080 larsks/mini-httpd 

容器中的Web服务器现在可以在我的主机上的端口8080上使用。 如果我想阻止对这个端口的访问,我需要在FORWARD链中插入一个规则来阻止访问容器ip上的端口80。 所以首先我需要容器的IP地址:

 $ web_ip=$(docker inspect --format '{{ .NetworkSettings.IPAddress }}' web) $ echo $web_ip 172.17.0.5 

我在FORWARD链创build的规则需要 docker创build的规则之前 ,所以我需要指定一个明确的位置:

 iptables -I FORWARD 1 -d $web_ip -p tcp --dport 80 \ \! -s 192.168.1.10 -j DROP 

这将阻止来自192.168.1.10以外的主机的所有通信。

如果你想要一个规则适用于所有的容器,而不是一个特定的容器,你可以将它绑定到docker0接口而不是一个特定的ip地址:

 -A FORWARD -o docker0 -p tcp --dport 80 \ \! -s 192.168.1.10 -j DROP 

这将禁止访问任何容器上的端口80。

我不是iptables的专家,但是我知道,如果你使用-p 127.0.0.1:123:123运行容器,那么端口将不会暴露在所有接口上,只是在环回上。

结束了或多或less正确的说法。 只是没有把它添加到FORWARD链,我把它添加到DOCKER链。

我在文档中find了相同的内容: https : //docs.docker.com/v1.5/articles/networking/#the-world

Docker不会删除或修改DOCKERfilter链中的任何预先存在的规则。 这允许用户预先创build 任何需要进一步限制访问容器的规则。

Docker的转发规则默认允许所有外部源IP。 要仅允许特定的IP或networking访问容器 ,请在DOCKERfilter链的顶部插入否定规则。 例如,要限制外部访问,只有源IP地址8.8.8.8才能访问容器,可以添加以下规则:

 $ iptables -I DOCKER -i ext_if ! -s 8.8.8.8 -j DROP