限制互联网访问 - Docker 容器
Restrict Internet Access - Docker Container
我有一个限制负载均衡器网络中容器的 Internet 访问的情况。例如下图
只有 container4 连接到互联网;其他 three 只能通过 container4 与外界交流。例如,如果 container1 需要 smtp 支持,它会将 smtp 请求转发到 container4 以获得访问权限。
除 container4 以外的任何容器都不允许直接访问 Internet!这应该在 Docker 级别上强制执行。
我相信它可以在 docker 网络创建时配置 ,任何人都可以解释如何实现这一点吗?
用于访问 internet 的网络创建
docker network create --subnet=172.19.0.0/16 internet
用于阻止互联网访问的网络创建
docker network create --internal --subnet 10.1.1.0/24 no-internet
如果你想将 docker 容器连接到互联网
docker network connect internet container-name
如果您想阻止互联网访问
docker network connect no-internet container-name
备注
在内部网络中,我们无法公开端口以连接外部世界,请参阅此了解更多详情
据发现 here,我将其与 docker-compose 一起使用。另存为 docker-compose.yml
:
version: '3'
services:
outgoing-wont-work:
image: alpine
networks:
- no-internet
command: ping -c 3 google.com # will crash
internal-will-work:
image: alpine
networks:
- no-internet
command: ping -c 3 internal-and-external
internal-and-external:
image: alpine
networks:
- no-internet
- internet
command: ping -c 3 google.com
networks:
no-internet:
driver: bridge
internal: true
internet:
driver: bridge
然后运行 docker-compose up -d
, docker-compose ps
会在几秒后显示如下内容:
Name Command State Ports
----------------------------------------------------------------------------------
dco_inet_internal-and-external_1 ping -c 3 google.com Exit 0
dco_inet_internal-will-work_1 ping -c 3 internal-and-ext ... Exit 0
dco_inet_outgoing-wont-work_1 ping -c 3 google.com Exit 1
另一种选择,如果您需要在没有 Internet 访问权限的情况下公开容器上的端口,但又想让它与其他容器通信,则可以提供伪造的 DNS 配置。但这不是一个完美的解决方案,因为它不会阻止对外部世界的直接 IP 访问。
docker-compose.yaml
version: '3'
services:
service1:
image: alpine
command: sh -c 'ping service2 -c 1; ping google.com -c 1'
dns: 0.0.0.0
service2:
image: alpine
command: sh -c 'ping service1 -c 1; ping google.com -c 1'
dns: 0.0.0.0
isolated> docker-compose up
Recreating isolated_service1_1 ... done Recreating isolated_service2_1 ... done Attaching to isolated_service2_1, isolated_service1_1
service1_1 | PING service2 (172.18.0.2) 56(84) bytes of data.
service1_1 | 64 bytes from isolated_service2_1.isolated_default (172.18.0.2): icmp_seq=1 ttl=64 time=0.038 ms
service1_1 |
service1_1 | --- service2 ping statistics ---
service1_1 | 1 packets transmitted, 1 received, 0% packet loss, time 0ms
service1_1 | rtt min/avg/max/mdev = 0.038/0.038/0.038/0.000 ms
service2_1 | PING service1 (172.18.0.3) 56(84) bytes of data.
service2_1 | 64 bytes from isolated_service1_1.isolated_default (172.18.0.3): icmp_seq=1 ttl=64 time=0.093 ms
service2_1 |
service2_1 | --- service1 ping statistics ---
service2_1 | 1 packets transmitted, 1 received, 0% packet loss, time 0ms
service2_1 | rtt min/avg/max/mdev = 0.093/0.093/0.093/0.000 ms
service1_1 | ping: google.com: Temporary failure in name resolution
service2_1 | ping: google.com: Temporary failure in name resolution
isolated_service1_1 exited with code 2
isolated_service2_1 exited with code 2
如 Bilal 的回答所述,如果您不需要公开端口,内部网络是一个很好的解决方案。
如果您确实需要公开端口,下面使用 iptables 的解决方案可以满足我的要求:
docker network create --subnet 172.19.0.0/16 no-internet
sudo iptables --insert DOCKER-USER -s 172.19.0.0/16 -j REJECT --reject-with icmp-port-unreachable
sudo iptables --insert DOCKER-USER -s 172.19.0.0/16 -m state --state RELATED,ESTABLISHED -j RETURN
然后添加
--network no-internet
当您 运行 您的 docker 容器时。例如:
$ docker run -it --network no-internet ubuntu:focal /bin/bash
root@9f2181f79985:/# apt update
Err:1 http://archive.ubuntu.com/ubuntu focal InRelease
Temporary failure resolving 'archive.ubuntu.com'
我有一个限制负载均衡器网络中容器的 Internet 访问的情况。例如下图
只有 container4 连接到互联网;其他 three 只能通过 container4 与外界交流。例如,如果 container1 需要 smtp 支持,它会将 smtp 请求转发到 container4 以获得访问权限。
除 container4 以外的任何容器都不允许直接访问 Internet!这应该在 Docker 级别上强制执行。
我相信它可以在 docker 网络创建时配置 ,任何人都可以解释如何实现这一点吗?
用于访问 internet 的网络创建
docker network create --subnet=172.19.0.0/16 internet
用于阻止互联网访问的网络创建
docker network create --internal --subnet 10.1.1.0/24 no-internet
如果你想将 docker 容器连接到互联网
docker network connect internet container-name
如果您想阻止互联网访问
docker network connect no-internet container-name
备注
在内部网络中,我们无法公开端口以连接外部世界,请参阅此
据发现 here,我将其与 docker-compose 一起使用。另存为 docker-compose.yml
:
version: '3'
services:
outgoing-wont-work:
image: alpine
networks:
- no-internet
command: ping -c 3 google.com # will crash
internal-will-work:
image: alpine
networks:
- no-internet
command: ping -c 3 internal-and-external
internal-and-external:
image: alpine
networks:
- no-internet
- internet
command: ping -c 3 google.com
networks:
no-internet:
driver: bridge
internal: true
internet:
driver: bridge
然后运行 docker-compose up -d
, docker-compose ps
会在几秒后显示如下内容:
Name Command State Ports
----------------------------------------------------------------------------------
dco_inet_internal-and-external_1 ping -c 3 google.com Exit 0
dco_inet_internal-will-work_1 ping -c 3 internal-and-ext ... Exit 0
dco_inet_outgoing-wont-work_1 ping -c 3 google.com Exit 1
另一种选择,如果您需要在没有 Internet 访问权限的情况下公开容器上的端口,但又想让它与其他容器通信,则可以提供伪造的 DNS 配置。但这不是一个完美的解决方案,因为它不会阻止对外部世界的直接 IP 访问。
docker-compose.yaml
version: '3'
services:
service1:
image: alpine
command: sh -c 'ping service2 -c 1; ping google.com -c 1'
dns: 0.0.0.0
service2:
image: alpine
command: sh -c 'ping service1 -c 1; ping google.com -c 1'
dns: 0.0.0.0
isolated> docker-compose up
Recreating isolated_service1_1 ... done Recreating isolated_service2_1 ... done Attaching to isolated_service2_1, isolated_service1_1
service1_1 | PING service2 (172.18.0.2) 56(84) bytes of data.
service1_1 | 64 bytes from isolated_service2_1.isolated_default (172.18.0.2): icmp_seq=1 ttl=64 time=0.038 ms
service1_1 |
service1_1 | --- service2 ping statistics ---
service1_1 | 1 packets transmitted, 1 received, 0% packet loss, time 0ms
service1_1 | rtt min/avg/max/mdev = 0.038/0.038/0.038/0.000 ms
service2_1 | PING service1 (172.18.0.3) 56(84) bytes of data.
service2_1 | 64 bytes from isolated_service1_1.isolated_default (172.18.0.3): icmp_seq=1 ttl=64 time=0.093 ms
service2_1 |
service2_1 | --- service1 ping statistics ---
service2_1 | 1 packets transmitted, 1 received, 0% packet loss, time 0ms
service2_1 | rtt min/avg/max/mdev = 0.093/0.093/0.093/0.000 ms
service1_1 | ping: google.com: Temporary failure in name resolution
service2_1 | ping: google.com: Temporary failure in name resolution
isolated_service1_1 exited with code 2
isolated_service2_1 exited with code 2
如 Bilal 的回答所述,如果您不需要公开端口,内部网络是一个很好的解决方案。
如果您确实需要公开端口,下面使用 iptables 的解决方案可以满足我的要求:
docker network create --subnet 172.19.0.0/16 no-internet
sudo iptables --insert DOCKER-USER -s 172.19.0.0/16 -j REJECT --reject-with icmp-port-unreachable
sudo iptables --insert DOCKER-USER -s 172.19.0.0/16 -m state --state RELATED,ESTABLISHED -j RETURN
然后添加
--network no-internet
当您 运行 您的 docker 容器时。例如:
$ docker run -it --network no-internet ubuntu:focal /bin/bash
root@9f2181f79985:/# apt update
Err:1 http://archive.ubuntu.com/ubuntu focal InRelease
Temporary failure resolving 'archive.ubuntu.com'