Files
server/README.md
T

33 KiB
Raw Blame History

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 端口访问

出站directfreedom 直连)

路由:所有 external_* + interconn + socks-dynamicportal(反向隧道);interconn 探测流量(baidu.com)→ directproxy_from_landirect

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_nasNAS 管理)
  • 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_sshSpark SSH 远程)
  • 38660 → to_spark_rdpSpark xRDP 桌面远程)
  • 38662 → to_spark_38662
  • 38664 → to_win_rdpWindows 远程桌面)
  • 38665 → to_spark_3080Spark Web 3080
  • 默认(catch-all)→ direct(不匹配端口规则的动态请求直连目标)
  • socks-lan 入站 → to_beijing_direct

所有显式端口规则优先于 catch-all,现有端口转发不受影响。

搬瓦工 VPS (xray-代理服务器-config.json)

极简:VLESS+Reality 入站 :9443SNI=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 DNSenhanced-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, 直连]

防死循环 IP49.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 独立 IPPT 专用

第一部分:北京 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 入站 keypairserverNames 用新的 www.bilibili.com 与 Nginx 对应。 target 设为 www.apple.com:443,Reality 从此地址偷取真实 TLS 证书用于伪装。

新增入站 external_qbitBT 入站端口)
{
  "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.199qBittorrent 的默认网关设为旁路由,确保出站流量经过旁路由。 --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 反向代理不支持 UDPBT 的 μ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 移到了 penetrationMinecraft 那条 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/32PrivateKey 换成 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-snatSNAT → 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 服务

  1. VPS 新建一个 socat service,修改端口号
  2. 旁路由 LuCI 端口转发新增一条规则
  3. 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 (客户端用)
北京 VPS3 个入站共用) GGT9LfN_2JdQG68cwrULgUK-adfT6wIokLzWjaB0fXs 62y5gDjPrdeuePGl-D2IW4Cw9Kb8_bSBBTmArvL7Nhs
搬瓦工 VPS(客户端直连) iBlu3eH1VLf1S5Qw87m_1w0TGYUktDwHAzgpQ2aKuGI jr_zQjC4mvlQITuG5Ap5Mxqe5EBbGyyvwbVLDEi8OCA

Beijing-Direct 节点必须 skip-cert-verify: true,因 Reality 返回 targetwww.bilibili.com)的证书,而 SNI 是 www.bilibili.comTLS SAN 校验可能失败。

Reality 故障排查

现象 根因 解决
Mihomo 日志 connect error: EOFXray 日志 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.comwww.youtube.com 作为 destwww.cloudflare.com 作为 SNI

Reality 参数一致性清单(出现握手失败时逐项核对):

  • Xray privateKey ←→ Mihomo public-keyxray x25519 -i <私钥> 验证)
  • Xray shortIds ←→ Mihomo short-id
  • Xray id ←→ Mihomo uuid
  • Xray serverNames[0] ←→ Mihomo servername ←→ 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 → 互联网

路径 3qBittorrent 代理出站

qBittorrent → SOCKS5 旁路由:1080 → Xray to_beijing_direct
  → salmonstill.cn:443 (SNI=www.bilibili.com) → proxy_from_lan → direct → 互联网

路径 4BT 入站

BT Peer → salmonstill.cn:51413 → portal → 隧道 → bridge → to_qbit → 1.200:51413

路径 5Minecraft UDP

公网玩家 → salmonstill.cn:19132 → socat → WireGuard → 旁路由 → NAS :19132

路径 6SOCKS5 动态回家

浏览器 SOCKS5 → salmonstill.cn:38658 → socks-dynamic → portal → 隧道
  → bridge → catch-all direct → 任意 LAN IP:PORT
文件 目标设备 部署路径
北京vps-stream.conf 北京 VPS /etc/nginx/nginx.confstream {}
xray-北京vps-config.json 北京 VPS /usr/local/etc/xray/config.json
代理vps-stream.conf 搬瓦工 VPS /etc/nginx/nginx.confstream {}
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 + 端口转发 + SNATLuCI
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