使用iptables限制与docker容器的外部连接的步骤?


20

我的目标是将对Docker容器的访问限制为仅几个公共IP地址。是否有一个简单,可重复的过程来实现我的目标?在使用Docker的默认选项时仅了解iptables的基础知识,我发现这非常困难。

我想运行一个容器,使其对公共Internet可见,但只允许来自选定主机的连接。我希望将默认的INPUT策略设置为REJECT,然后仅允许来自主机的连接。但是Docker的NAT规则和链妨碍了我的INPUT规则。

在以下假设的基础上,有人可以提供一个示例来说明如何实现我的目标吗?

  • 在eth0上托管公共IP 80.80.80.80
  • eth1上的主机专用IP 192.168.1.10
  • docker run -d -p 3306:3306 mysql
  • 阻止从主机4.4.4.4和8.8.8.8到主机/容器3306的所有连接

我很高兴将容器仅绑定到本地ip地址,但是需要有关如何正确设置iptables转发规则的说明,这些规则可以在docker进程和主机重启后继续存在。

谢谢!

Answers:


15

使用docker的防火墙规则时要记住两件事:

  1. 为了避免您的规则被Docker破坏,请使用DOCKER-USER
  2. Docker在PREROUTING表链中进行端口映射nat。这种情况发生在之前filter的规则,所以--dest--dport会看到容器的内部IP和端口。要访问原始目的地,可以使用-m conntrack --ctorigdstport

例如:

iptables -A DOCKER-USER -i eth0 -s 8.8.8.8 -p tcp -m conntrack --ctorigdstport 3306 --ctdir ORIGINAL -j ACCEPT
iptables -A DOCKER-USER -i eth0 -s 4.4.4.4 -p tcp -m conntrack --ctorigdstport 3306 --ctdir ORIGINAL -j ACCEPT
iptables -A DOCKER-USER -i eth0 -p tcp -m conntrack --ctorigdstport 3306 --ctdir ORIGINAL -j DROP

注意:如果没有--ctdir ORIGINAL,这也将匹配从容器到其他服务器上端口3306的连接返回的回复数据包,这几乎肯定不是您想要的!如果像我一样,您的第一个规则不是严格要求的-m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT,因为这将处理所有答复数据包,但是仍然使用它会更安全--ctdir ORIGINAL


是否应对此进行编辑以包含 --ctdir?我使用-m conntrack --ctstate NEW --ctorigdstport 3306 --ctdir ORIGINAL
lonix

@Ionix,是的,尽管我只是弄清楚了为什么它让我感到困惑,但应该。我添加了一些解释。
SystemParadox

1
请注意,默认DOCKER-USER表包含以下条目:-A DOCKER-USER -j RETURN如果使用,它将在以上条目之前运行-A。一种解决方案是使用反向插入规则-I
BMitch19年

@BMitch或者甚至更好的是,添加的所有规则,在新FILTERS链,-I:插入新的规则(像你说的),跳转到它-I INPUT -j FILTERS-I DOCKER-USER -i eth0 -j FILTERS
lonix

@BMitch但是,我只是检查了服务器,而返回规则不存在,也许最新的Docker版本不再插入它了?-I为了安全起见,虽然要使用好主意。
lonix

8

在Docker v.17.06中,有一个名为DOCKER-USER的新iptables链。这是您的自定义规则:https : //docs.docker.com/network/iptables/

与DOCKER链不同,它不会在构建/启动容器时重置。因此,即使在安装docker和启动容器之前,也可以将这些行添加到iptables config / script中以配置服务器:

-N DOCKER
-N DOCKER-ISOLATION
-N DOCKER-USER
-A DOCKER-ISOLATION -j RETURN
-A DOCKER-USER -i eth0 -p tcp -m tcp --dport 3306 -j DROP
-A DOCKER-USER -j RETURN

现在,即使认为docker为世界打开了端口,MySQL的端口也被阻止了外部访问(eth0)。(这些规则假定您的外部接口是eth0。)

