在使用“-p< port>:< port>”时,Docker忽略可调用的规则。 [英] Docker ignores iptable rules when using "-p <port>:<port>"

查看:122
本文介绍了在使用“-p< port>:< port>”时,Docker忽略可调用的规则。的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

刚刚意识到,Docker似乎绕过了我的iptable规则。我对Docker和iptables并不感到不可思议。试过了很多不同的事情,最后几天。还看到最近的码头码头版本有一个很大的变化,有一个特殊的DOCKER链,应该允许我做到这一点。但是不知道我做错了什么,但是从来没有做过我期望的事情。



所以我想要的是很简单的。我希望它的行为像预期的那样。如果我有一个ACCEPT规则来通过,如果不是它被阻止。



我的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相关,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





谢谢!



Docker-版本: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相关,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]
#我可以从IP访问1.2.3.4
-A DOCKER -s 1.2.3.4/32 -p tcp -m tcp - -dport 123 -j ACCEPT
#我可以从其他Docker容器访问
-A DOCKER -o docker0 -p tcp -m tcp --dport 123 -j ACCEPT
#不允许它为任何其他
-A DOCKER -p tcp --dport 123 -j DROP

-A INPUT -i lo -j ACCEPT
-A INPUT -m conntrack - ctstate相关,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


解决方案

您的iptables配置现在看起来有点破碎,好像您在某些时候没有重新清除它开始Docker。例如,您可以在过滤器 nat DOCKER c $ c>表,但没有引用它的规则,所以放在该链中的规则将不会有任何影响。



一般来说,如果要实现iptables规则影响您的Docker容器,他们需要进入过滤器表的 FORWARD 链。每个容器都有*自己的* ip地址,这意味着您的主机只是接受数据包,然后将 FORWARD'将它们转发到容器地址。



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



但是,我不知道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 链中创建的规则需要在在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上的任何容器。


Just realized a few days ago that Docker seems to bypass my iptable rules. I am not incredible experienced with Docker nor iptables. Tried a lot of different things the last days. Also saw that there was big change in recent docker versions with a special DOCKER-chain that should allow me to do that. However not sure what I am doing wrong but it never does what I expect it to do.

So what I want is quite simple. I want that it behaves like expected. That if I have an ACCEPT-Rule to go through and if not it gets blocked.

My iptable looked originally like that (so before my many unsuccessful attempts):

*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

Hoped that it does exactly what I want. Just allow access to ports 22 and 80 and also allow port 123 from the ip 1.2.3.4. However If I create a container with "-p 123:123" everybody can access it. Can anybody help me and tell me how I have to change the above file?

Thanks!

Docker-Version: 1.6.2

Edit:

Left initially my different tries out to not overcomplicate the question. However adding at least one of them could maybe be helpful.

*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

The above kind of works. However get then a lot of other problems. For example do I get problems with container linking, DNS does not work anymore, and so on. So then end up adding a lot of additional rules to fix that issues but I get never to a state where it runs properly. So I guess there most be better and easier solution out there.

Solution:

Ended up doing more or less exactly what larsks said. Just did not add it to the FORWARD chain, I added it to the DOCKER chain instead. The problem with the FORWARD chain is that Docker adds its stuff in there when it restarts in first position. Which results in having my rules getting pushed down and not having any effect. However for the DOCKER chain it seems Docker appends only additional rules so mine stay in effect. So when I save my rules and then restart the server everything still works fine.

So now it looks more or less like that:

*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

解决方案

Your iptables configuration looks a little broken right now, as if you cleared it out at some point without restarting Docker. For example, you have a DOCKER chain available in both the filter and nat tables, but no rules that reference it, so rules placed in that chain will have no affect.

In general, if you want to implement iptables rules that affect your Docker containers they need to go in the FORWARD chain of the filter table. Each container has it's *own* ip address, which means that your host is simply accepting packets and thenFORWARD`ing them to the container address.

Rules in the INPUT chain are only for packets with a final destination of an address on an interface in the host's global network namespace.

However, I'm not sure that iptables is actually your problem.

If you are trying to expose services in containers such that they are available to other systems, you need to publish those ports using the -p flag to docker run. You can read more about that in this section of the documentation (Dockumentation?).

If you want to update your question with a specific example of what you are trying to accomplish I can provide a more targeted answer.

Update

It's true that when you publish a container port using -p it will generally be available to any source ip address. In order to restrict access to a published port you would need to add a new rule to your FORWARD chain. For example, if I start a web server:

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

The web server in the container is now available on port 8080 on my host. If I want to block access to this port, I need to insert a rule into the FORWARD chain that blocks access to port 80 on the container ip. So first I need the container ip address:

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

The rule I create in the FORWARD chain needs to come before the rules that docker creates, so I will need to specify an explicit position:

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

This would block all traffic from hosts other than 192.168.1.10.

If you want a rule to apply to all containers, rather than a specific container, you can bind it to the docker0 interface rather than a specific ip address:

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

This would prohibit access to port 80 on any container.

这篇关于在使用“-p< port>:< port>”时,Docker忽略可调用的规则。的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