将 Docker 容器端口仅绑定到特定的外部服务器地址

将 Docker 容器端口仅绑定到特定的外部服务器地址

这是我第一次用docker解决这样的网络“问题”,我需要一些输入。

这是我的情况:

  • Ubuntu 14.04 运行 NginX、ufw 作为防火墙和 docker 容器来运行 PHP 后端应用程序。

  • Ufw 默认策略将 INPUT 和 OUTPUT 以及 FORWARD 设置为 DROP。

  • sysctl 规则:net.ipv4.conf.all.forwarding = 0

我的需求:

  • 以守护进程模式运行的容器,端口 8888/tcp 接受来自外部的连接,但仅来自 ip 8.8.8.8,端口 4444/tcp 监听来自本地主机的连接

我的问题:

Ufw 设置为仅接受来自 ip 8.8.8.8 的端口 8888/tcp 上的传入连接。因此,基本上:

sudo ufw allow in from 8.8.8.8 to any port 8888 proto tcp

然后,我使用以下命令运行容器:

docker run -p 8888:8888/tcp -p 127.0.0.1:4444:4444/tcp [other options ]

之后,nmap -p 8888 45.45.45.45从没有 ip = 8.8.8.8 的机器运行,我期望得到port filtered。但是......

Host is up (0.056s latency).
PORT      STATE SERVICE
8888/tcp  open  unknown

然后我尝试再次运行该容器,-p 8888:8888/tcp然后我尝试再次运行 nmap,然后......

Host is up (0.061s latency).
PORT      STATE SERVICE
8888/tcp  filtered  unknown

因此,如果我错了,请纠正我,docker 规则会覆盖 ufw 的规则。

然后,我搜索了一种方法,只允许来自特定地址的容器中的传入流量,我发现了类似的东西:

iptables -I DOCKER -i ext_if ! -s 8.8.8.8 -j DROP

并且它有效:

PORT      STATE    SERVICE
8888/tcp  filtered unknown

Nmap done: 1 IP address (1 host up) scanned in 15.05 seconds

我的问题是:

上面的解决方案适合我的情况吗?我的意思是:像上面那样,我用allow in from 8.8.8.8 to any port 8888 proto tcpdocker 规则覆盖 ufw 规则,该规则规定“仅当流量来自 ip 8.8.8.8 时才公开端口”...这是正确的方法吗?

让 ufw 去做丢弃不需要的数据包的“坏事”,然后将流量从过滤端口转发到 docker,不是更好吗?有没有办法做到这一点?

我会避免使用这个解决方案,因为作为 DOCKER 链的 iptable 规则,该规则涉及我当前拥有或将拥有的所有容器。

谢谢。

答案1

在 Linux 上,ufw 和 docker 的规则都是在网络过滤器。所以是的iptables。因此,不可能让 ufw 做一些事情,并让 docker 规则做其他事情 - 所有这些事情都将由单个底层 netfilter 子系统完成。

该命令iptables-save可用于转储为 netfilter 配置的所有内容,包括 docker 规则和 ufw,然后(经过一些努力)您可以跟踪链条并查看它在做什么。

答案2

请注意,当 Docker 守护进程启动时,它会将DOCKER链添加到*filter*nat规则中。如果随后使用 ufw 等清除所有 iptables 规则,可能会破坏预期的行为。启动容器时,FORWARD会将规则添加到DOCKER链中。Docker 正在运行如下命令:

iptables --wait -t filter -A DOCKER ! -i docker0 -o docker0 -p tcp -d 172.17.0.2 --dport 8888 -j ACCEPT

但是,这不会向外界开放任何端口,因为 Docker 没有修改 的INPUT规则iptables。所以,这意味着你的 ufw 规则有问题。

如果你不喜欢 Docker 修改你的iptables规则,你可以在 Docker 服务配置中添加来禁用它--iptables=false

答案3

Docker 允许使用 DOCKER-USER 表配置防火墙规则。设置端口过滤器时,您需要使用 conntrack 来获取原始目标端口,因为您可能有多个容器都在容器内的同一端口上监听,并发布到主机上的不同端口,防火墙规则将在数据包被处理后发送到容器端口后看到它们。

使用 DOCKER-USER 时,请务必将规则插入到链的顶部,因为它在末尾带有默认接受规则,在此之后附加的规则将被忽略。这也意味着您需要反转逻辑,先插入最后一条规则,因为后面的规则将在此之前插入。

使用 iptables 从 eth0 接口丢弃不在 10.0.0.0/24 源 CIDR 上并发布到 8080 端口的数据包的示例如下:

iptables -I DOCKER-USER -i eth0 ! -s 10.0.0.0/24 -p tcp \
  -m conntrack --ctorigdstport 8080 -j DROP
iptables -I DOCKER-USER -i eth0 -s 10.0.0.0/24 -p tcp \
  -m conntrack --ctorigdstport 8080 -j ACCEPT

相关内容