限制Docker容器的互联网访问

时间:2019-01-09 07:53:30

标签: docker networking docker-compose iptables

TLDR; --向docker容器添加了一些iptable规则以限制Internet访问。工作正常,除了现在我无法从主机访问容器应用程序,但可以从容器本身内部访问容器

我有一个运行Web应用程序的容器。该容器使用mysqlredis等。每个依赖项都是远程的,可以通过IP地址在特定端口上访问。

例如,可以在ip 13.255.255.255上访问mysql

我想要的是只允许容器使用mysql ip地址,而不能使用其他IP。很少有curl请求来自代码内的请求,我不想超出我的主机网络。

我在docker中添加了一个入口点脚本,该脚本在容器中添加了一些iptables规则。

ALLOWED_CIDR1=172.0.0.0/16
ALLOWED_CIDR2=13.255.255.255 #For mysql access

#iptables -P FORWARD DROP # we aren't a router
iptables -A INPUT -m state --state INVALID -j DROP
iptables -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
iptables -A INPUT -i lo -j ACCEPT
iptables -A INPUT -s 127.0.0.1 -j ACCEPT
iptables -A OUTPUT -d 127.0.0.1 -j ACCEPT
iptables -P INPUT DROP # Drop everything we don't accept

iptables -A INPUT -s 0.0.0.0 -j ACCEPT
iptables -A INPUT -s ::1 -j ACCEPT
iptables -A OUTPUT -d ::1 -j ACCEPT
iptables -A INPUT -s $ALLOWED_CIDR1 -j ACCEPT
iptables -A INPUT -s $ALLOWED_CIDR1 -j ACCEPT
iptables -A OUTPUT -d $ALLOWED_CIDR2 -j ACCEPT
iptables -A OUTPUT -d $ALLOWED_CIDR2 -j ACCEPT
iptables -P INPUT DROP
iptables -P OUTPUT DROP

当我运行容器并执行

docker-compose exec <container-name> curl http://google.com

我得到以下回应:

  

卷曲:(6)无法解析主机:google.com

这是预期的。现在,当我这样做

docker-compose exec <container-name> curl http://0.0.0.0

我得到以下回应:

  

“世界你好!”

再次期望。但是,当我从主机上执行curl http://0.0.0.0时,输出如下

* Trying 0.0.0.0...
* TCP_NODELAY set
* Connected to 0.0.0.0 (127.0.0.1) port 80 (#0)
> GET / HTTP/1.1
> Host: 0.0.0.0
> User-Agent: curl/7.62.0
> Accept: */*
> // Hangs here

因此,我无法从主机连接到http://0.0.0.0,但可以从docker内部连接。

1 个答案:

答案 0 :(得分:0)

我完全愚蠢地忽略了自己发布的iptables规则。

错误的规则集

ALLOWED_CIDR1=172.0.0.0/16
ALLOWED_CIDR2=13.255.255.255 #For mysql access

#iptables -P FORWARD DROP # we aren't a router
iptables -A INPUT -m state --state INVALID -j DROP
iptables -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
iptables -A INPUT -i lo -j ACCEPT
iptables -A INPUT -s 127.0.0.1 -j ACCEPT
iptables -A OUTPUT -d 127.0.0.1 -j ACCEPT
iptables -P INPUT DROP # Drop everything we don't accept

iptables -A INPUT -s 0.0.0.0 -j ACCEPT
iptables -A INPUT -s ::1 -j ACCEPT
iptables -A OUTPUT -d ::1 -j ACCEPT
iptables -A INPUT -s $ALLOWED_CIDR1 -j ACCEPT
iptables -A INPUT -s $ALLOWED_CIDR1 -j ACCEPT
iptables -A OUTPUT -d $ALLOWED_CIDR2 -j ACCEPT
iptables -A OUTPUT -d $ALLOWED_CIDR2 -j ACCEPT
iptables -P INPUT DROP
iptables -P OUTPUT DROP

您可以在上一节中看到

  1. ip 0.0.0.0没有 OUTPUT ACCEPT
  2. ip 192.168.x.x没有 OUTPUT ACCEPT 规则,该规则是我的docker-0网络接口的ip地址

如果在启动容器时使用了网络模式docker0,则docker和主机都使用bridged网络接口进行通信(碰巧是我的情况)。

我注意到的另一件事是,我根本不需要0.0.0.0127.0.0.1规则。由于入口点脚本将在docker容器中添加iptable规则,因此我们可能永远都不想从容器本身访问webapp。因此,为什么还要打扰127.0.0.1?

总而言之,这就是我所做的:

  1. 获取我的docker0网络的IP地址。 ip addr show docker0。它输出了192.168.144.1/20
  2. 我在入口点iptable规则的 ACCEPT 规则中添加了192.168.0.0/16,该规则涵盖了第1点的ipaddress。
  3. 现在我可以从外面访问我的容器了

我的iptable规则现在看起来像这样:

ALLOWED_CIDR1=172.0.0.0/16
ALLOWED_CIDR2=13.255.255.255
ALLOWED_CIDR3=192.168.0.0/16

iptables -A INPUT -m state --state INVALID -j DROP
iptables -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
iptables -A INPUT -i lo -j ACCEPT
iptables -P INPUT DROP # Drop everything we don't accept
iptables -P OUTPUT DROP

iptables -A INPUT -s $ALLOWED_CIDR1 -j ACCEPT
iptables -A INPUT -s $ALLOWED_CIDR2 -j ACCEPT
iptables -A INPUT -s $ALLOWED_CIDR3 -j ACCEPT
iptables -A OUTPUT -d $ALLOWED_CIDR1 -j ACCEPT
iptables -A OUTPUT -d $ALLOWED_CIDR2 -j ACCEPT
iptables -A OUTPUT -d $ALLOWED_CIDR3 -j ACCEPT