如何使openvpn与docker一起工作

jb.*_*jb. 33 debian openvpn docker docker-networking

我最近安装了隐私vpn,事实证明启用openvpn打破了docker.

当我尝试运行时,docker-compose up我得到以下错误

ERROR: could not find an available, non-overlapping IPv4 address pool among the defaults to assign to the network
Run Code Online (Sandbox Code Playgroud)

禁用vpn可以解决问题(但我不想禁用它).有没有办法让这两个和平共处?我使用debian jessie,我的openvpn有以下版本字符串

 OpenVPN 2.3.4 x86_64-pc-linux-gnu [SSL (OpenSSL)] [LZO] [EPOLL] [PKCS11] [MH] [IPv6] built on Jun 26 2017
Run Code Online (Sandbox Code Playgroud)

很多人通过禁用openvpn"解决"了这个问题,所以我特别要求如何让这两个工作同时工作.

参考文献:

  1. /sf/answers/3176414601/
  2. /sf/answers/2974957541/

如果这有什么不同,我的VPN提供商是:https://www.ovpn.com/,这里是(有些编辑)配置文件:

client
dev tun

proto udp

remote host port
remote-random

mute-replay-warnings
replay-window 256

push "dhcp-option DNS 46.227.67.134"    
push "dhcp-option DNS 192.165.9.158"

remote-cert-tls server
cipher aes-256-cbc
pull

nobind
reneg-sec 432000
resolv-retry infinite

comp-lzo
verb 1

persist-key
persist-tun
auth-user-pass /etc/openvpn/credentials
ca ovpn-ca.crt
tls-auth ovpn-tls.key 1
Run Code Online (Sandbox Code Playgroud)

jb.*_*jb. 40

解决方案(TL; DR;)

/etc/openvpn/fix-routes.sh使用以下内容创建脚本:

#!/bin/sh

echo "Adding default route to $route_vpn_gateway with /0 mask..."
ip route add default via $route_vpn_gateway

echo "Removing /1 routes..."
ip route del 0.0.0.0/1 via $route_vpn_gateway
ip route del 128.0.0.0/1 via $route_vpn_gateway
Run Code Online (Sandbox Code Playgroud)

将可执行位添加到文件中:chmod o+x /etc/openvpn/fix-routes.sh.将此文件的所有者更改为root : chown root:root /etc/openvpn/fix-routes.sh.

按以下两行添加到您的配置:

 script-security 2
 route-up  /etc/openvpn/fix-routes.sh
Run Code Online (Sandbox Code Playgroud)

说明

Openvpn添加了以下网络的路由:0.0.0.0/1128.0.0.0/1(这些路由覆盖整个IP范围),并且docker无法找到IP地址范围来创建自己的专用网络.

您需要添加默认路由(通过openvpn路由所有路由)并禁用这两个特定路由.fix-routes脚本做到了.

在openvpn添加自己的路由后调用此脚本.要执行脚本,你需要设置script-security2允许从OpenVPN的背景下的bash脚本的执行.

谢谢

我要感谢github上这篇评论的作者,也感谢ovpn的支持.

  • 小心这个建议 - 如果您希望_all_流量通过VPN,此脚本将通过您之前(未受保护的)默认路由发送您的流量.OpenVPN添加了一个`_ 1`路由,它比_minm更具体.要真正完成这项工作,您需要删除`route-up`脚本中的默认路由,然后将其添加回`down`脚本.OpenVPN通过`$ route_net_gateway`,所以`ip route delete默认通过$ route_net_gateway`为`route-up`和`ip route add default通过$ route_net_gateway`为'down`. (8认同)

小智 21

如果在docker compose文件中定义子网CIDR,也可以使docker-compose工作:

networks:
  your-network:
   ipam:
      config:
      - subnet: 172.16.238.0/24
        gateway: 172.16.238.1
Run Code Online (Sandbox Code Playgroud)

另一个选项:首先使用子网CIDR创建网络,然后在docker compose文件中指定要使用此网络的文件:

