几天前刚刚意识到Docker似乎绕过了我的iptable规则。我对Docker和iptables的体验并不令人难以置信。在最后的日子里尝试了很多不同的事情。还看到最近的docker版本有一个很大的变化,特殊的DOCKER链应该允许我这样做。但是不确定我做错了什么,但它永远不会做我期望它做的事。
所以我想要的很简单。我希望它表现得像预期的那样。如果我有一个ACCEPT-Rule要通过,如果没有它被阻止。
我的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。但是,如果我使用“-p 123:123”创建容器,则每个人都可以访问它。任何人都可以帮助我并告诉我如何更改上述文件?
谢谢!
Docker-Version:1.6.2
离开我最初的不同尝试不会使问题过于复杂。但是,添加其中至少一个可能会有所帮助。
*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不再工作,等等。因此,最后添加了许多额外的规则来解决这些问题,但我从未进入正常运行的状态。所以我想那里有更好更简单的解决方案。
完全或多或少地做了larsks所说的话。只是没有将它添加到FORWARD链中,我将其添加到DOCKER链中。 FORWARD链的问题在于Docker在第一个位置重新启动时会在其中添加它的东西。这导致我的规则被压低而没有任何影响。但是对于DOCKER链,似乎Docker只附加了额外的规则,因此我的工作仍然有效。因此,当我保存规则然后重新启动服务器时,一切仍然正常。
所以现在看起来或多或少是这样的:
*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
答案 0 :(得分:7)
我不是iptables的专家,但我知道如果你使用-p 127.0.0.1:123:123
运行容器,那么端口不会在所有接口上公开,只是在环回上。
答案 1 :(得分:4)
你的iptables配置现在看起来有点破,好像你在某些时候清除了它而没有重新启动Docker。例如,DOCKER
和filter
表中都有nat
链,但没有引用它的规则,因此放在该链中的规则不会产生任何影响。
通常,如果要实现影响Docker容器的iptables规则,则需要将它们放在FORWARD
表的filter
链中。每个容器都有自己的 IP地址,这意味着您的主机只是接受数据包,然后FORWARD
将它们添加到容器地址。
INPUT
链中的规则仅适用于主机全局网络命名空间中接口上具有地址的最终目的地的数据包。
但是,我不确定iptables实际上是你的问题。
如果您尝试在容器中公开服务以使其可供其他系统使用,则需要使用-p
标记将这些端口发布到docker run
。您可以阅读更多相关信息
在文档的this section中。
如果您想使用您要完成的具体示例来更新您的问题,我可以提供更具针对性的答案。
<强>更新强>
当您使用-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
链中创建的规则需要在 docker创建的规则之前,所以我需要指定一个明确的位置:
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。
答案 2 :(得分:2)
完全或多或少地做了larsks所说的话。只是没有添加 它转发到FORWARD链,我将它添加到DOCKER链中。
我在文档中发现了相同内容:https://docs.docker.com/v1.5/articles/networking/#the-world
Docker不会从中删除或修改任何预先存在的规则 DOCKER过滤链。此允许用户提前创建 进一步限制对容器的访问所需的规则。
Docker的转发规则默认允许所有外部源IP。 要 只允许特定的IP或网络访问容器,插入一个 否定了DOCKER过滤器链顶部的规则。例如,到 限制外部访问,以便只有源IP 8.8.8.8可以访问 容器,可以添加以下规则:
$ iptables -I DOCKER -i ext_if ! -s 8.8.8.8 -j DROP
答案 3 :(得分:1)
要在来自 docker 容器的已发布端口上使用 iptables,您需要综合考虑:
要使用这些,生成的 iptables 规则如下所示:
Select [Date].[1].[1].[2014], [Date].[1].[1].[2015], [Date].[1].[2].[2014], [Date].[1].[2].[2015]
这会处理对已发布端口 8080/tcp(在主机上,容器可能正在侦听 80 或任何其他端口)的请求,并且只接受来自 10.0.0.0/24 子网的请求。该子网之外的所有内容都将被丢弃。
请注意,DOCKER-USER 表有一个默认规则可以立即返回,因此所有更改都应在表中该默认规则之前插入。
答案 4 :(得分:0)
我需要从多个子网通过主机端口1234访问docker容器,并使用以下命令(Debian Stretch,docker 18.06):
iptables -I DOCKER-USER -p tcp --dport 1234 -j REJECT
iptables -I DOCKER-USER -s 18.204.0.0/16 -p tcp --dport 1234 -j RETURN
iptables -I DOCKER-USER -s 34.192.0.0/16 -p tcp --dport 1234 -j RETURN
iptables -I DOCKER-USER -s 35.153.0.0/16 -p tcp --dport 1234 -j RETURN
iptables -I DOCKER-USER -s 13.56.63.0/24 -p tcp --dport 1234 -j RETURN
结果:
iptables -L DOCKER-USER -n -v --line-numbers
Chain DOCKER-USER (1 references)
pkts bytes target prot opt in out source destination
0 0 RETURN tcp -- * * 13.56.63.0/24 0.0.0.0/0 tcp dpt:1234
0 0 RETURN tcp -- * * 35.153.0.0/16 0.0.0.0/0 tcp dpt:1234
0 0 RETURN tcp -- * * 34.192.0.0/16 0.0.0.0/0 tcp dpt:1234
0 0 RETURN tcp -- * * 18.204.0.0/16 0.0.0.0/0 tcp dpt:1234
0 0 REJECT tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:1234 reject-with icmp-port-unreachable
背景:
所有规则均按照当前Docker文档的建议添加到链DOCKER-USER
中。
第一个规则的目标是REJECT
,最后将成为最后一个规则,因为其他规则被添加到顶部(没有位置编号的选项-I
对应于在位置1添加一个规则)。所有目标端口为1234的软件包都将被拒绝。
其他规则以RETURN
为目标,即,目标端口为1234且来自给定子网之一的源IP的数据包将返回到调用链,即FORWARD
链。
iptables -L FORWARD -n -v
Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
16471 4568K DOCKER-USER all -- * * 0.0.0.0/0 0.0.0.0/0
16413 4565K DOCKER-ISOLATION-STAGE-1 all -- * * 0.0.0.0/0 0.0.0.0/0
7173 2060K ACCEPT all -- * docker0 0.0.0.0/0 0.0.0.0/0 ctstate RELATED,ESTABLISHED
45 2340 DOCKER all -- * docker0 0.0.0.0/0 0.0.0.0/0
在FORWARD
链中,它将由DOCKER
链进行处理,在我的情况下,它将根据需要转发到Docker容器:
iptables -L DOCKER -n -v
Chain DOCKER (1 references)
pkts bytes target prot opt in out source destination
45 2340 ACCEPT tcp -- !docker0 docker0 0.0.0.0/0 172.17.0.2 tcp dpt:1234