这是我第一次用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 tcp
docker 规则覆盖 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