docker network create your-network --subnet 172.24.24.0/24
Run Code Online (Sandbox Code Playgroud)

在您的docker撰写文件中:

networks:
  your-network:
    external: true
Run Code Online (Sandbox Code Playgroud)

  • 这是有效的,是一个更好的答案.谢谢! (3认同)
  • 网关:目前不适用于docker-compose V3.0。它是已知的限制,唯一的解决方法是坚持使用V2或使用建议的network create命令。 (3认同)

luc*_*yan 12

免责声明:

此解决方案最初是为下一个配置设计的:

  • Ubuntu 18.04
  • OpenVPN 2.4.4
  • Docker-CE 19.03.5
  • Docker-Compose 1.24.0
  • 桥接 IPV4 网络
  • 未使用 Docker-Swarm

并且可能因其他配置而异。


问题

启动您的 VPN 连接。


情况1

当您尝试重新启动 docker 守护进程时,您将进入日志:

failed to start daemon: Error initializing network controller: list bridge addresses failed: PredefinedLocalScopeDefaultNetworks
Run Code Online (Sandbox Code Playgroud)


案例二

当您尝试在以下情况下创建桥接网络(隐式dockerdocker-compose尝试创建此类网络)时:

  • docker create network 不定义子网参数
  • docker-compose up 不定义子网参数

你会得到:

ERROR: could not find an available, non-overlapping IPv4 address pool among the defaults to assign to the network
Run Code Online (Sandbox Code Playgroud)

解决方案 (TL;BPR)

  1. 私有地址空间中选择 docker 网络的地址范围,该地址范围不打算用于 VPN 内的资源。想象一下172.26.0.0/16

  2. 将更改添加到 Docker 的守护程序配置文件daemon.json文件。:

    {
        "bip": "172.26.0.1/17",
        "fixed-cidr": "172.26.0.0/17", 
        "default-address-pools" : [
            {
                "base" : "172.26.128.0/17",
                "size" : 24
            }
        ]
    }
    
    Run Code Online (Sandbox Code Playgroud)

    在哪里:

    • bip- 又名«bridge ip»:docker0桥接网络的特定桥接IP地址,如果其他未指定,则默认使用。
    • fixed-cidr-docker0接口和本地容器的CIDR 范围。仅当您想限制由 定义的 IP 范围时才需要bip
    • default-address-pools- docker_gwbridge(需要docker-swarm)接口和桥接网络的CIDR 范围。size参数设置此范围内新创建的网络的默认子掩码。


    在此示例中,我们将初始172.26.0.0/16范围除以 equal172.26.0.0 - 172.26.127.255172.26.128.0 - 172.26.255.255pools。

    daemon.json格式化时要小心,否则在重启docker的守护进程时会出现这样的错误

    unable to configure the Docker daemon with file /etc/docker/daemon.json
    
    Run Code Online (Sandbox Code Playgroud)
  3. 运行您的 VPN 连接
  4. 通过运行命令查找您的设备名称。通常它像tun0
    failed to start daemon: Error initializing network controller: list bridge addresses failed: PredefinedLocalScopeDefaultNetworks
    
    Run Code Online (Sandbox Code Playgroud)
  5. 显示创建的路由
    ERROR: could not find an available, non-overlapping IPv4 address pool among the defaults to assign to the network
    
    Run Code Online (Sandbox Code Playgroud)
  6. 找到与我们选择的地址重叠的池,让它成为:
    172.16.0.0/12 via 10.8.0.1
    
    Run Code Online (Sandbox Code Playgroud)
  7. 使用我们选择的 Docker 池在块上的子网上拆分该池172.26.0.0/16。您可以使用David C 的这个惊人的计算器。我们有:

    172.16.0.1/13
    172.24.0.1/15
    172.26.0.0/16
    172.27.0.1/16
    172.28.0.1/14
    
    Run Code Online (Sandbox Code Playgroud)
  8. 创建/etc/openvpn/mynetwork-route-up.sh脚本,用于 OpenVPN 从路由中排除我们的子网,内容如下(注意我们排除了我们的网络):

    {
        "bip": "172.26.0.1/17",
        "fixed-cidr": "172.26.0.0/17", 
        "default-address-pools" : [
            {
                "base" : "172.26.128.0/17",
                "size" : 24
            }
        ]
    }
    
    Run Code Online (Sandbox Code Playgroud)
  9. 创建/etc/openvpn/mynetwork-route-pre-down.sh包含以下内容的脚本(注意我们排除了我们的网络):

    unable to configure the Docker daemon with file /etc/docker/daemon.json
    
    Run Code Online (Sandbox Code Playgroud)
  10. 使该脚本可执行

    ip addr show type tun
    
    Run Code Online (Sandbox Code Playgroud)
  11. 将此行添加到.ovpn配置的末尾

    script-security 2
    route-up /etc/openvpn/mynetwork-route-up.sh
    route-pre-down /etc/openvpn/mynetwork-route-pre-down.sh
    
    Run Code Online (Sandbox Code Playgroud)
  12. 重启你的 OpenVPN

  13. 运行(用于删除守护进程重启时可能发生冲突的网络)

