如何使openvpn工作与docker

gstyhher  于 2022-12-26  发布在  Docker
关注(0)|答案(9)|浏览(116)

我最近安装了隐私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

禁用vpn解决了这个问题(但是我不想禁用它)。有什么办法可以让这两个系统和平共存吗?我使用debian杰西,我的openvpn有以下版本字符串

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

很多人通过禁用openvpn“解决”了这个问题,所以我特别问一下如何让这两个同时工作。
参考文献:

  1. https://stackoverflow.com/a/45377351/7918
  2. https://stackoverflow.com/a/42499393/7918
    如果这使任何差异我的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
0s0u357o

0s0u357o1#

溶液(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

向文件添加可执行位: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

解释

Openvpn为以下网络添加路由:0.0.0.0/1128.0.0.0/1(这些路由覆盖整个IP范围),Docker无法找到IP地址范围来创建自己的专用网络。
您需要添加一个默认路由(通过openvpn路由所有内容)并禁用这两个特定的路由。fix-routes脚本可以做到这一点。
这个脚本在openvpn添加了自己的路由后被调用,要执行这个脚本,你需要把script-security设置为2,这样就允许从openvpn上下文执行bash脚本。
谢谢
我要感谢github上这篇评论的作者,也要感谢ovpn support

kb5ga3dv

kb5ga3dv2#

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

networks:
  your-network:
   ipam:
      config:
      - subnet: 172.16.238.0/24
        gateway: 172.16.238.1

另一种选择:首先创建具有子网CIDR的网络,然后在Docker合成文件中指定要使用此网络:

docker network create your-network --subnet 172.24.24.0/24

在Docker合成文件中:

networks:
  your-network:
    external: true
ukxgm1gy

ukxgm1gy3#

基于answer from Anas El Barkani,这里是一个使用PostgreSQL的完整的分步示例。
当VPN未连接时,创建永久docker network

docker network create my-network --subnet 172.24.24.0/24

在Docker-compose文件中,将网络指定为外部:

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

现在您可以像往常一样启用您的VPN,并启动/停止container:

docker-compose up -d
docker-compose down

不需要打开/关闭VPN的每一次,或添加奇怪的脚本作为根。

wqsoz72f

wqsoz72f4#

免责声明:

此解决方案最初设计用于下一种配置:

  • Ubuntu 18.04
  • 开放虚拟专用网2.4.4
  • 对接器-CE 19.03.5
  • 对接器-合成1.24.0
  • 桥接IPV4网络
  • 未使用对接器群

并且对于其它配置可以不同。

问题

启动VPN连接。

    • 案例1**

当您尝试重新启动Docker守护进程时,您将在日志中获得:

failed to start daemon: Error initializing network controller: list bridge addresses failed: PredefinedLocalScopeDefaultNetworks
    • 案例二**

当您尝试在以下情况下创建网桥网络(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

溶液(TL;业务流程重新设计)

1.从private address space中选择Docker网络的地址范围,该范围不打算用于VPN内部的资源。假设它是172.26.0.0/16

  • 将更改添加到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
        }
    ]
}

其中:

      • bip**-又称"网桥IP":docker0网桥网络的特定网桥IP地址,如果未指定other,则默认使用该地址。
      • fixed-cidr**-docker0接口和本地容器的CIDR范围。仅当要限制bip定义的IP范围时才需要。
      • default-address-pools**-docker_gwbridgedocker-swarm需要)接口和网桥网络的CIDR范围。size参数设置此范围内新建网络的默认子掩码。

在此示例中,我们将初始172.26.0.0/16范围除以相等的172.26.0.0 - 172.26.127.255172.26.128.0 - 172.26.255.255池。
请小心daemon.json,否则在重新启动docker守护进程时会出现如下错误

unable to configure the Docker daemon with file /etc/docker/daemon.json
  • 运行VPN连接
  • 运行命令找到你的设备名,通常是tun0
ip addr show type tun
  • 显示创建的路线
ip route show dev tun0
  • 查找与所选地址重叠的池,将其设置为:
172.16.0.0/12 via 10.8.0.1
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
  • 创建/etc/openvpn/mynetwork-route-up.sh脚本,OpenVPN从路由中排除我们的子网,具有以下内容(请注意,我们排除了我们的网络):
