因此,我有以下示例撰写文件,其中包含自定义网络:
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: service
Ubuntu 容器将通过 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