【问题标题】:Restrict Internet Access - Docker Container限制 Internet 访问 - Docker 容器
【发布时间】:2017-02-16 05:56:09
【问题描述】:

我遇到了限制负载平衡器网络中容器的 Internet 访问的情况。比如下图

只有 container4 连接到互联网;其他三个只通过container4与外界交流。例如,如果container1需要smtp支持,它会将smtp请求转发给container4以获得访问权限。

除了container4之外的任何容器都不能直接访问互联网!这应该在 Docker 级别强制执行。

我相信它可以在 docker 网络创建上进行配置,谁能解释一下如何实现这一点?

【问题讨论】:

    标签: docker docker-networking


    【解决方案1】:

    为访问互联网创建网络

    docker network create --subnet=172.19.0.0/16 互联网

    创建网络以阻止互联网访问

    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
    

    注意

    在内部网络中我们不能暴露端口来连接外部世界,请参考question了解更多详情

    【讨论】:

    • 你知道如何使用 Docker Compose 进行配置吗?
    • 我不知道@JozefKnaperek
    • no-internet 网络上的容器仍然可以进行 DNS 查询;阅读this
    • @BharatKhatri 是的,但不是通过互联网。
    • @JozefKnaperek 查看我对 docker-compose 解决方案的回答。
    【解决方案2】:

    如发现 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      
    

    【讨论】:

    • 我希望这对我有用。我们将 Traefik 作为应用程序容器前面的反向代理运行,将 Squid 作为从应用程序容器到 Internet 的传出 HTTP(S) 请求的代理运行。我尝试了您的解决方案,但应用程序容器仍然可以访问互联网,我认为是通过它与 Traefik 共享的网络。
    【解决方案3】:

    另一种选择,如果您需要在无法访问 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
    

    【讨论】:

    • 它并不完美,但它可能会减轻大多数来自软件的互联网访问尝试。
    • 我不同意它不限制任何东西,因此远非完美......
    • 这适用于需要 DNS 解析的请求,并且对于基于网络的限制不可行的情况是一个很好的解决方法。我们的设置涉及应用程序容器前面的 Traefik 实例,在这种情况下,其他解决方案似乎不起作用。
    【解决方案4】:

    如 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'
    

    【讨论】:

    • 你知道如何在windows主机上做到这一点吗?
    猜你喜欢
    • 1970-01-01
    • 2014-10-06
    • 2018-01-30
    • 1970-01-01
    • 2022-11-02
    • 2016-03-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多