ip route show dev tun0
Run Code Online (Sandbox Code Playgroud)
  1. 重启 Docker 守护进程
    172.16.0.0/12 via 10.8.0.1
    
    Run Code Online (Sandbox Code Playgroud)

原因

OpenVPN 经常用于通过隧道或至少代理专用池路由所有流量。那么为什么 docker 会在启动时失败呢?

情况1

当您启动 Docker 守护进程时,它会检查守护进程的配置桥接网络是否与路由重叠(向上->向下堆栈跟踪):

正如您在此处看到的,您还可以禁用在守护程序配置中创建默认网桥网络以修复此错误。


案例二

当 Docker 的组件libnetwork尝试创建它的网络时,它会检查所有可用地址是否与路由重叠。如果没有找到,它会返回一个错误(向上->向下堆栈跟踪):


当然,也存在其他导致此错误的情况。需要把他们全都抓到!


解决方法(不推荐)

使用子网参数创建网络

Docker 允许您显式传递子网地址范围,并且在这种情况下似乎不执行重叠检查。

https://github.com/docker/libnetwork/blob/922cd533eac14b6e0754756c5cacf9f44af5d699/network.go#L1657


在 OpenVPN 停止时创建一个网络,然后启动它

我没有深入研究,但我认为,OpenVPN 不会检查重叠。


聚苯乙烯

谢谢(/sf/users/554291/)[jb]他的伟大的答案,它激发了我很多关于wrtiting这个答案。

对Docker的深度网络理解,可以阅读这篇文章:

另外,不要忘记这个

  • 很好的答案,有详尽的解释和参考。 (2认同)

ale*_*n13 7

根据Anas El Barkani的回答,这是使用PostgreSQL的完整分步示例。

在未连接VPN的情况下,创建一个永久的docker网络

docker network create my-network --subnet 172.24.24.0/24
Run Code Online (Sandbox Code Playgroud)

在docker-compose文件中,将network指定为external:

version: "2"
services: postgres: container_name: postgres image: postgres volumes: - ./volumes/postgres/data:/var/lib/postgresql/data environment: - POSTGRES_DB=dummy - POSTGRES_USER=user - POSTGRES_PASSWORD=123456 - POSTGRES_HOST=localhost networks: - default ports: - "127.0.0.1:5432:5432"
networks: default: external: name: my-network
Run Code Online (Sandbox Code Playgroud)

就这样。现在,您可以启用您的VPN,并照常启动/停止容器:

docker-compose up -d
docker-compose down
Run Code Online (Sandbox Code Playgroud)

无需每次都打开/关闭VPN,也不需要添加奇怪的脚本作为root用户。

  • 你是对的,但例如我们使用一个工具来创建所有容器,按项目自动连接所有东西。再次用于其他项目。我们不希望这些手动步骤减慢我们的开发人员的速度。他们每周更换项目。对于我们的案例,通过配置文件设置的 openvpn ip 范围是更可接受的解决方案。 (2认同)