VPS 流量转发配置
基于 Xray + Nginx SNI 分流 + Mihomo TUN 透明代理 + WireGuard,实现: 内网服务反向代理、多 VPS 链路中转、BT 透明代理、Minecraft UDP 转发。
设备
| 设备 | IP / 域名 | 角色 |
|---|---|---|
| 北京 VPS | salmonstill.cn / 49.232.242.90 |
公网入口,Nginx + Xray + socat + WireGuard |
| 搬瓦工 VPS | 67.230.189.235 |
代理出口,Xray Reality 入站(客户端直连) |
| 旁路由 | 192.168.1.199 / WG 10.0.0.2 |
内网核心,Xray bridge + Mihomo 代理 |
| NAS | 192.168.1.188 |
绿联云 UGOS,思源笔记等服务 |
| qBittorrent | 192.168.1.200 (macvlan) |
PT 下载,独立 IP |
| Windows | 192.168.1.177 |
内网办公,SSH |
| Spark | 192.168.1.166 |
Ubuntu 主机,本地 TUN 代理 |
| iPhone | WG 10.0.0.3 |
WireGuard 客户端,远程访问内网 |
| Mac | WG 10.0.0.4 |
WireGuard 客户端,远程访问内网 |
Nginx SNI 分流 (北京vps-stream.conf)
端口 443 — 公网入口,按 SNI 分发流量:
| SNI | 后端 | 端口 | 用途 |
|---|---|---|---|
www.apple.com / www.samsung.com / www.amd.com / www.asus.com |
Xray interconn | :9443 | 反向代理隧道(4 SNI leastPing 轮换) |
www.bilibili.com |
Xray proxy_from_lan | :9445 | 北京直连代理(qBittorrent 出站) |
drive.salmonstill.cn |
NAS | :38653 | 绿联云直接转发 |
| 默认 | NPM | :8443 | Nginx Proxy Manager |
端口 9447 — 数据中心回落:Reality 探针/探测流量回落到此,按 SNI 代理到真实网站。
搬瓦工 VPS(部署 代理vps-stream.conf + xray-代理服务器-config.json):www.cloudflare.com → Xray :9443,默认 → NPM。
Xray 核心
北京 VPS (xray-北京vps-config.json)
Reality 入站 — 共享 privateKey GGT9LfN_...,由 Nginx SNI 转发:
| Tag | 端口 | serverNames | Reality target | 说明 |
|---|---|---|---|---|
interconn |
:9443 | apple/samsung/amd/asus 4 SNI leastPing 轮换 | 127.0.0.1:9447 |
反向隧道,多 SNI 防封 + 数据中心回落 |
proxy_from_lan |
:9445 | www.bilibili.com |
www.bilibili.com:443 |
北京直连代理(qBittorrent) |
mihomo_in(旧 Mihomo 中转)已删除,客户端直接连接搬瓦工。
dokodemo-door 入站 — 端口转发到旁路由反向隧道,共 11 个:
| Tag | 公网端口 | 路由目标 |
|---|---|---|
external |
38653 | → portal → NAS :9443 |
external_siyuan |
38654 | → portal → NAS :5005 |
external_minecraft |
39132 | → portal → 旁路由 :39132 |
external_wsl |
38655 | → portal → Windows :22 |
external_nas_ssh |
38656 | → portal → NAS :22 |
external_router_ssh |
38657 | → portal → 旁路由 :22 |
external_spark_ssh |
38659 | → portal → Spark (166) :22 |
external_spark_rdp |
38660 | → portal → Spark (166) :3389 |
external_win_rdp |
38664 | → portal → Windows (177) :3389 |
external_spark_38662 |
38662 | → portal → Spark (166) :38662 |
external_router_web |
39766 | → portal → 旁路由 :80 |
external_tmp |
8501 | → portal → Windows :8501 |
external_gitea |
38661 | → portal → NAS :3000 |
external_222 |
222 | → portal → NAS :222 |
external_qbit |
51413 | → portal → qBittorrent :51413 |
其他入站:
| Tag | 端口 | 类型 | 用途 |
|---|---|---|---|
socks-dynamic |
38658 | SOCKS5 (password) | 动态 LAN 端口访问 |
出站:direct(freedom 直连)
路由:所有 external_* + interconn + socks-dynamic → portal(反向隧道);interconn 探测流量(baidu.com)→ direct;proxy_from_lan → direct
mihomo_in+proxy_in+to_tokyo旧中转链路(北京→搬瓦工),已删除。
旁路由 (xray-旁路由-config.json)
Bridge 入站:与北京 VPS 的 Portal 建立永久反向隧道。
出站(14 个):
| Tag | 目标 | 用途 |
|---|---|---|
to_nas |
192.168.1.188:9443 |
NAS 管理 |
to_siyuan |
192.168.1.188:5005 |
思源笔记 |
to_wsl |
192.168.1.177:22 |
WSL SSH |
to_nas_ssh |
192.168.1.188:22 |
NAS SSH |
to_router_ssh |
192.168.1.199:22 |
旁路由 SSH |
to_router_web |
192.168.1.199:80 |
旁路由 Web |
to_minecraft |
127.0.0.1:39132 |
Minecraft 服务 |
to_tmp |
192.168.1.177:8501 |
临时服务 |
to_3000 |
192.168.1.188:3000 |
Web 服务 |
to_222 |
192.168.1.188:222 |
备用服务 |
to_qbit |
192.168.1.200:51413 |
qBittorrent 入站 |
to_spark_ssh |
192.168.1.166:22 |
Spark SSH 远程 |
to_spark_rdp |
192.168.1.166:3389 |
Spark xRDP 桌面远程 |
to_spark_38662 |
192.168.1.166:38662 |
Spark 自定义服务 |
interconn-apple/samsung/mozilla |
VLESS+Reality → salmonstill.cn:443 (多 SNI 轮换) |
隧道链接(balancer + leastPing + fallback) |
to_beijing_direct |
VLESS+Reality → salmonstill.cn:443 (SNI=www.bilibili.com) |
北京直连 |
direct |
freedom | 直连 |
路由规则(bridge 入站按端口匹配):
- 38653 →
to_nas(NAS 管理) - 38654 →
to_siyuan - 38655 →
to_wsl - 38656 →
to_nas_ssh - 38657 →
to_router_ssh - 8501 →
to_tmp - 39766 →
to_router_web - 38661 →
to_3000 - 222 →
to_222 - 39132 →
to_minecraft - 51413 →
to_qbit - 38658 →
direct(SOCKS5 动态回家,直接连接目标地址) - 38659 →
to_spark_ssh(Spark SSH 远程) - 38660 →
to_spark_rdp(Spark xRDP 桌面远程) - 38662 →
to_spark_38662 - 38664 →
to_win_rdp(Windows 远程桌面) - 38665 →
to_spark_3080(Spark Web 3080) - 默认(catch-all)→
direct(不匹配端口规则的动态请求直连目标) socks-lan入站 →to_beijing_direct
所有显式端口规则优先于 catch-all,现有端口转发不受影响。
搬瓦工 VPS (xray-代理服务器-config.json)
极简:VLESS+Reality 入站 :9443(SNI=www.cloudflare.com, dest=www.cloudflare.com),freedom 出站。
所有客户端(Spark、旁路由、macOS)直连此服务器,不再经北京 VPS 中转。
Mihomo
旁路由 (旁路由的mihomo config.yaml)
纯代理模式 — 无内核级劫持,提供多端口代理服务供客户端手动指定:
| 端口 | 类型 | 路由 | 用途 |
|---|---|---|---|
7890 |
mixed | 按规则分流 | 本地服务默认代理 |
7891 |
mixed | 全部走 US-Direct | 全局国外代理 |
7892 |
mixed | 全部直连 | 全局国内直连 |
配合 fake-ip DNS(enhanced-mode: fake-ip),DNS 请求返回 198.18.x.x 假 IP,强制流量进入代理路由。
代理节点:
US-Direct— VLESS+Reality →67.230.189.235:443(默认国外出口,客户端直连搬瓦工,SNI=www.cloudflare.com)
Xray-Real代理节点(经北京 VPS 中转)已移除,Mihomo 全部直连搬瓦工。
关键策略组:
- 国外 →
[US-Direct, 直连]
防死循环 IP:49.232.242.90(北京 VPS)、67.230.189.235(搬瓦工 VPS)强制直连。
额外监听器::7891(全局→US-Direct)、:7892(强制直连)
macOS (非tun模式的主机mihomo config.yaml)
结构与旁路由一致,无 TUN,监听器 :7890 + :7891 + :7892。
重启(launchctl 管理):
launchctl unload ~/Library/LaunchAgents/com.mihomo.proxy.plist
launchctl load ~/Library/LaunchAgents/com.mihomo.proxy.plist
Ubuntu / Spark (tun模式的主机mihomo config.yaml)
本地 TUN 模式(stack: system),不依赖旁路由网关。设备重启后 auto-route 自建路由表,稳定可靠。监听器 :7890 + :7891 + :7892,节点直连 US-Direct。
qBittorrent 透明代理
架构总览
出站(SOCKS5 代理)
qBittorrent(192.168.1.200) 互联网
↓ SOCKS5 旁路由:1080 (socks-lan) ↑
↓ Xray routing → to_beijing_direct │
↓ Reality(VLESS, SNI=www.bilibili.com) │
↓ 北京VPS:443 → Nginx分流 │
↓ proxy_from_lan:9445 → direct(freedom) ─────────────────┘
入站(端口转发)
Peer → 北京VPS:51413 → external_qbit → portal
→ bridge隧道 → 旁路由 → to_qbit → 192.168.1.200:51413
设备清单
| 设备 | IP | 角色 |
|---|---|---|
| 北京VPS | salmonstill.cn / 49.232.242.90 |
公网出口 + 入站入口 |
| 旁路由 | 192.168.1.199 |
Xray 桥接 + SOCKS5 代理 |
| NAS | 192.168.1.188 |
Docker 宿主机 |
| qBittorrent 容器 | 192.168.1.200 |
macvlan 独立 IP,PT 专用 |
第一部分:北京 VPS 配置
1.1 Nginx Stream SNI 分流 beijing-vps-stream.conf
新增 www.bilibili.com SNI 映射(用于旁路由 Mihomo 直连代理):
stream {
map $ssl_preread_server_name $backend {
www.apple.com xray; # 旁路由反向代理隧道
www.microsoft.com mihomo; # 外部客户端代理 → 东京出口
www.bilibili.com xray_lan; # 旁路由 Mihomo 北京直连代理
drive.salmonstill.cn nas; # 绿联云服务
default npm; # Nginx Proxy Manager
}
upstream xray { server 127.0.0.1:9443; }
upstream mihomo { server 127.0.0.1:9444; }
upstream xray_lan { server 127.0.0.1:9445; } # 新增
upstream nas { server 127.0.0.1:38653; }
upstream npm { server 127.0.0.1:8443; }
server {
listen 443 reuseport;
listen [::]:443 reuseport;
ssl_preread on;
proxy_pass $backend;
}
}
1.2 Xray 配置 xray-北京vps-config.json
新增入站 proxy_from_lan(北京直连出口)
{
"tag": "proxy_from_lan",
"listen": "127.0.0.1",
"port": 9445,
"protocol": "vless",
"settings": {
"clients": [
{
"id": "113e167a-a2be-4b46-9010-60020108626c",
"flow": "xtls-rprx-vision"
}
],
"decryption": "none"
},
"streamSettings": {
"network": "raw",
"security": "reality",
"realitySettings": {
"show": false,
"target": "www.apple.com:443",
"serverNames": ["www.bilibili.com"],
"privateKey": "GGT9LfN_2JdQG68cwrULgUK-adfT6wIokLzWjaB0fXs",
"shortIds": ["7c947a71b94f369e"]
}
}
}
Reality 公私钥复用已有的
interconn入站 keypair,serverNames用新的www.bilibili.com与 Nginx 对应。target设为www.apple.com:443,Reality 从此地址偷取真实 TLS 证书用于伪装。
新增入站 external_qbit(BT 入站端口)
{
"tag": "external_qbit",
"listen": "0.0.0.0",
"port": 51413,
"protocol": "dokodemo-door",
"settings": {
"address": "127.0.0.1",
"port": 51413,
"network": "tcp"
}
}
仅 TCP——Xray portal 反向代理对 UDP 支持不完善,BT 的 μTP(UDP) 走不了,需要在 qBittorrent 里关闭。
新增路由规则
{ "type": "field", "inboundTag": ["proxy_from_lan"], "outboundTag": "direct" },
{ "type": "field", "inboundTag": ["external_qbit"], "outboundTag": "portal" }
1.3 腾讯云防火墙
新开端口:
| 端口 | 协议 | 用途 |
|---|---|---|
| 51413 | TCP | BT 入站 |
第二部分:旁路由 Xray SOCKS5 出站代理
2.1 配置 xray-旁路由-config.json
qBittorrent 出站不走 Mihomo 透明代理,而是通过旁路由上 Xray 的 socks-lan 入站(:1080),直接转发到北京 VPS 直连出口。
SOCKS5 入站
{
"tag": "socks-lan",
"port": 1080,
"listen": "0.0.0.0",
"protocol": "socks",
"settings": {
"auth": "noauth",
"udp": true
}
}
出站 to_beijing_direct
{
"tag": "to_beijing_direct",
"protocol": "vless",
"settings": {
"vnext": [
{
"address": "salmonstill.cn",
"port": 443,
"users": [
{
"id": "113e167a-a2be-4b46-9010-60020108626c",
"flow": "xtls-rprx-vision",
"encryption": "none"
}
]
}
]
},
"streamSettings": {
"network": "raw",
"security": "reality",
"realitySettings": {
"fingerprint": "chrome",
"serverName": "www.bilibili.com",
"publicKey": "62y5gDjPrdeuePGl-D2IW4Cw9Kb8_bSBBTmArvL7Nhs",
"shortId": "7c947a71b94f369e"
}
}
}
路由规则
{ "type": "field", "inboundTag": ["socks-lan"], "outboundTag": "to_beijing_direct" }
路径:
qBittorrent → SOCKS5 旁路由:1080 → to_beijing_direct → 北京VPS:443(SNI=www.bilibili.com) → proxy_from_lan:9445 → direct → 互联网
第三部分:旁路由 Xray 51413 转发
3.1 配置 xray-旁路由-config.json
新增加出站 to_qbit
{
"tag": "to_qbit",
"protocol": "freedom",
"settings": {
"redirect": "192.168.1.200:51413"
}
}
新增路由规则
{
"type": "field",
"inboundTag": ["bridge"],
"port": "51413",
"outboundTag": "to_qbit"
}
放在 bridge 下——从北京 VPS 的 portal 通过反向隧道过来的 BT 入站流量,由 bridge 接收后按端口 51413 匹配到此规则,转发到 qBittorrent 容器。
第四部分:NAS qBittorrent Docker
4.1 创建 macvlan 网络
docker network create -d macvlan \
--subnet=192.168.1.0/24 \
--gateway=192.168.1.199 \
--ip-range=192.168.1.200/32 \
-o parent=eth0 \
qbit_macvlan
--gateway=192.168.1.199:qBittorrent 的默认网关设为旁路由,确保出站流量经过旁路由。--ip-range=192.168.1.200/32:固定 IP。
4.2 启动容器
docker run -d \
--name qbittorrent \
--network qbit_macvlan \
--ip 192.168.1.200 \
-e WEBUI_PORT=8090 \
-p 8090:8090 \
-v /path/to/downloads:/downloads \
lscr.io/linuxserver/qbittorrent:latest
4.3 qBittorrent 设置
| 设置项 | 值 |
|---|---|
| 监听端口 | 51413 |
| UPnP/NAT-PMP | 禁用 |
| SOCKS5 代理 | 192.168.1.199 / 端口 1080 |
| 连接协议 | 仅 TCP(关闭 μTP) |
| DHT | 可选(建议开) |
| PEX | 可选(建议开) |
关闭 μTP(UDP):Xray portal 反向代理不支持 UDP,BT 的 μTP 走 UDP 会导致入站失败。
4.4 定时做种调度(crontab)
让 qBittorrent 只在夜间(01:00-07:00)做种,白天暂停以节省带宽:
crontab -e
添加以下两行(在 NAS 或任意可访问 192.168.1.200 的设备上):
0 1 * * * curl -s -X POST "http://192.168.1.200:8888/api/v2/torrents/start" --data "hashes=all"
0 7 * * * curl -s -X POST "http://192.168.1.200:8888/api/v2/torrents/stop" --data "hashes=all"
| 时间 | 操作 | 含义 |
|---|---|---|
| 凌晨 01:00 | /torrents/start hashes=all |
启动全部种子开始做种 |
| 早上 07:00 | /torrents/stop hashes=all |
停止全部种子 |
第五部分:部署顺序
1. 腾讯云防火墙 → 开放 51413/tcp
2. scp beijing-vps-stream.conf → 北京VPS /etc/nginx/stream.conf.d/
3. scp xray-北京vps-config.json → 北京VPS /usr/local/etc/xray/config.json
4. 北京VPS: nginx -t && systemctl reload nginx
5. 北京VPS: systemctl restart xray
6. scp 旁路由的mihomo config.yaml → 旁路由 /opt/mihomo/config.yaml
7. scp xray-旁路由-config.json → 旁路由 /etc/xray/config.json
8. 旁路由: /etc/init.d/mihomo restart
9. 旁路由: /etc/init.d/xray restart
10. NAS: 创建 macvlan 网络 + 启动 qBittorrent 容器
11. NAS: 配置 qBittorrent 监听端口 51413,关闭 μTP
第六部分:验证
6.1 SOCKS5 代理出站验证
# 在 NAS 上执行,应返回北京 VPS 的公网 IP
docker exec qbittorrent curl --socks5 192.168.1.199:1080 https://ip.sb
6.2 Xray 日志确认
# 旁路由上查看 Xray 日志,确认 socks-lan 流量转发正常
tail -f /var/log/xray.log | grep socks-lan
6.3 BT 入站验证
# 北京 VPS 上确认端口监听
ss -tlnp | grep 51413
# 从外部测试端口可达
nc -zv salmonstill.cn 51413
6.4 端到端 BT 测试
下载一个热门 Ubuntu torrent 种子,观察:
- qBittorrent WebUI → 连接 → 应显示 DHT 节点数增长
- 跟踪器页面 → 应显示 "Working"
- 下载速度应有上传来确认入站工作
第七部分:故障排查
| 现象 | 排查 |
|---|---|
| qBittorrent curl ip.sb 返回真实 IP | SOCKS5 代理未生效,检查 qBittorrent 设置中代理配置 |
| 代理连不上 | 确认 旁路由 Xray 正在运行且 socks-lan 入站监听 :1080 |
| 入站无上传 | 检查北京 VPS ufw/腾讯云安全组已放行 51413/tcp |
xray 报错 reverse-proxy.xray.internal |
portal/bridge 域名不匹配,两边必须一致 |
| 下载有速度、无上传 | μTP 没关或 portal UDP 不支持,qBittorrent 设置仅 TCP |
第八部分:文件清单
| 文件 | 位置 | 作用 |
|---|---|---|
beijing-vps-stream.conf |
北京VPS /etc/nginx/stream.conf.d/ |
Nginx SNI分流(含 www.bilibili.com → 9445) |
xray-北京vps-config.json |
北京VPS /usr/local/etc/xray/config.json |
Xray 入站+路由(含 proxy_from_lan + external_qbit) |
xray-旁路由-config.json |
旁路由 /etc/xray/config.json |
Xray bridge + to_qbit(51413) + socks-lan(1080) → to_beijing_direct |
WireGuard 内网穿透(iPhone / Mac 远程访问内网)
复用已有的 WireGuard 隧道,让外部 iPhone / Mac 通过北京 VPS 中继,访问家里整个 192.168.1.0/24 内网的任意端口(无需逐个配置端口规则)。
架构
iPhone (WireGuard App, 10.0.0.3)
Mac (WireGuard, 10.0.0.4)
↓ WG 隧道 (UDP 51820)
北京VPS 49.232.242.90 (wg0, 10.0.0.1/24)
↓ 转发 (iptables FORWARD ACCEPT)
旁路由 192.168.1.199 (10.0.0.2, penetration zone)
↓ 转发 + SNAT (→ 192.168.1.199)
整个 192.168.1.0/24 任意端口可达 (如 Spark 192.168.1.166:8081 Expo dev server)
虚拟网段 IP 分配
| 设备 | WG IP | 说明 |
|---|---|---|
| 北京 VPS | 10.0.0.1/24 |
WG 服务端,监听 :51820 |
| 旁路由 | 10.0.0.2/24 |
子网代理节点,进 LAN |
| iPhone | 10.0.0.3/32 |
WireGuard App |
| Mac | 10.0.0.4/32 |
WireGuard |
北京 VPS 配置 (/etc/wireguard/wg0.conf)
[Interface]
Address = 10.0.0.1/24
ListenPort = 51820
PrivateKey = <北京VPS私钥>
MTU = 1420
PostUp = iptables -t nat -A POSTROUTING -s 10.0.0.0/24 -o eth0 -j MASQUERADE
PostUp = iptables -A FORWARD -i wg0 -j ACCEPT
PostUp = iptables -A FORWARD -o wg0 -j ACCEPT
PostDown = iptables -t nat -D POSTROUTING -s 10.0.0.0/24 -o eth0 -j MASQUERADE
PostDown = iptables -D FORWARD -i wg0 -j ACCEPT
PostDown = iptables -D FORWARD -o wg0 -j ACCEPT
[Peer]
# 旁路由(子网代理,带 192.168.1.0/24)
PublicKey = <旁路由公钥>
AllowedIPs = 10.0.0.2/32, 192.168.1.0/24
PersistentKeepalive = 25
[Peer]
# iPhone
PublicKey = <iPhone公钥>
AllowedIPs = 10.0.0.3/32
PersistentKeepalive = 25
[Peer]
# Mac
PublicKey = <Mac公钥>
AllowedIPs = 10.0.0.4/32
PersistentKeepalive = 25
⚠️ 关键坑:iptables FORWARD policy DROP。VPS 装过 Docker 后,
iptables的 FORWARD 链默认策略会变成DROP,导致客户端流量穿透 VPS 转发时被丢弃(症状:ping 10.0.0.1通、ping 10.0.0.2不通)。必须在 PostUp 加-i wg0/-o wg0两条 ACCEPT。 查看规则用iptables -L FORWARD -n -v(必须带-v,否则不显示 In/Out 接口列,grep wg0会以为规则不存在)。
旁路由配置(ImmortalWrt LuCI)
1. 新建 penetration zone
网络 → 防火墙 → General Settings → 添加:
| 字段 | 值 |
|---|---|
| Name | penetration |
| Input | accept |
| Output | accept |
| Forward | accept |
| Covered networks | WireGuard |
| Allow forward to destination zones | lan |
同时把 WG 接口从 wan zone 的 Covered networks 取消勾选(一个接口只能属于一个 zone)。
2. 新增通用 SNAT 规则(关键)
网络 → 防火墙 → NAT 规则 → 添加:
| 字段 | 值 |
|---|---|
| Name | penetration-snat |
| 地址族限制 | 仅 IPv4 |
| 协议 | Any |
| 出站区域 | lan |
| 源地址 | 10.0.0.0/24 |
| 目标地址 | any |
| 操作 | SNAT → 重写 IP 192.168.1.199 |
生成规则:ip saddr 10.0.0.0/24 ... snat ip to 192.168.1.199
⚠️ 关键坑:penetration zone 勾 masq 无效。ImmortalWrt (fw4) 的 masquerade 按"出接口"触发,隧道流量转发进 LAN 时出接口是
br-lan(属于 lan zone),不会进srcnat_penetration。必须显式加 SNAT 规则,否则 166 等设备的回包发给主路由(192.168.1.1)而丢失(症状:ping 10.0.0.2通、ping 192.168.1.166不通)。
3. Minecraft 端口转发联动
因为 WG 接口从 wan 移到了 penetration,Minecraft 那条 Minecraft-udp 端口转发的 Source zone 要从 wan 改成 penetration(玩家流量实际也走 WG 隧道进来),否则 Minecraft 会断。
客户端配置
iPhone(海外区 App Store 官方 WireGuard)
[Interface]
PrivateKey = <iPhone私钥>
Address = 10.0.0.3/32
DNS = 223.5.5.5
[Peer]
PublicKey = <北京VPS服务端公钥>
Endpoint = 49.232.242.90:51820
AllowedIPs = 10.0.0.0/24, 192.168.1.0/24
PersistentKeepalive = 25
Mac
同上,Address = 10.0.0.4/32,PrivateKey 换成 Mac 的。
AllowedIPs 只含虚拟网段和内网网段 → split tunnel,仅内网流量走隧道,不影响正常上网。
验证命令
# 北京 VPS 上:确认 3 个 peer 都有握手
wg show
# 客户端设备上:三层诊断(定位故障层级)
ping -c 3 10.0.0.1 # ① 隧道到 VPS —— 通说明客户端配置对
ping -c 3 10.0.0.2 # ② 隧道到旁路由 —— 通说明 VPS 转发对
ping -c 3 192.168.1.166 # ③ 进内网 —— 通说明旁路由转发+SNAT 对
# 旁路由上确认 SNAT 规则
nft list ruleset | grep -iE "penetration-snat|10.0.0.0/24"
排障对照表
| 现象 | 原因 | 修复 |
|---|---|---|
ping 10.0.0.1 通、ping 10.0.0.2 不通 |
VPS iptables FORWARD policy DROP | wg0.conf PostUp 加 -i wg0 / -o wg0 ACCEPT |
ping 10.0.0.2 通、ping 192.168.1.166 不通 |
旁路由缺通用 SNAT | 新增 penetration-snat(SNAT → 192.168.1.199) |
| 旁路由自己 ping 166 通,但客户端不通 | 同上 | 同上 |
iptables -L FORWARD -n | grep wg0 为空 |
没带 -v,接口列不显示 |
用 iptables -L FORWARD -n -v |
Minecraft UDP 转发
架构
公网玩家 (UDP 19132)
↓
北京VPS (salmonstill.cn)
socat 监听 19132 → 转发到 10.0.0.2:19132
↓ WireGuard 隧道
旁路由 ImmortalWrt (192.168.1.199 / 10.0.0.2)
nftables 端口转发 + SNAT
↓
NAS (192.168.1.188:19132)
↓
Minecraft 基岩版 Docker 容器
设备信息
| 设备 | IP | 系统 |
|---|---|---|
| 北京VPS | salmonstill.cn / 49.232.242.90 |
Ubuntu 22.04 |
| 旁路由 | 192.168.1.199 / WG隧道: 10.0.0.2 |
ImmortalWrt 24.10 (GL-MT2500) |
| NAS | 192.168.1.188 |
绿联云 UGOS |
第一部分:北京VPS 配置
WireGuard 配置 /etc/wireguard/wg0.conf
[Interface]
Address = 10.0.0.1/24
ListenPort = 51820
PrivateKey = <北京VPS私钥>
MTU = 1420
# 回包源地址转换(必须,否则公网玩家收不到回包)
PostUp = iptables -t nat -A POSTROUTING -s 10.0.0.0/24 -o eth0 -j MASQUERADE
PostDown = iptables -t nat -D POSTROUTING -s 10.0.0.0/24 -o eth0 -j MASQUERADE
[Peer]
# 旁路由
PublicKey = 9jPlaUhx2Dc+C5ZqJx6Iu8GtNMig3cFIoqfHg8PZbCA=
AllowedIPs = 10.0.0.2/32
PersistentKeepalive = 25
⚠️ 不使用 iptables DNAT 转发,改用 socat 处理 UDP 转发,避免 conntrack 连接跟踪问题导致回包丢失。
开启内核转发
echo "net.ipv4.ip_forward=1" >> /etc/sysctl.conf
sysctl -p
开放防火墙端口
ufw allow 51820/udp # WireGuard
ufw allow 19132/udp # Minecraft 基岩版
启动 WireGuard
systemctl enable wg-quick@wg0
systemctl start wg-quick@wg0
socat UDP 转发
socat 监听公网 19132 端口,收到包后转发给旁路由隧道 IP,并维护连接状态确保回包正确返回。
创建 systemd service:
nano /etc/systemd/system/mc-forward.service
[Unit]
Description=Minecraft UDP Forward
After=network.target
[Service]
ExecStart=/usr/bin/socat UDP4-LISTEN:19132,fork,reuseaddr UDP4:10.0.0.2:19132
Restart=always
[Install]
WantedBy=multi-user.target
启动并设置开机自启:
systemctl daemon-reload
systemctl enable mc-forward
systemctl start mc-forward
第二部分:旁路由 ImmortalWrt 配置
WireGuard 接口配置
路径:网络 → 接口 → 添加新接口
常规设置:
| 字段 | 值 |
|---|---|
| 接口名称 | WireGuard |
| 协议 | WireGuard VPN |
| 私钥 | <旁路由私钥> |
| IP 地址 | 10.0.0.2/24 |
| 监听端口 | 不填 |
防火墙设置: 加入 wan 区域
Peers → 添加对端:
| 字段 | 值 |
|---|---|
| 公钥 | n159R7bNB+tW3Br0cok2zA27Pzg2WSPTI9uQ9odOFyU= |
| 端点主机 | salmonstill.cn |
| 端点端口 | 51820 |
| 允许的 IP | 0.0.0.0/0 |
| 路由允许的 IP | ✅ 勾选 |
| 持续 Keep-Alive | 25 |
⚠️ 允许的 IP 必须设为
0.0.0.0/0,否则 WireGuard 会丢弃来自公网玩家 IP 的包。
端口转发配置
路径:网络 → 防火墙 → 端口转发 → 添加
| 字段 | 值 |
|---|---|
| 名称 | Minecraft-udp |
| 协议 | UDP |
| 源区域 | wan |
| 外部端口 | 19132 |
| 目标区域 | lan |
| 内部 IP 地址 | 192.168.1.188 |
| 内部端口 | 19132 |
SNAT 配置
路径:网络 → 防火墙 → NAT 规则 → 添加
| 字段 | 值 |
|---|---|
| 名称 | minecraft-snat |
| 地址族限制 | 仅 IPv4 |
| 协议 | UDP |
| 出站区域 | lan |
| 目标地址 | 192.168.1.188 |
| 目标端口 | 19132 |
| 操作 | SNAT - 重写为特定的源 IP 或端口 |
| 重写 IP 地址 | 192.168.1.199 |
SNAT 的作用:将转发给 NAS 的包源 IP 改为旁路由 IP,确保 NAS 的回包发回给旁路由而不是直接走主路由,避免回包路径不对称。
第三部分:NAS Docker 配置
使用 network_mode: host 避免 Docker NAT 导致的 IP 映射问题。
services:
bedrock:
image: itzg/minecraft-bedrock-server:2026.2.1
container_name: mc-bedrock
network_mode: host
stdin_open: true
tty: true
environment:
EULA: "TRUE"
VERSION: "1.26.14.1"
TZ: "Asia/Shanghai"
OPS: "2535472561115036"
volumes:
- /volume2/ProgramsV2/minecraft:/data
restart: unless-stopped
第四部分:验证
检查 WireGuard 隧道
# 旁路由
wg show
# 正常应有 latest handshake 和双向 transfer
检查 socat 运行状态
systemctl status mc-forward
抓包验证完整链路
# VPS 上抓 wg0,确认双向流量
tcpdump -i wg0 udp port 19132 -n
# 旁路由抓 br-lan,确认转发到 NAS
tcpdump -i br-lan udp port 19132 -n
# NAS 上抓包,确认收到并回包
sudo tcpdump -i bridge0 udp port 19132 -n
故障排查
| 现象 | 排查方法 |
|---|---|
| WireGuard 无握手 | 检查 VPS 防火墙 51820/udp 是否开放 |
| socat 收不到包 | 检查 ufw 19132/udp 是否开放 |
| 旁路由收不到包 | 检查 WireGuard AllowedIPs 是否为 0.0.0.0/0 |
| NAS 收不到包 | 检查端口转发内部端口是否填写正确 |
| NAS 有回包但玩家连不上 | 检查 SNAT 规则是否生效,确认 NAS 用 host 网络模式 |
| 游戏内延迟不显示 | 检查 socat 是否正常运行,DNAT 规则是否已删除 |
扩展:新增其他 UDP 服务
- VPS 新建一个 socat service,修改端口号
- 旁路由 LuCI 端口转发新增一条规则
ufw allow <新端口>/udp
SOCKS5 动态 LAN 端口访问
通过新增的 socks-dynamic 入站(:38658,密码认证),可从外部访问任意内网 IP:PORT,无需事先配置端口规则。
浏览器 SOCKS5 → salmonstill.cn:38658
→ 北京VPS socks-dynamic → portal → 反向隧道
→ 旁路由 bridge → catch-all direct → 任意 LAN IP:PORT
Reality 密钥
| 位置 | Private Key | Public Key (客户端用) |
|---|---|---|
| 北京 VPS(3 个入站共用) | GGT9LfN_2JdQG68cwrULgUK-adfT6wIokLzWjaB0fXs |
62y5gDjPrdeuePGl-D2IW4Cw9Kb8_bSBBTmArvL7Nhs |
| 搬瓦工 VPS(客户端直连) | iBlu3eH1VLf1S5Qw87m_1w0TGYUktDwHAzgpQ2aKuGI |
jr_zQjC4mvlQITuG5Ap5Mxqe5EBbGyyvwbVLDEi8OCA |
Beijing-Direct 节点必须 skip-cert-verify: true,因 Reality 返回 target(www.bilibili.com)的证书,而 SNI 是 www.bilibili.com,TLS SAN 校验可能失败。
Reality 故障排查
| 现象 | 根因 | 解决 |
|---|---|---|
Mihomo 日志 connect error: EOF,Xray 日志 handshake did not complete successfully |
运营商检测并干扰特定 SNI(如 www.microsoft.com)。某次 VPS 迁移后开始出现,同配置在旧 VPS 正常 |
更换 SNI/serverNames/dest 为其他高信誉域名,如 www.cloudflare.com。仅 SNI 变换即可,无需更换密钥 |
Xray 日志 target sent incorrect server hello or handshake incomplete |
Reality dest 目标不适合(如 www.cloudflare.com 不支持直连 TLS 1.3 或返回非标准 Server Hello) |
换用标准 Web 站点(如 www.microsoft.com 或 www.youtube.com 作为 dest,www.cloudflare.com 作为 SNI) |
Reality 参数一致性清单(出现握手失败时逐项核对):
- Xray
privateKey←→ Mihomopublic-key(xray x25519 -i <私钥>验证) - Xray
shortIds←→ Mihomoshort-id - Xray
id←→ Mihomouuid - Xray
serverNames[0]←→ Mihomoservername←→ Nginx stream map - VPS 能直连 Reality
dest目标(curl -4s https://<dest> -o /dev/null -w '%{http_code}')
流量路径
路径 1:内网服务反向代理
用户 → salmonstill.cn:端口 → dokodemo-door → portal → 隧道 → bridge
→ 端口匹配出站 → 内网目标 → 原路返回
路径 2:代理翻墙(直连搬瓦工)
Mihomo 客户端 → 67.230.189.235:443 (SNI=www.cloudflare.com)
→ Nginx 分流 → Xray :9443 → freedom → 互联网
路径 3:qBittorrent 代理出站
qBittorrent → SOCKS5 旁路由:1080 → Xray to_beijing_direct
→ salmonstill.cn:443 (SNI=www.bilibili.com) → proxy_from_lan → direct → 互联网
路径 4:BT 入站
BT Peer → salmonstill.cn:51413 → portal → 隧道 → bridge → to_qbit → 1.200:51413
路径 5:Minecraft UDP
公网玩家 → salmonstill.cn:19132 → socat → WireGuard → 旁路由 → NAS :19132
路径 6:SOCKS5 动态回家
浏览器 SOCKS5 → salmonstill.cn:38658 → socks-dynamic → portal → 隧道
→ bridge → catch-all direct → 任意 LAN IP:PORT
| 文件 | 目标设备 | 部署路径 | |
|---|---|---|---|
北京vps-stream.conf |
北京 VPS | /etc/nginx/nginx.conf 的 stream {} 块 |
|
xray-北京vps-config.json |
北京 VPS | /usr/local/etc/xray/config.json |
|
代理vps-stream.conf |
搬瓦工 VPS | /etc/nginx/nginx.conf 的 stream {} 块 |
|
xray-代理服务器-config.json |
搬瓦工 VPS | /usr/local/etc/xray/config.json |
|
xray-旁路由-config.json |
旁路由 | /etc/xray/config.json |
|
旁路由的mihomo config.yaml |
旁路由 | /opt/mihomo/config.yaml |
|
非tun模式的主机mihomo config.yaml |
macOS | ~/Library/Application Support/mihomo/config.yaml (launchctl 管理) |
|
tun模式的主机mihomo config.yaml |
Spark (Ubuntu) | /opt/mihomo/config.yaml |
|
subscribe-7891-only.yaml |
通用 | 精简版模板(单独 7891 端口) | |
qbittorrent流量转发.md |
— | 方案文档(已合并到 README,可删除) | |
我的世界udp转发.md |
— | 方案文档(已合并到 README,可删除) |
部署流程
1. 腾讯云防火墙开放端口(443, 51413/tcp, 51820/udp, 19132/udp)
2. 北京 VPS: 部署 Nginx stream → nginx -t && systemctl reload nginx
3. 北京 VPS: 部署 Xray → systemctl restart xray
4. 北京 VPS: 部署 WireGuard → wg-quick@wg0
5. 北京 VPS: 部署 socat → systemctl start mc-forward
6. 搬瓦工 VPS: 部署 Nginx + Xray
7. 旁路由: 部署 Xray → /etc/init.d/xray restart
8. 旁路由: 部署 Mihomo → /etc/init.d/mihomo restart
9. 旁路由: 配置 WireGuard + 端口转发 + SNAT(LuCI)
10. NAS: 创建 macvlan 网络 → 启动 qBittorrent 容器
11. NAS: 启动 Minecraft 容器
验证命令
# 北京 VPS
ss -tlnp | grep -E '944[345]|3865[3-8]|51413|10809'
systemctl status nginx xray wg-quick@wg0 mc-forward
# 搬瓦工 VPS
ss -tlnp | grep -E '443|9443'
systemctl status nginx xray
# 旁路由
ss -tlnp | grep -E '789[0-2]|1080' # Mihomo 端口 + Xray socks-lan
mihomo -d /opt/mihomo -t # 配置文件校验
tail /opt/mihomo/logs/mihomo.log | grep INFO # 确认代理无报错
wg show
# qBittorrent 连通性
docker exec qbittorrent curl -s https://ip.sb # 应返回北京 VPS IP
# Minecraft
systemctl status mc-forward
tcpdump -i wg0 udp port 19132 -n