docker 手册(http://docs.docker.com/installation/ubuntulinux/#docker-and-ufw) 指出,有必要将 UFW 的 DEFAULT_FORWARD_POLICY 设置为“ACCEPT”,以便 Docker 容器可以相互访问。
在具有可公开访问的网络接口的服务器上这样做会带来什么安全隐患?
应该做什么来确保这样的docker主机的安全?
答案1
他们似乎已经解决了这部分问题,至少在最新版本 1.4.1 中是这样。我的 FORWARD 策略是丢弃数据包,容器间通信可以正常进行。
这些是 docker 创建的 FORWARD 链中的标准规则:
$ iptables -vnL FORWARD
Chain FORWARD (policy DROP 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
6902 96M ACCEPT all -- * docker0 0.0.0.0/0 0.0.0.0/0 ctstate RELATED,ESTABLISHED
6151 482K ACCEPT all -- docker0 !docker0 0.0.0.0/0 0.0.0.0/0
3 180 ACCEPT all -- docker0 docker0 0.0.0.0/0 0.0.0.0/0
从下往上:
- 第三条规则是docker->docker通信,无限制接受。
- 第二条规则是docker->anywhere(but not docker),同样可以无限制接受。
- 第一条规则是anywhere->docker,只有“答案”数据包才会被接受。
这里没有问题。(除非你想要传出过滤器)
您可以愉快地将 FORWARD + INPUT 策略设置为 DROP/REJECT。
现在,您可能想在互联网上提供服务。例如一个简单的网络服务器:
$ docker run -d -p 80:80 dockerfile/nginx
好的,现在转到yourserver.com。您将看到默认的nginx页面。为什么? Docker在iptables中为您添加了一些特殊规则。
$ iptables -vn -t nat -L # NAT table, truncated for clarity
Chain PREROUTING (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
189 11900 DOCKER all -- * * 0.0.0.0/0 0.0.0.0/0 ADDRTYPE match dst-type LOCAL
Chain DOCKER (2 references)
pkts bytes target prot opt in out source destination
0 0 DNAT tcp -- !docker0 * 0.0.0.0/0 0.0.0.0/0 tcp dpt:80 to:172.17.0.15:80
$ iptables -vnL FORWARD
Chain FORWARD (policy DROP 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
0 0 ACCEPT tcp -- !docker0 docker0 0.0.0.0/0 172.17.0.15 tcp dpt:80
6903 96M ACCEPT all -- * docker0 0.0.0.0/0 0.0.0.0/0 ctstate RELATED,ESTABLISHED
6159 483K ACCEPT all -- docker0 !docker0 0.0.0.0/0 0.0.0.0/0
3 180 ACCEPT all -- docker0 docker0 0.0.0.0/0 0.0.0.0/0
如果有容器正在监听,这些规则将绕过所有 ufw 规则。ufw 在 nat 表中不执行任何操作,Docker 在 FORWARD 链的第一个位置设置其规则。因此,您无法阻止 IP 地址或进行任何类型的速率限制。
可能的解决方案:
- 启动 Docker
--iptables=false
并手动执行所有操作。这是一个费力的解决方案,因为每次重新启动容器时,它都会获得一个新的 IP(目前,他们计划改变这一点)。 - 绑定本地主机上的所有端口
-p 127.0.0.1:30080:80
并创建自己的 iptables 规则来实现。 - 以某种方式修改 ufw?
- 不要使用任何防火墙框架。我现在这样做。我的所有规则都保存在单独的脚本中作为 iptables 命令。此脚本在重新启动后以及每次重新启动后执行
service docker start
。虽然有点黑客,但它有效......