我的目标是将 docker 容器的访问权限限制为几个公共 IP 地址。是否有一个简单、可重复的过程来实现我的目标?在使用 Docker 的默认选项时只了解 iptables 的基础知识,我发现这非常困难。
我想运行一个容器,使其对公共 Internet 可见,但只允许来自选定主机的连接。我希望设置 REJECT 的默认 INPUT 策略,然后只允许来自我的主机的连接。但是 Docker 的 NAT 规则和链妨碍了我的 INPUT 规则。
鉴于以下假设,有人可以提供一个如何实现我的目标的例子吗?
docker run -d -p 3306:3306 mysql
我很高兴将容器仅绑定到本地 ip 地址,但需要有关如何正确设置 iptables 转发规则的说明,以便在 docker 进程和主机重新启动后继续存在。
谢谢!
Sys*_*dox 39
使用 docker 的防火墙规则时要记住两件事:
DOCKER-USER
链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
Run Code Online (Sandbox Code Playgroud)
注意:如果没有--ctdir ORIGINAL
,这也将匹配从容器到其他服务器上的端口 3306 的连接返回的回复数据包,这几乎肯定不是您想要的!如果像我一样你的第一条规则是-m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
,你并不严格需要这个,因为这将处理所有回复数据包,但--ctdir ORIGINAL
无论如何仍然使用会更安全。
小智 8
Docker v.17.06 有一个名为 DOCKER-USER 的新 iptables 链。这是您的自定义规则:https : //docs.docker.com/network/iptables/
与链 DOCKER 不同,它不会在构建/启动容器时重置。因此,您可以将这些行添加到您的 iptables 配置/脚本中,以便在安装 docker 和启动容器之前配置服务器:
-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
Run Code Online (Sandbox Code Playgroud)
现在 MySQL 的端口被阻止从外部访问 (eth0) 甚至认为 docker 为世界打开了端口。(这些规则假设您的外部接口是 eth0。)
最终,您将不得不先清理 iptables,然后重新启动 docker 服务,如果您像我一样试图锁定端口而把它弄得一团糟。
更新:虽然在 2015 年有效,但此解决方案不再是正确的方法。
\n\n答案似乎就在 Docker 的文档中:https://docs.docker.com/articles/networking/#the-world
\n\n\n\n\nDocker\xe2\x80\x99s 转发规则默认允许所有外部源 IP。要仅允许特定 IP 或网络访问容器,请在 DOCKER 过滤器链的顶部插入否定规则。例如,要限制外部访问,仅源 IP 8.8.8.8 可以访问容器,可以添加以下规则:
\niptables -I DOCKER -i ext_if ! -s 8.8.8.8 -j DROP
我最终做的是:
\n\niptables -I DOCKER -i eth0 -s 8.8.8.8 -p tcp --dport 3306 -j ACCEPT\niptables -I DOCKER -i eth0 -s 4.4.4.4 -p tcp --dport 3306 -j ACCEPT\niptables -I DOCKER 3 -i eth0 -p tcp --dport 3306 -j DROP\n
Run Code Online (Sandbox Code Playgroud)\n\n我没有碰--iptables
或--icc
选项。
更新:DOCKER-USER
虽然这个答案仍然有效,但 @SystemParadox与 结合使用的答案--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
Run Code Online (Sandbox Code Playgroud)
我构建了一个 Docker 映像,它使用此方法自动为您管理 iptables,使用环境变量或动态使用 etcd(或两者):
https://hub.docker.com/r/colinmollenhour/confd-firewall/
归档时间: |
|
查看次数: |
45043 次 |
最近记录: |