#!/usr/bin/env bash

echo "Remove the route that conflicts with the Docker's subnet"
ip route del 172.16.0.0/12 via $route_vpn_gateway

echo "Bring back routes that don't intersect"
ip route add 172.16.0.0/13 via $route_vpn_gateway dev $dev
ip route add 172.24.0.0/15 via $route_vpn_gateway dev $dev
ip route add 172.27.0.0/16 via $route_vpn_gateway dev $dev
ip route add 172.28.0.0/14 via $route_vpn_gateway dev $dev
  • 创建包含以下内容的/etc/openvpn/mynetwork-route-pre-down.sh脚本(请注意,我们排除了网络):
#!/usr/bin/env bash

echo "Remove manually created routes"
ip route del 172.16.0.0/13 dev $dev
ip route del 172.24.0.0/15 dev $dev
ip route del 172.27.0.0/16 dev $dev
ip route del 172.28.0.0/14 dev $dev

echo "Creating original route because OpenVPN will try to del that"
ip route add 172.16.0.0/12 via $route_vpn_gateway dev $dev
  • 使脚本可执行
sudo chmod u+x /etc/openvpn/mynetwork-route-up.sh
sudo chmod u+x /etc/openvpn/mynetwork-route-pre-down.sh
  • 将以下行添加到.ovpn配置的末尾
script-security 2
route-up /etc/openvpn/mynetwork-route-up.sh
route-pre-down /etc/openvpn/mynetwork-route-pre-down.sh
  • 重新启动您的OpenVPN
  • 运行(用于删除守护程序重新启动时可能发生冲突的网络)
docker network prune

1.重新启动Docker守护程序

sudo service docker restart

原因

OpenVPN经常用来路由所有流量通过隧道,或至少,代理私有池.那么为什么Docker失败,当它启动?

    • 案例1**

当您启动Docker守护进程时,它会检查守护进程的配置网桥网络是否与路由重叠(up-〉down stacktrace):

  • docker-ce/组件/引擎/守护进程/守护进程。go:新守护进程
  • docker-ce/组件/引擎/守护进程/守护进程. go:恢复
  • docker-ce/组件/引擎/守护进程/守护进程_unix. go:initNetworkController
  • docker-ce/组件/引擎/守护进程/守护进程_unix. go:初始化桥接驱动程序
  • docker-ce/components/engine/vendor/github.com/docker/libnetwork/netutils/utils_linux.go:ElectInterfaceAddresses
  • docker-ce/components/engine/vendor/github.com/docker/libnetwork/netutils/utils_linux.go:FindAvailableNetwork
  • docker-ce/components/engine/vendor/github.com/docker/libnetwork/netutils/utils_linux.go:CheckRouteOverlaps
  • docker-ce/components/engine/vendor/github.com/docker/libnetwork/netutils/utils.go
  • 💥💥💥

正如您在这里看到的,您也可以在守护进程配置中禁用创建默认网桥网络来修复此错误。

    • 案例二**

当Docker的组件libnetwork尝试创建它的网络时,它会检查所有可用地址是否与路由重叠。如果没有发现,它会返回一个错误(up-〉down stacktrace):

  • [docker-ce/组件/引擎/守护进程/网络。go:创建网络]
  • docker-ce/components/engine/vendor/github.com/docker/libnetwork/controller.go:NewNetwork
  • docker-ce/components/engine/vendor/github.com/docker/libnetwork/network.go:ipamAllocate
  • docker-ce/components/engine/vendor/github.com/docker/libnetwork/network.go:ipamAllocateVersion
  • docker-ce/components/engine/vendor/github.com/docker/libnetwork/network.go:requestPoolHelper
  • docker-ce/components/engine/vendor/github.com/docker/libnetwork/ipam/allocator.go:RequestPool
  • docker-ce/components/engine/vendor/github.com/docker/libnetwork/ipam/allocator.go:getPredefinedPool
  • 💥💥💥

当然,其他情况下得到这个错误也存在。必须抓住他们所有!

变通方法(不推荐)

    • 使用子网参数创建网络**