最终,如果您像我一样试图锁住端口,将其弄得一团糟,则必须先清理iptables,然后重新启动docker服务。


我想念为什么此DOCKER-USER表与任何其他用户添加的表有什么不同。它没有预先应用过滤器,因此您仍然必须自己指定接口名称。如果创建“ MY-CHAIN”并将其插入到FORWARD链中,将得到相同的结果,不是吗?
ColinM

是的,这有所作为,因为Docker将DOCKER-USER链插入到FORWARD链中: -A FORWARD -j DOCKER-USER -A FORWARD -j DOCKER-ISOLATION 这就是为什么自定义指令在DOCKER链之前执行。
ck1

请注意,如果您--dport在DOCKER-USER内部使用,则必须匹配容器服务的内部 IP,而不是裸露的端口。这些通常匹配但并不总是匹配,并且很容易与其他服务冲突,因此我仍然认为这种DOCKER-USER解决方案是半熟的。
ColinM '17

4

更新:尽管此解决方案在2015年有效,但它不再是正确的解决方案。

答案似乎在Docker的文档中,网址https://docs.docker.com/articles/networking/#the-world

Docker的转发规则默认允许所有外部源IP。要仅允许特定的IP或网络访问容器,请在DOCKER过滤器链的顶部插入一个否定的规则。例如,为了限制外部访问,以便只有源IP 8.8.8.8可以访问容器,可以添加以下规则:iptables -I DOCKER -i ext_if ! -s 8.8.8.8 -j DROP

我最终要做的是:

iptables -I DOCKER -i eth0 -s 8.8.8.8 -p tcp --dport 3306 -j ACCEPT
iptables -I DOCKER -i eth0 -s 4.4.4.4 -p tcp --dport 3306 -j ACCEPT
iptables -I DOCKER 3 -i eth0 -p tcp --dport 3306 -j DROP

我没有触摸--iptables--icc选项。


1
如果这样做iptables -vnL DOCKER,则目标端口是容器内的所有端口。如果我做对了,那就意味着上面的规则只会影响3306容器中的端口-也就是说,如果您使用了-p 12345:3306容器,那么您的规则仍然是锁定访问权限的规则(即--dport 12345不起作用) ,因为DOCKER链的ACCEPT规则是NAT后的。
海边

没错,规则需要与容器内的端口相关。
GGGforce 2015年

1
哼,如果您碰巧运行多个使用内部NGINX进行反向代理的容器(例如Zabbix,自定义负载均衡器等),这是很丑的,因为这将需要您事先知道容器的IP。我仍在寻找不需要的问题的解决方案--iptables=false,因为这似乎是所有人中最糟糕的选择。
海边

谢谢!经过数小时的搜索,您已经解决了我的问题。现在,我终于可以将MySQL仅仅锁定到我的家庭IP地址,而不会将软肋暴露给整个世界。
马特·卡瓦纳

1
DOCKER链不应由用户直接操纵!为此,请使用DOCKER-USER链。检查接受的答案。
Paul-Sebastian Manole

3

更新:虽然此答案仍然有效,但@SystemParadox DOCKER-USER与结合使用的答案--ctorigdstport更好。

这是一个可以在重新启动之间保持良好状态的解决方案,可让您影响裸露的端口而不是内部端口。

iptables -t mangle -N DOCKER-mysql iptables -t mangle -A DOCKER-mysql -s 22.33.44.144/32 -j RETURN iptables -t mangle -A DOCKER-mysql -s 22.33.44.233/32 -j RETURN iptables -t mangle -A DOCKER-mysql -j DROP iptables -t mangle -A PREROUTING -i eth0 -p tcp -m tcp --dport 3306 -j DOCKER-mysql

我已经构建了一个Docker映像,使用该方法使用环境变量或使用etcd(或两者)动态地为您自动管理iptables:

https://hub.docker.com/r/colinmollenhour/confd-firewall/

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.