iptables规则集,以便docker容器可以访问主机IP上的服务


18

我无法从Docker容器访问主机专用接口(ip)。我相当确定它与我的Iptables规则(或路由)有关。当我将--net=host标志添加到时docker run,一切都会按预期进行。同样,当我指定INPUT策略遵循Liberal时-P INPUT ACCEPT,事情也会按我期望的那样工作。但是,这些都是我要避免的不理想和不安全的选择。

由于它不特定于我的服务(DNS),因此已将其排除在问题之外,因为与docker结合进行搜索会在另一个(受欢迎的)问题区域中产生结果,从而给搜索结果增加了噪音。

另外,链接Docker容器也不是一个可行的选择,因为某些容器需要使用--net = host选项运行,从而阻止了链接,我想在可能的情况下创建一致的情况。

我有以下Iptables规则。我假设结合了CoreOS,Digital Ocean和Docker。

-P INPUT DROP
-P FORWARD ACCEPT
-P OUTPUT ACCEPT
-N DOCKER
-A INPUT -i lo -j ACCEPT
-A INPUT -i eth1 -j ACCEPT
-A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A INPUT -p tcp -m tcp --dport 22 -j ACCEPT
-A INPUT -p icmp -m icmp --icmp-type 0 -j ACCEPT
-A INPUT -p icmp -m icmp --icmp-type 3 -j ACCEPT
-A INPUT -p icmp -m icmp --icmp-type 11 -j ACCEPT
-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

我的(相关)主机接口:

3: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
    inet 10.129.112.210/16 brd 10.129.255.255 scope global eth1
       valid_lft forever preferred_lft forever
4: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default
    inet 172.17.42.1/16 scope global docker0
       valid_lft forever preferred_lft forever

我运行一个Docker容器:

$ docker run --rm -it --dns=10.129.112.210 debian:jessie # Specifying the DNS is so that the public DNS servers aren't used.

此时,我希望能够使用绑定在10.129.112.210:53上的本地服务。这样以下内容将产生答复:

$ ping google.com
^C
$ ping user.skydns.local
^C

当我从主机运行相同的命令时:

$ ping photo.skydns.localPING photo.skydns.local (10.129.112.206) 56(84) bytes of data.
64 bytes from 10.129.112.206: icmp_seq=1 ttl=64 time=0.790 ms
^C

我的resolv.conf

$ cat /etc/resolv.conf
nameserver 10.129.112.210
nameserver 127.0.0.1
nameserver 8.8.8.8
nameserver 8.8.4.4

这里的重点不是使用主机上可用的本地DNS服务(通过另一个docker实例)访问公共主机,而是内部主机。

为了进一步说明(我的ascii艺术设计技能超过了iptables fu,因此在这一点上应该足够说明):

 ______________________________________________
|  __________________________           Host   |
| |   Docker DNS container   |                 |
|  ``````````````````````|```                  |
|                        |                     |
|     ,----------,---( private n. interface )  |
|     |          |                             |
|     |          |   ( public  n. interface )---
|     |          |                             |
|     |          |   ( loopbck n. interface )  |
|     |          |                             |
|     |          |                             |
|     |        __|_______________________      |
|     |       | Docker service container |     |
|     |        ``````````````````````````      |
|     |                                        |
|     |                                        |
| [ Local host service using DNS. ]            |
|                                              |
|______________________________________________|

  private (host) network interface: eth1 (10.129.0.0/16)
  Docker network interface: docker0 (172.17.0.0/16)

我已经搜索,阅读并应用了不同的示例Iptables配置,但是我对“高级” Iptables规则知之甚少,无法理解正在发生的事情并因此无法获得所需的结果。

输出iptables -t nat -nL

Chain PREROUTING (policy ACCEPT)
target     prot opt source               destination
DOCKER     all  --  0.0.0.0/0            0.0.0.0/0            ADDRTYPE match dst-type LOCAL

Chain INPUT (policy ACCEPT)
target     prot opt source               destination

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination
DOCKER     all  --  0.0.0.0/0           !127.0.0.0/8          ADDRTYPE match dst-type LOCAL

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

Chain DOCKER (2 references)
target     prot opt source               destination

输出cat /proc/sys/net/ipv4/ip_forward

1

您可以发布的输出iptables -t nat -nL吗?您是否进行了任何数据包分析,例如从源容器执行ping操作,然后使用tcpdump捕获主机上的数据包。
Daniel t。

当然,感谢您到目前为止提供的帮助:pastebin.com/TAaT73nk(不适合注释。)- 编辑 ->将链接更新为未过期的pastebin。
Dynom

也许我没有正确理解您的问题,但是我没有看到任何允许主机上进行DNS查询的规则。另外,是否启用了ip_forward?
Laurentiu Roescu 2015年

嗨@LaurentiuRoescu。$ cat /proc/sys/net/ipv4/ip_forward -> 1-A INPUT -i eth1 -j ACCEPT接受专用接口上的所有连接。您缺少什么规则?
Dynom

2
我认为来自容器的数据包来自docker0接口,而不是eth1。试试-A INPUT -i docker0 -j ACCEPT
Laurentiu Roescu 2015年

Answers:


14

容器使用docker0接口与主机进行通信。要允许来自容器的流量添加:

-A INPUT -i docker0 -j ACCEPT

2
Dynom,您可能想从中学到的一课是,使用例如记录所有拒绝内容非常有用iptables -A INPUT -j LOGIN=docker0在确定需要进行哪些规则调整时,该标记将非常有用。不要错过Laurentiu的作品,这是很棒的-我+1!
MadHatter支持Monica 2015年

5
对于使用UFW的人,这是我所做的,以允许所有来自Docker容器的通信传递给主机:ufw允许在docker0上使用
Ali Ok

0

我遇到过非常相似的情况,但是添加-A INPUT -i docker0 -j ACCEPT将打开我在docker host的eth0接口上对容器的所有访问,这绝对不是我想要的。

而且由于我注意到我的容器对主机接口的访问受到限制(例如只有端口22),而不是完全从主机网络关闭,因此我查看了iptables规则,并在IN_public_allow链中找到了一个应对此负责的规则。规则是-A IN_public_allow -p tcp -m tcp --dport 22 -m conntrack --ctstate NEW -j ACCEPT。因此,我添加了类似的规则以允许我的容器访问所需的其他主机端口,我认为这可能是打开对容器的主机网络访问权限的更精确的方法。


-i docker0应确保这不会影响未通过docker0网络到达的流量。您的语法虽然不清楚。也许您是说启用了通过eth0从docker主机进行的出站访问,这可能是正确的。我同意,更有针对性的规则可能只在您需要时才开放。
mc0e
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.