Docker 容器桥接模式禁用互联网(2023/12/14)

Docker 容器桥接模式禁用互联网

文章目录

  • Docker 容器桥接模式禁用互联网
    • 1. 环境
    • 2. 方案
      • 2.1 方案一
      • 2.2 方案二
      • 2.3 方案三
    • 3. 实现

最近在 Docker 容器中用到了一些第三方的闭源程序,考虑到隐私和安全问题决定将容器禁用外网,但该容器同时又需要访问宿主机及宿主机网段下的其它主机,所以最终决定将容器禁用互联网保留指定局域网,本文将详细介绍实现过程。

1. 环境

  • CentOS Linux release 7.9.2009 (Core);
  • Docker 23.0.1;

2. 方案

2.1 方案一

利用 docker network 的--internal参数限制 docker 网络外部访问,--internal参数官方解释如下:

$ docker network create --help

Usage:  docker network create [OPTIONS] NETWORK

Create a network

Options:
      --attachable           Enable manual container attachment
      --aux-address map      Auxiliary IPv4 or IPv6 addresses used by Network driver (default map[])
      --config-from string   The network from which to copy the configuration
      --config-only          Create a configuration only network
  -d, --driver string        Driver to manage the Network (default "bridge")
      --gateway strings      IPv4 or IPv6 Gateway for the master subnet
      --ingress              Create swarm routing-mesh network
      --internal             Restrict external access to the network
      --ip-range strings     Allocate container ip from a sub-range
      --ipam-driver string   IP Address Management Driver (default "default")
      --ipam-opt map         Set IPAM driver specific options (default map[])
      --ipv6                 Enable IPv6 networking
      --label list           Set metadata on a network
  -o, --opt map              Set driver specific options (default map[])
      --scope string         Control the network's scope
      --subnet strings       Subnet in CIDR format that represents a network segment

Restrict external access to the network 即限制 docker 网络的外部访问,经过测试该方式可以隔离互联网,但同时隔离了宿主机的访问,故不满足需求。

2.2 方案二

利用 docker network 的驱动选项com.docker.network.bridge.enable_ip_masquerade禁用 docker 网络的 IP 伪装,官方解释如下:

Option Equivalent Description
com.docker.network.bridge.name - Bridge name to be used when creating the Linux bridge
com.docker.network.bridge.enable_ip_masquerade --ip-masq Enable IP masquerading
com.docker.network.bridge.enable_icc --icc Enable or Disable Inter Container Connectivity
com.docker.network.bridge.host_binding_ipv4 --ip Default IP when binding container ports
com.docker.network.driver.mtu --mtu Set the containers network MTU
com.docker.network.container_iface_prefix - Set a custom prefix for container interfaces

Enable IP masquerading 即是否开启 IP 伪装,使用方法如下:

docker network create --subnet 10.9.2.0/28 -o com.docker.network.bridge.enable_ip_masquerade=false my-test-network
# docker-compose.yml
version: "3.9"
services:
networks:
  test:
    driver: bridge
    driver_opts:
      com.docker.network.bridge.enable_ip_masquerade: false

经过测试该方式可以隔离互联网的同时访问宿主机,但无法访问宿主机网段下的其它主机,故不满足需求。

2.3 方案三

通过修改容器内部的路由表实现禁止访问互联网及允许访问指定局域网,具体思路如下:

  1. 删除容器内部的默认网关实现禁止访问互联网;
  2. 添加指定局域网段的路由实现指定局域网的访问;

该方式通过路由表的方式控制可访问的资源,灵活方便,完全满足笔者的需求。

3. 实现

本文仅介绍方案三的实现,方案一与方案二因不满足笔者需求,故此处不多介绍,感兴趣的读者自行研究。

下面将以 busybox 容器为例介绍如何通过修改路由表的方式实现容器禁用互联网及允许指定局域网。

