背景
OpenClaw 部署在本地服务器(无固定公网 IP),QQ Bot 开放平台要求配置 IP 白名单。通过 WireGuard VPN 将 OpenClaw 容器的出口流量从 VPS(固定公网 IP)出去,从而满足白名单要求。
架构
OpenClaw容器 → Docker网络 → 宿主机策略路由 → WireGuard隧道 → VPS → 互联网
(172.18.0.x) (10.10.0.2) (10.10.0.1)
出口IP = 43.138.233.89
- 只有 OpenClaw 容器的流量走 VPN,宿主机和其他容器不受影响
- 不需要修改 OpenClaw 容器,更新版本无需重新配置
环境信息
| 角色 | IP | 系统 |
|---|---|---|
| VPS | 43.138.233.89 | OpenCloudOS (内核 5.4) |
| 本地服务器 | 动态 IP | Debian |
| WireGuard VPS 端 | 10.10.0.1 | - |
| WireGuard 本地端 | 10.10.0.2 | - |
| OpenClaw 容器 | 172.18.0.x (动态) | Docker |
一、VPS 端配置
1.1 开启内核转发
echo "net.ipv4.ip_forward = 1" >> /etc/sysctl.conf
sysctl -p1.2 生成密钥
mkdir -p /root/wireguard/config
cd /root/wireguard
# 用 Docker 生成(或手动生成后放入 config 目录)
docker run --rm -i masipcat/wireguard-go wg genkey > config/privatekey
docker run --rm -i masipcat/wireguard-go wg pubkey < config/privatekey > config/publickey1.3 创建 WireGuard 配置
cat > config/wg0.conf << EOF
[Interface]
PrivateKey = <VPS私钥内容>
Address = 10.10.0.1/24
ListenPort = 51820
PostUp = iptables -t nat -A POSTROUTING -s 10.10.0.0/24 -o eth0 -j MASQUERADE
PostDown = iptables -t nat -D POSTROUTING -s 10.10.0.0/24 -o eth0 -j MASQUERADE
[Peer]
PublicKey = <本地服务器公钥>
AllowedIPs = 10.10.0.2/32
EOF注意:
eth0需替换为 VPS 实际网卡名(用ip -o -4 route show default | awk '{print $5}'查看)。
1.4 Docker Compose 部署
cat > docker-compose.yml << 'EOF'
services:
wireguard:
image: masipcat/wireguard-go:latest
container_name: wireguard
cap_add:
- NET_ADMIN
network_mode: host
volumes:
- /dev/net/tun:/dev/net/tun
- ./config:/etc/wireguard
environment:
- WG_COLOR_MODE=always
- LOG_LEVEL=info
restart: always
EOF关键: 必须使用
network_mode: host,否则 wg0 在容器内部,宿主机看不到,NAT 转发不生效。使用network_mode: host后不能配置sysctls和ports,需在宿主机上手动设置。
1.5 启动并验证
docker compose up -d
docker logs wireguard
# 确认 wg0 在宿主机可见
ip a show wg01.6 添加 iptables 转发规则
如果日志中的 iptables MASQUERADE 因 iptables 版本问题未生效,手动在宿主机添加:
iptables -t nat -A POSTROUTING -s 10.10.0.0/24 -o eth0 -j MASQUERADE
iptables -I FORWARD -i wg0 -j ACCEPT
iptables -I FORWARD -o wg0 -j ACCEPT1.7 持久化 iptables 规则
yum install -y iptables-services
iptables-save > /etc/sysconfig/iptables
systemctl enable iptables1.8 安全组
腾讯云安全组放行 UDP 51820 端口。
二、本地服务器配置
2.1 安装 WireGuard
apt install -y wireguard2.2 生成密钥
wg genkey | tee /etc/wireguard/client_private | wg pubkey > /etc/wireguard/client_public将 client_public 的内容填入 VPS 配置的 [Peer] PublicKey。
2.3 创建 WireGuard 配置
CLIENT_KEY=$(cat /etc/wireguard/client_private)
cat > /etc/wireguard/wg0.conf << EOF
[Interface]
PrivateKey = $CLIENT_KEY
Address = 10.10.0.2/24
Table = off
[Peer]
PublicKey = <VPS公钥>
Endpoint = 43.138.233.89:51820
AllowedIPs = 0.0.0.0/0
PersistentKeepalive = 25
EOF关键配置说明:
Table = off:防止 WireGuard 覆盖宿主机默认路由,避免所有流量走 VPNAllowedIPs = 0.0.0.0/0:允许所有目标地址的流量通过隧道(配合策略路由只让特定容器走)
2.4 启动 WireGuard
wg-quick up wg0
# 验证隧道连通
ping -c 3 10.10.0.12.5 设置开机自启
systemctl enable wg-quick@wg0三、策略路由(只让 OpenClaw 容器走 VPN)
3.1 添加路由表
grep -q "wgvpn" /usr/share/iproute2/rt_tables || echo "100 wgvpn" >> /usr/share/iproute2/rt_tablesrt_tables 位置可能不同,用
find / -name "rt_tables" 2>/dev/null查找。
3.2 配置策略路由
CONTAINER_IP=$(docker inspect 1Panel-openclaw-GCbN --format='{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}')
ip route add default dev wg0 table wgvpn
ip rule add from $CONTAINER_IP table wgvpn3.3 验证
# 容器走 VPN — 应返回 43.138.233.89
docker exec -it 1Panel-openclaw-GCbN curl -s --max-time 5 ifconfig.me
# 宿主机不走 VPN — 应返回本地 IP
curl -s --max-time 5 ifconfig.me3.4 持久化策略路由
cat > /opt/openclaw-vpn-route.sh << 'SCRIPT'
#!/bin/bash
CONTAINER_IP=$(docker inspect 1Panel-openclaw-GCbN --format='{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}')
if [ -z "$CONTAINER_IP" ]; then
echo "Container not running"
exit 1
fi
ip route replace default dev wg0 table wgvpn
ip rule del from $CONTAINER_IP table wgvpn 2>/dev/null
ip rule add from $CONTAINER_IP table wgvpn
echo "VPN route set for $CONTAINER_IP"
SCRIPT
chmod +x /opt/openclaw-vpn-route.sh
cat > /etc/systemd/system/openclaw-vpn-route.service << 'EOF'
[Unit]
Description=OpenClaw VPN Route
After=wg-quick@wg0.service docker.service
Requires=docker.service
[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/opt/openclaw-vpn-route.sh
ExecStartPre=/bin/sleep 10
[Install]
WantedBy=multi-user.target
EOF
systemctl daemon-reload
systemctl enable openclaw-vpn-route四、OpenClaw 容器 DNS 配置
问题
容器默认使用本地 ISP 的 DNS,会将 api.sgroup.qq.com 解析到本地运营商优化的 IP(如 111.31.x.x)。流量走 VPN 从 VPS 出去后,这些 IP 无法从腾讯云网络访问,导致 QQ API 请求超时。
解决方案
在 OpenClaw 的 docker-compose 文件中(通过 1Panel 管理),为 OpenClaw 容器单独指定 DNS,不影响其他容器:
services:
openclaw:
# ... 现有配置保持不变 ...
dns:
- 119.29.29.29
- 8.8.8.8119.29.29.29:腾讯 DNSPod,会返回腾讯云友好的 IP8.8.8.8:Google DNS,作为备用
验证
# 确认 DNS 配置生效
docker exec -it 1Panel-openclaw-GCbN cat /etc/resolv.conf
# 确认能连通 QQ API
docker exec -it 1Panel-openclaw-GCbN curl --max-time 5 -I https://api.sgroup.qq.com注意: 修改 compose 文件后容器会重建,IP 可能变化,需重新执行策略路由脚本:
/opt/openclaw-vpn-route.sh
五、QQ Bot 白名单
在 QQ 开放平台的 IP 白名单中填入 VPS 公网 IP:43.138.233.89
六、日常维护
查看 WireGuard 状态
# 本地
wg show
# VPS
docker exec wireguard wg showOpenClaw 容器重启/更新后
如果容器 IP 变化,重新执行策略路由脚本:
/opt/openclaw-vpn-route.sh故障排查
# 1. 检查隧道是否连通
ping -c 3 10.10.0.1
# 2. 检查容器出口 IP
docker exec -it 1Panel-openclaw-GCbN curl -s --max-time 5 ifconfig.me
# 3. 检查 WireGuard 握手状态
wg show
# 4. VPS 端检查
docker logs wireguard
ip a show wg0
iptables -t nat -L POSTROUTING -v -n | grep 10.10
iptables -L FORWARD -v -n | grep wg0
# 5. DNS 相关排查(QQ API 超时时检查)
docker exec -it 1Panel-openclaw-GCbN cat /etc/resolv.conf
docker exec -it 1Panel-openclaw-GCbN curl --max-time 5 -I https://api.sgroup.qq.com七、安全提醒
- WireGuard 私钥务必保密,不要泄露在聊天记录中
- 如密钥已泄露,重新生成密钥对并更新两端配置
- VPS 安全组只放行必要端口(UDP 51820)
Sources:
- QQBot GitHub ⭐️