Docker允许您显式传递子网地址范围,在这种情况下似乎不执行重叠检查。
https://github.com/docker/libnetwork/blob/922cd533eac14b6e0754756c5cacf9f44af5d699/network.go#L1657

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

我不深潜,但我认为,OpenVPN不检查重叠.

附言

谢谢(https://stackoverflow.com/users/7918/jb)[jb][jb]) for his great answer,写这个答案给了我很多启发。
要深入了解Docker的网络,您可以阅读以下文章:

还有,don't forget this!

yyyllmsg

yyyllmsg5#

导致问题的默认路由被推到OpenVPN客户端的OpenVPN服务器.
与其创建一个脚本来删除路由,不如从一开始就停止创建有问题的路由。
有两种方法可以做到这一点:
1.如果您可以更改OpenVPN服务器上的设置,请编辑配置并删除redirect-gateway选项.在我的EdgeRouter上,相关行如下所示:
openvpn-option "--push redirect-gateway def1"
一个Linux服务器,我相信它看起来像这样:
push "redirect-gateway def1"
1.如果您不能更改OpenVPN服务器上的设置,您可以告诉您的OpenVPN客户端忽略从服务器推送的路由.在我的Linux客户端上,相关行看起来像这样:
pull-filter ignore redirect-gateway
一旦你做了这些更改,并重新启动OpenVPN服务,你应该能够启动Docker容器没有可怕的could not find an available, non-overlapping IPv4 address错误.

wnvonmuf

wnvonmuf6#

也许一种方法是将除www.example.com以外的所有路由添加172.16.0.0/12到通过VPN的路由中,这样我们就可以确保所有传出的路由都得到了正确处理:

sudo ip route add 192.0.0.0/2 via $route_vpn_gateway
sudo ip route add 128.0.0.0/3 via $route_vpn_gateway
sudo ip route add 176.0.0.0/4 via $route_vpn_gateway
sudo ip route add 160.0.0.0/5 via $route_vpn_gateway
sudo ip route add 168.0.0.0/6 via $route_vpn_gateway
sudo ip route add 174.0.0.0/7 via $route_vpn_gateway
sudo ip route add 173.0.0.0/8 via $route_vpn_gateway
sudo ip route add 172.128.0.0/9 via $route_vpn_gateway
sudo ip route add 172.64.0.0/10 via $route_vpn_gateway
sudo ip route add 172.32.0.0/11 via $route_vpn_gateway
sudo ip route add 172.0.0.0/12 via $route_vpn_gateway

# And finally delete the default route which handle 172.16.0.0/12
sudo ip route del 128.0.0.0/1 via $route_vpn_gateway
irlmq6kh

irlmq6kh7#

对我有效的方法:看过之后

Creating network "airflow_default" with the default driver
ERROR: could not find an available, non-overlapping IPv4 address pool 
among the defaults to assign to the network

只需手动创建网络:

docker network create airflow_default --subnet 172.24.24.0/24
lymnna71

lymnna718#

这里有一些额外的背景:0.0.0.0和128.0.0.0路由仅在OpenVPN服务器(又称访问服务器)配置为推送路由,以通过VPN发送端点的所有Internet流量。通过添加这些宽路由,可以路由用户的Internet流量,而不会干扰本地LAN上的路由,并且确保端点保持能够将OpenVPN业务本身路由到本地路由器。
如果不需要通过OpenVPN服务器发送所有的互联网流量,您最好让您的VPN管理员创建一个配置文件,只通过VPN将流量路由到所需的目的地(如私有IP地址范围),而不是所有的目的地。

ego6inou

ego6inou9#

基于the answer from alexanderlukanin13。它对我的docker-compose文件版本有效:“3.8”。我从文档中添加了一个使用预先存在的网络。
1.关闭OpenVPN连接。
1.创建自定义Docker网络:第一个月
1.在Docker-compose文件的底部:

version: "3.8"

services:
...

volumes:
...

networks:
  default:
    name: your-network
    external: true

1.打开OpenVPN连接
之后:sudo docker compose -f docker-compose.yml up -d --build正常工作,没有错误:
failed to create network your-network-name_default: Error response from daemon: could not find an available, non-overlapping IPv4 address pool among the defaults to assign to the network

相关问题