网络 IP 地址
docker0 10.2.0.1/24
容器 10.2.0.5
宿主机局域网 172.20.2.1/24
宿主机 172.20.2.7
  1. 创建 busybox 容器;

    # -it 交互式终端
    # --rm 容器停止后自动删除
    # --privileged 为容器提升权限,否则无法操作路由表
    $ docker run -it --rm --privileged busybox sh
    

    提示: 此处必须添加--privileged参数,否则无法在容器内部操作路由表。

  2. 修改 busybox 容器路由表;

    # 以下操作皆在容器交互式终端中执行
    
    # 获取默认网关地址,例如 10.2.0.1
    $ gw=$(route -n | tail -n +3 | grep U | grep G | awk '{print $2}')
    
    # 删除默认网关
    $ route del default gw $gw
    
    # 添加指定局域网路由
    $ route add -net 172.20.2.0 netmask 255.255.255.0 gw $gw
    

    提示: 容器内部可能找不到route命令,根据容器系统版本选择合适的包管理工具手动安装即可。

  3. 测试网络连通情况;

    # 以下操作皆在容器交互式终端中执行
    
    # 测试访问互联网,禁止访问
    $ ping -c 4 www.baidu.com
    ping: bad address 'www.baidu.com'
    
    # 测试访问宿主机,允许访问
    $ ping -c 4 172.20.2.7
    PING 172.20.2.7 (172.20.2.7): 56 data bytes
    64 bytes from 172.20.2.7: seq=0 ttl=64 time=0.091 ms
    64 bytes from 172.20.2.7: seq=1 ttl=64 time=0.083 ms
    64 bytes from 172.20.2.7: seq=2 ttl=64 time=0.077 ms
    64 bytes from 172.20.2.7: seq=3 ttl=64 time=0.116 ms
    
    --- 172.20.2.7 ping statistics ---
    4 packets transmitted, 4 packets received, 0% packet loss
    round-trip min/avg/max = 0.077/0.091/0.116 ms
    
    # 测试访问宿主机网段其它主机,允许访问
    $ ping -c 4 172.20.2.5
    PING 172.20.2.5 (172.20.2.5): 56 data bytes
    64 bytes from 172.20.2.5: seq=0 ttl=63 time=0.279 ms
    64 bytes from 172.20.2.5: seq=1 ttl=63 time=0.352 ms
    64 bytes from 172.20.2.5: seq=2 ttl=63 time=0.345 ms
    64 bytes from 172.20.2.5: seq=3 ttl=63 time=0.277 ms
    
    --- 172.20.2.5 ping statistics ---
    4 packets transmitted, 4 packets received, 0% packet loss
    round-trip min/avg/max = 0.277/0.313/0.352 ms
    
    # 以下操作皆在宿主机中执行
    
    # 测试访问容器,允许访问
    $ ping -c 4 10.2.0.5
    PING 10.2.0.5 (10.2.0.5) 56(84) bytes of data.
    64 bytes from 10.2.0.5: icmp_seq=1 ttl=64 time=0.051 ms
    64 bytes from 10.2.0.5: icmp_seq=2 ttl=64 time=0.050 ms
    64 bytes from 10.2.0.5: icmp_seq=3 ttl=64 time=0.064 ms
    64 bytes from 10.2.0.5: icmp_seq=4 ttl=64 time=0.062 ms
    
    --- 10.2.0.5 ping statistics ---
    4 packets transmitted, 4 received, 0% packet loss, time 2999ms
    rtt min/avg/max/mdev = 0.050/0.056/0.064/0.011 ms
    
  4. 路由表持久化;

    至此已经实现了本文的需求,但是路由表的修改容器重建后便会失效,因此需要将路由表的修改进行持久化。持久化的方式视情况而定(例如添加到entrypoint.sh脚本中),本文不在进行赘述。

参考文章:

  • 如何在Docker容器中阻止互联网访问-腾讯云开发者社区-腾讯云 (tencent.com)
  • 一个参数搞定 Docker 禁止单个容器访问外网-腾讯云开发者社区-腾讯云 (tencent.com)
  • docker network create | Docker Docs

你可能感兴趣的:(Docker,docker,桥接模式,容器,网络)