Docker 容器通过主机 VPN 接口短暂路由后失去连接

Docker 容器通过主机 VPN 接口短暂路由后失去连接

因此,我有以下示例撰写文件,其中包含自定义网络:

version: '3.7'
services:
  ubuntu:
    image: ubuntu
    restart: unless-stopped
    tty: true
    networks:
      wireguard:
        ipv4_address: 172.18.0.2
networks:
  wireguard:
    driver: bridge
    driver_opts:
      com.docker.network.bridge.name: 'wireguard'
    ipam:
      driver: default
      config:
        - subnet: 172.18.0.0/16

以下 Wireguard 配置定义为wg0.conf

[Interface]
Table = off
SaveConfig = false
PrivateKey = {Client Private Key}
Address = 10.8.0.21/32
DNS = 10.8.0.1

# And create routing manually only for WG related communication.
PostUp = iptables -t mangle -I PREROUTING 1 -i wg0 -m conntrack --ctstate NEW -j CONNMARK --set-mark 2
PostUp = iptables -t mangle -I OUTPUT 1 -m connmark --mark 2 -j CONNMARK --restore-mark
PostUp = iptables -t mangle -I PREROUTING 2 -m connmark --mark 2 -j CONNMARK --restore-mark
PostUp = ip rule add fwmark 2 lookup 2
PostUp = ip rule add table main suppress_prefixlength 0
PostUp = ip route add default dev wg0 table 2
PostUp = sysctl -q net.ipv4.conf.all.src_valid_mark=1
PostUp = sysctl -w net.ipv4.conf.wg0.rp_filter=2

# Removal when `wg0` goes down
PostDown = iptables -t mangle -D PREROUTING -i wg0 -m conntrack --ctstate NEW -j CONNMARK --set-mark 2
PostDown = iptables -t mangle -D OUTPUT -m connmark --mark 2 -j CONNMARK --restore-mark
PostDown = iptables -t mangle -D PREROUTING -m connmark --mark 2 -j CONNMARK --restore-mark
PostDown = ip rule del table main suppress_prefixlength 0
PostDown = ip rule flush table 2

[Peer]
PublicKey = {VPN Server Public Key}
AllowedIPs = 10.8.0.1/32,0.0.0.0/0
Endpoint = {VPN Server Connection Endpoint}
PersistentKeepalive = 25

现在已设置 wireguard 连接以将传入连接路由回 wg0 接口,以避免所有客户端连接都通过 VPN。

所以现在我的目标是具体的docker 容器通过 VPN 连接路由其连接。因此,我所做的是在主机 shell 中运行以下规则和路由以添加到现有表中:

# ip rule add from 172.18.0.0/16 lookup 2
# ip route add 172.18.0.0/16 dev wg0 table 2

如果我进入 docker shell 并检查连接,它可以完美运行并显示 VPN 服务器的 IP: docker 容器内的 ping 和 ip

但大约 30 秒到 5 分钟后,我无法建立连接,并且任何连接尝试都会超时: 没有连接docker容器

如果我 tcpdump 桥接网络,它只会继续尝试对 172.18.0.1 发出 ARP 请求: tcpdump 容器桥接

我不知道为什么会发生这种情况,也不知道该如何解决。我看过几篇帖子和论坛,有人通过特定接口路由 docker 网络连接,所以我不知道我是否在其他地方做错了什么。

答案1

我认为正确的做法是在单独的 Docker 容器中运行 VPN,然后通过该 VPN 连接其他 Docker 容器。这至少是最佳做法。

docker compose 示例:

---
version: "3.7"
services:
  wireguard:
    image: lscr.io/linuxserver/wireguard:latest
    container_name: wireguard
    cap_add:
      - NET_ADMIN
      - SYS_MODULE #optional
    environment:
      - PUID=1000
      - PGID=1000
      - TZ=Etc/UTC
      - SERVERURL=wireguard.domain.com #optional
      - SERVERPORT=51820 #optional
      - PEERS=1 #optional
      - PEERDNS=auto #optional
      - INTERNAL_SUBNET=10.13.13.0 #optional
      - ALLOWEDIPS=0.0.0.0/0 #optional
      - PERSISTENTKEEPALIVE_PEERS= #optional
      - LOG_CONFS=true #optional
    volumes:
      - /path/to/appdata/config:/config
      - /lib/modules:/lib/modules #optional
    ports:
      - 51820:51820/udp
    sysctls:
      - net.ipv4.conf.all.src_valid_mark=1
    restart: unless-stopped
   

  ubuntu:
    image: ubuntu
    restart: unless-stopped
    tty: true
    network_mode: service:wireguard

使用network_mode: serviceUbuntu 容器将通过 WireGuard 容器与 vpn 客户端连接。服务:这允许容器与另一个服务共享网络命名空间。您指定服务名称,容器将使用相同的网络堆栈。


您也可以使用network_mode: host网络

答案2

因此很可能是规则优先级导致了奇怪的 ARP 问题,设置以下优先级可以解决问题:

ip rule add table main suppress_prefixlength 0 prio 9999
ip rule add fwmark 2 lookup 2 prio 10000
ip rule add from 172.18.0.0/16 lookup 2 prio 11000

相关内容