阻止对 docker 个容器的外部访问

Block external access to docker containers

我想阻止从外部直接访问 docker 容器。我使用 haproxy 并希望只允许访问端口 80、443。

我在 iptables 中添加了以下规则。但是我仍然可以通过不同的端口访问 docker 个容器。

*filter
:INPUT DROP [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
-A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
-A INPUT -p icmp -j ACCEPT
-A INPUT -i lo -j ACCEPT
-A INPUT -p tcp -m state --state NEW -m tcp --dport 22 -j ACCEPT
-A INPUT -p tcp -m state --state NEW -m tcp --dport 80 -j ACCEPT
-A INPUT -p tcp -m state --state NEW -m tcp --dport 443 -j ACCEPT
COMMIT

这可能是由于 DOCKER 链

# iptables -L
Chain INPUT (policy DROP)
target     prot opt source               destination
ACCEPT     all  --  anywhere             anywhere             state RELATED,ESTABLISHED
ACCEPT     icmp --  anywhere             anywhere
ACCEPT     all  --  anywhere             anywhere
ACCEPT     tcp  --  anywhere             anywhere             state NEW tcp dpt:ssh
ACCEPT     tcp  --  anywhere             anywhere             state NEW tcp dpt:http
ACCEPT     tcp  --  anywhere             anywhere             state NEW tcp dpt:https

Chain FORWARD (policy ACCEPT)
target     prot opt source               destination
DOCKER-ISOLATION  all  --  anywhere             anywhere
DOCKER     all  --  anywhere             anywhere
ACCEPT     all  --  anywhere             anywhere             ctstate RELATED,ESTABLISHED
ACCEPT     all  --  anywhere             anywhere
ACCEPT     all  --  anywhere             anywhere
DOCKER     all  --  anywhere             anywhere
ACCEPT     all  --  anywhere             anywhere             ctstate RELATED,ESTABLISHED
ACCEPT     all  --  anywhere             anywhere
ACCEPT     all  --  anywhere             anywhere
DOCKER     all  --  anywhere             anywhere
ACCEPT     all  --  anywhere             anywhere             ctstate RELATED,ESTABLISHED
ACCEPT     all  --  anywhere             anywhere
ACCEPT     all  --  anywhere             anywhere
DOCKER     all  --  anywhere             anywhere
ACCEPT     all  --  anywhere             anywhere             ctstate RELATED,ESTABLISHED
ACCEPT     all  --  anywhere             anywhere
ACCEPT     all  --  anywhere             anywhere

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination

Chain DOCKER (4 references)
target     prot opt source               destination
ACCEPT     tcp  --  anywhere             172.18.0.2           tcp dpt:http

Chain DOCKER-ISOLATION (1 references)
target     prot opt source               destination
DROP       all  --  anywhere             anywhere
DROP       all  --  anywhere             anywhere
DROP       all  --  anywhere             anywhere
DROP       all  --  anywhere             anywhere
DROP       all  --  anywhere             anywhere
DROP       all  --  anywhere             anywhere
DROP       all  --  anywhere             anywhere
DROP       all  --  anywhere             anywhere
DROP       all  --  anywhere             anywhere
DROP       all  --  anywhere             anywhere
DROP       all  --  anywhere             anywhere
DROP       all  --  anywhere             anywhere
RETURN     all  --  anywhere             anywhere

我需要创建什么规则来阻止直接访问?

您可以使用 docker network create NETWORK 命令创建一个网络来连接您的应用程序和代理,而不是使用 IP 表来执行此操作。也不要在任何端口上公开应用程序。您应该公开的唯一容器是您的代理。然后,您可以从代理内部使用容器名称作为主机名来路由流量。同一网络上的每个容器都可以被其他容器访问。

例如如果

  • 我有容器 A,其名称为 my-service,服务 运行ning 在端口 3000 上 没有发布到主机的端口
  • 作为代理的容器 B 运行在端口 80 上 发布到主机 。我的代理可以将请求传递给 http://my-service:3000 并将流量路由到容器。
  • 如果我尝试转到 http://mydomain:3000 这将无法工作,因为端口尚未公开并且访问该应用程序的唯一方法是通过端口 80 上的代理

我建议阅读 https://docs.docker.com/engine/userguide/networking/work-with-networks/,因为它解释了如何开始使用网络。

完全披露:我 运行 这种个人设置 VPS 无法直接通过端口访问我的容器。使用内置的 docker 网络可能比乱用 IP 表更好

希望这有用。

迪伦

编辑

我已经概括了这个过程,因为我不知道你的设置在代理、网络限制等方面的细节。我也没有进入具体的命令,因为上面的 link 比我更好地涵盖了它会。

我知道我正在回复一个旧线程,但我花了一个上午的大部分时间来解决这个问题。这个 post 显示在 google 搜索的顶部,但我觉得接受的答案没有回答 OP 的问题,而是提供了一种不同的设计来避免原始问题中所述的问题.该解决方案需要建立一个新的 docker 图像作为通往原始 docker.

的门户

有可能以下信息在原问题出现时不可用,但我从 Docker.com 中找到的是 link https://docs.docker.com/network/iptables/ 它在声明时似乎回答了原始问题:

” 默认情况下,允许所有外部源 IP 连接到 Docker 守护进程。要仅允许特定 IP 或网络访问容器,请在 DOCKER 过滤器链的顶部插入一条否定规则。例如,以下规则限制外部访问除 192.168.1.1 以外的所有 IP 地址:

$ iptables -I DOCKER-USER -i ext_if ! -s 192.168.1.1 -j DROP

"If you need to add rules which load before Docker’s rules, add them to the DOCKER-USER chain."

但遗憾的是,我已经尝试过该解决方案,但在 docker 版本 17.05.0-ce

上它似乎也不适合我

正如 @dpg 指出的那样,如果您需要从新手的角度来解决这个问题,那将是令人沮丧的。

我的主要问题(因为我也试图解决 @dpg 的回答的问题),是 Docker 文档混淆了两个解决此问题的页面数 (link1 and link2)

总结一下,也为大家节省时间,如果你没有太多的知识,陷入"Docker and iptables",答案就在那里,只是他们错过了这个:where ext_if is the name of the interface providing external connectivity to the host.

相反,在 "Understand container communication" link 中,确实有一点文字指出 ext_if 应该是网络接口.

所以,对我来说,限制对 docker 公开端口(例如:6782)​​的访问(这意味着需要修改 DOCKER-USER 而不是公共 INPUT 链)到某些 IP(例如:192.27.27.90)并限制所有其他 IP,我需要这样做,在我的情况下有效

sudo iptables -I DOCKER-USER -p tcp -i eth0 ! -s 192.27.27.90 --dport 6782 -j REJECT

(这里我假设与外界通信的网络接口是eth0,你想REJECT而不是DROP)。

如果需要更多说明,我很乐意提供帮助。

除了@Ezarate11 的评论(因为我没有足够的代表发表评论),确保--dport 是转发到 的端口,而不是端口即暴露。

例如,如果您的配置是 0.0.0.0:64743->80,那么您需要执行

sudo iptables -I DOCKER-USER -p tcp -i eth0 ! -s 192.27.27.90 --dport 80 -j REJECT

光是这个细节我就花了一段时间才弄清楚,我没有在其他地方看到这个。