Files
server/README.md
T
2026-10-08 18:27:02 +08:00

1227 lines
42 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# VPS 流量转发配置
基于 **Xray + Nginx SNI 分流 + Mihomo TUN 透明代理 + WireGuard**,实现:
内网服务反向代理、多 VPS 链路中转、BT 透明代理、Minecraft UDP 转发、NAS 外网加速入口(香港 → 东京 → 内网)。
---
## 设备
| 设备 | IP / 域名 | 角色 |
|---|---|---|
| **北京 VPS** | `salmonstill.cn` / `49.232.242.90` | 公网入口,Nginx + Xray + socat + WireGuard |
| **搬瓦工 VPS** | `74.82.200.116`(日本东京 / Ubuntu 24.04) | 代理出口、**NAS 外网转发入口**(Xray `portal-jp`)、**SearXNG**(:8080) |
| **旁路由** | `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.app,**当前没有隧道配置**;需要时按「客户端配置」添加 |
---
## 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`)—— 同一个 443 按 SNI 分三路:
| SNI | 后端 | 端口 | 用途 |
|---|---|---|---|
| `www.cloudflare.com` | Xray `vless-jp` | :9443 | Mihomo 客户端代理入口(Reality);未匹配到 bridge 域名的流量 → `direct` 出网 |
| `drive-jp.salmonstill.cn` | NAS | :38653 | 香港访问 NAS 的快速入口 → `portal-jp` → 反向隧道回旁路由 |
| 默认 | — | :8443 | **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`)
**这台现在同时干三件事**(已从美国迁到日本东京,IP `74.82.200.116`,主机 `classic-hops-2`,Ubuntu 24.04):
| 职责 | 入口 | 出站 | 说明 |
|---|---|---|---|
| 代理出口 | nginx `443` SNI=`www.cloudflare.com` → `vless-jp:9443` | `direct` | Mihomo 客户端直连,Reality(dest=www.cloudflare.com),不经北京中转 |
| NAS 转发入口 | nginx `443` SNI=`drive-jp.salmonstill.cn` → `nas:38653` → `external_nas_jp` | `portal-jp` | 香港访问 NAS 的快速通道,反向隧道回旁路由 |
| SearXNG | `0.0.0.0:8080`(docker,compose 在 `/opt/searxng`) | — | 公网可直接访问;无反代、无 TLS,服务器上也没有防火墙 |
**Xray 配置**:`inbounds` = `vless-jp(9443)` + `external_nas_jp(38653)`;`reverse.portals` = `portal-jp`;`routing` 三条:
```jsonc
{ "inboundTag": ["external_nas_jp"], "outboundTag": "portal-jp" }, // NAS 流量送进隧道
{ "inboundTag": ["vless-jp"], "domain": ["full:reverse-proxy-jp.xray.internal"], "outboundTag": "portal-jp" }, // bridge 注册
{ "inboundTag": ["vless-jp"], "outboundTag": "direct" } // 其余 = 代理客户端
```
> ⚠️ **两条 `vless-jp` 规则里,带 domain 的那条不能省**:东京这台 **Reality 入站是「代理客户端 + bridge」共用的**(不像北京那台 `interconn` 是 bridge 专用)。只写 `vless-jp → portal-jp` 而不按域名区分,会把你**正常的代理流量也推进隧道**,代理立刻断掉。**这是本架构里唯一不能照抄北京的地方。**
### 香港 → NAS 快速入口 (`drive-jp.salmonstill.cn`)
**背景**:走老的 `drive.salmonstill.cn`(北京入口)进 NAS,瓶颈在腾讯云的峰值带宽。改用搬瓦工(东京,大带宽)做入口,香港侧更快。
**链路**
```
香港 → drive-jp.salmonstill.cn (74.82.200.116:443, SNI=drive-jp.salmonstill.cn)
→ nginx 按 SNI 分流 → 127.0.0.1:38653 (dokodemo external_nas_jp)
→ portal-jp → 反向隧道(旁路由 bridge-jp 主动注册)
→ bridge-jp : 38653 → to_nas → 192.168.1.188:9443
```
**两侧改动**(均已部署验证)
| 侧 | 文件 | 改动 |
|---|---|---|
| 东京 | `/etc/nginx/nginx.conf` 的 stream 块(**内联,不是独立 conf 文件**) | map 加 `drive-jp.salmonstill.cn nas;`,新增 `upstream nas → 127.0.0.1:38653` |
| 东京 | `/usr/local/etc/xray/config.json` | `reverse.portals: portal-jp`、入站 `external_nas_jp`(dokodemo 38653)、上面那三条 routing |
| 旁路由 | `/etc/xray/config.json` | 第二个 bridge `bridge-jp`、出站 `interconn-jp`(直连东京 Reality)、2 条 `bridge-jp` 路由规则 |
**关键设计**
- 两条路的 `38653` **共用同一个出站 `to_nas`** → **NAS 侧(端口、证书)完全不用改**
- TLS 全程**透传到 NAS**,出示的是 NAS 那张自签 `CN=UGREEN` 证书;新域名走新 SNI,与老路径互不影响
- 旁路由原有 **20 条 bridge 规则、`interconn-balancer`、`socks-lan` 全部未动**(`git diff --numstat` = `53 0`,纯新增)
- 两条路可以并存:老的 `drive.salmonstill.cn` 仍走北京,新的 `drive-jp.salmonstill.cn` 走东京
**验收**
```bash
# 端到端(应完成 TLS 握手并返回 307;NAS 是自签证书,所以要 -k)
curl -vkI --resolve drive-jp.salmonstill.cn:443:74.82.200.116 https://drive-jp.salmonstill.cn
# 东京侧:dokodemo 在听 + bridge 已注册
ss -tlnp | grep 38653
journalctl -u xray | grep -E 'portal-jp|reverse-proxy-jp' | tail
```
**备份(东京)**:`/etc/nginx/nginx.conf.bak-20261008-083207`、`/usr/local/etc/xray/config.json.bak-20261008-083207`
**部署顺序**:官方建议**先起 bridge、再起 portal** 最稳。反过来(portal 先起)时实测出现过「bridge 注册成功但数据不通」的半死状态,**重启一次 bridge 即可恢复**。
---
## 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 → `74.82.200.116:443`(默认国外出口,客户端直连搬瓦工,SNI=www.cloudflare.com)
> `Xray-Real` 代理节点(经北京 VPS 中转)已移除,Mihomo 全部直连搬瓦工。
**关键策略组**:
- 国外 → `[US-Direct, 直连]`
**防死循环 IP**:`49.232.242.90`(北京 VPS)、`74.82.200.116`(搬瓦工 VPS)强制直连。
**额外监听器**:`:7891`(全局→US-Direct,内网/保留网段直连)、`:7892`(强制直连)
### macOS (`非tun模式的主机mihomo config.yaml`)
结构与旁路由一致,无 TUN,监听器 `:7890` + `:7891` + `:7892`。
**重启**(launchctl 管理):
```bash
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。
### 内网网段直连(三份配置一致)
内网/保留网段**永远直连**,绝不出国:
| 网段 | 用途 |
|---|---|
| `192.168.0.0/16` | 家庭 LAN(NAS `1.188`、旁路由 `1.199`、Spark `1.166`、qBit `1.200`、Windows `1.177`) |
| `10.0.0.0/8` | WireGuard 虚拟网段(`10.0.0.1~10.0.0.4`) |
| `172.16.0.0/12` | Docker bridge(Spark `172.20.0.1` 等) |
| `100.64.0.0/10` | CGNAT / 运营商大内网 |
| `127.0.0.0/8`、`169.254.0.0/16` | 本机回环、链路本地 |
| `224.0.0.0/4`、`240.0.0.0/4` | 组播(mDNS/SSDP 发现)、保留段 |
**实现方式(两处改动同时生效)**:
1. `rules:` **最顶部**的 8 条显式 `IP-CIDR,<网段>,直连,no-resolve`。
不依赖 `RULE-SET,Private_IP`(该 rule-provider 是启动时从 GitHub 下载的,下载失败/被墙时为空,内网流量会一路落到 `MATCH,其他 → 国外` 被送出国——这正是加显式规则的原因)。`no-resolve` 避免为内网 IP 触发公网 DoH 解析。
2. `sub-rules.lan-direct-global` + `listeners: global-mixed` 的 `rule: lan-direct-global`。
`:7891` 原来的 `proxy: US-Direct` 会**完全绕过 rules**,所以经 7891 访问 `192.168.x` 一定被送到搬瓦工;改成子规则后:内网/保留网段 → `直连`,其余仍 `MATCH,US-Direct`(全局代理语义不变)。注意 `proxy` 与 `rule` 同时存在时 `proxy` 优先,排查时先确认 7891 上没有残留 `proxy:` 字段。
> `fake-ip` 段 `198.18.0.0/16` **不能**加进直连,否则代理路由失效。
> `sub-rules` / listener `rule` 需要 mihomo ≥ v1.19(本机验证版本 `Mihomo Meta v1.19.22`)。若某台设备版本过低,`mihomo -t` 会直接报错:此时保留 `rules` 里的显式 `IP-CIDR`(所有版本都支持),把该台 7891 还原成 `proxy: US-Direct`,内网访问改用 `7890`。
**验收**:
```bash
# 内网直连(应成功,且 mihomo 日志出站为 直连):把 <LAN_IP> 换成同网段任意内网设备
curl -x http://127.0.0.1:7891 http://<LAN_IP>:5005 -I
# 全局代理语义不变(应返回搬瓦工出口 IP)
curl -s -x http://127.0.0.1:7891 https://ip.sb
# 查看活跃连接的实际出站链
curl -s http://127.0.0.1:9090/connections | grep -E '192\.168|10\.'
# mihomo 日志里可直接看到匹配到的规则
# [TCP] 127.0.0.1:xxxxx --> 192.168.x.x:5005 match IPCIDR(192.168.0.0/16) using 直连
```
## 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 直连代理):
```nginx
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`(北京直连出口)
```json
{
"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 入站端口)
```json
{
"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 里关闭。
##### 新增路由规则
```json
{ "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 入站
```json
{
"tag": "socks-lan",
"port": 1080,
"listen": "0.0.0.0",
"protocol": "socks",
"settings": {
"auth": "noauth",
"udp": true
}
}
```
##### 出站 `to_beijing_direct`
```json
{
"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"
}
}
}
```
##### 路由规则
```json
{ "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`
```json
{
"tag": "to_qbit",
"protocol": "freedom",
"settings": {
"redirect": "192.168.1.200:51413"
}
}
```
##### 新增路由规则
```json
{
"type": "field",
"inboundTag": ["bridge"],
"port": "51413",
"outboundTag": "to_qbit"
}
```
> 放在 bridge 下——从北京 VPS 的 portal 通过反向隧道过来的 BT 入站流量,由 bridge 接收后按端口 51413 匹配到此规则,转发到 qBittorrent 容器。
---
### 第四部分:NAS qBittorrent Docker
#### 4.1 创建 macvlan 网络
```bash
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 启动容器
```bash
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)做种,白天暂停以节省带宽:
```bash
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 代理出站验证
```bash
# 在 NAS 上执行,应返回北京 VPS 的公网 IP
docker exec qbittorrent curl --socks5 192.168.1.199:1080 https://ip.sb
```
#### 6.2 Xray 日志确认
```bash
# 旁路由上查看 Xray 日志,确认 socks-lan 流量转发正常
tail -f /var/log/xray.log | grep socks-lan
```
#### 6.3 BT 入站验证
```bash
# 北京 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`)
```ini
[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 的。
> ⚠️ **实际状态(2026-10-08 核对)**:Mac 上 `WireGuard.app` 已安装,但**没有任何隧道配置、也没有活跃的 WG 接口**(`ifconfig` 里看不到 `10.0.0.4`)。需要远程进内网时,先在 app 里添加上面这份配置。
> AllowedIPs 只含虚拟网段和内网网段 → split tunnel,仅内网流量走隧道,不影响正常上网。
### 验证命令
```bash
# 北京 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`
```ini
[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 连接跟踪问题导致回包丢失。
#### 开启内核转发
```bash
echo "net.ipv4.ip_forward=1" >> /etc/sysctl.conf
sysctl -p
```
#### 开放防火墙端口
```bash
ufw allow 51820/udp # WireGuard
ufw allow 19132/udp # Minecraft 基岩版
```
#### 启动 WireGuard
```bash
systemctl enable wg-quick@wg0
systemctl start wg-quick@wg0
```
#### socat UDP 转发
socat 监听公网 19132 端口,收到包后转发给旁路由隧道 IP,并维护连接状态确保回包正确返回。
创建 systemd service:
```bash
nano /etc/systemd/system/mc-forward.service
```
```ini
[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
```
启动并设置开机自启:
```bash
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 映射问题。
```yaml
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 隧道
```bash
# 旁路由
wg show
# 正常应有 latest handshake 和双向 transfer
```
#### 检查 socat 运行状态
```bash
systemctl status mc-forward
```
#### 抓包验证完整链路
```bash
# 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 (客户端用) |
|---|---|---|
| **北京 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` ←→ Mihomo `public-key`(`xray 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 客户端 → 74.82.200.116: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
```
### 路径 7:香港 → NAS 快速入口(东京)
```
香港 → drive-jp.salmonstill.cn (74.82.200.116:443, SNI=drive-jp.salmonstill.cn)
→ nginx 按 SNI 分流 → 127.0.0.1:38653 (external_nas_jp) → portal-jp
→ 反向隧道(旁路由 bridge-jp 主动注册)
→ bridge-jp : 38653 → to_nas → 192.168.1.188:9443
```
> 与路径 1 的区别:入口从北京换到东京(大带宽),旁路由侧走 `bridge-jp`,**其余完全一样**,两条路并存。
| 文件 | 目标设备 | 部署路径 |
|---|---|---|---|
| `北京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 | **`/opt/mihomo/config.yaml`**(launchd `com.mihomo.proxy`,plist 里 `-d /opt/mihomo`;另有 `/opt/mihomo/start.sh` 可手动起) |
| `tun模式的主机mihomo config.yaml` | Spark (Ubuntu) | `/opt/mihomo/config.yaml` |
| `my_deepseek.sh` | macOS | 本机辅助脚本 |
| `qbittorrent流量转发.md` / `我的世界udp转发.md` | — | 方案文档,内容已并入 README;**文件仍保留在仓库里** |
| `旁路由备份/` | — | ImmortalWrt 配置备份 tar.gz |
| `dsh-local-403-fix/` | — | DSH 本地补丁工程(与本套网络无关) |
---
## 远程运维约定(tmux)
**在香港远程改旁路由的 xray / 网络配置,一律先开 tmux:**
```bash
tmux new -s x
# 在里面改配置、重启服务
```
原因:香港到旁路由的 SSH **走的就是那条反向 bridge**(`salmonstill.cn:38657 → portal → 隧道 → bridge → to_router_ssh → 192.168.1.199:22`)。一重启 xray 隧道就断,你自己的会话立刻死;命令跑到一半被杀,可能留下半残状态。tmux 挂在机器上,会话断了命令照样跑完。
**救援通道(xray 挂了、SSH 进不去时用)**
```
香港 → ssh root@49.232.242.90 # 北京 VPS,公网直连,不经任何隧道
→ ping -c3 10.0.0.2 # WireGuard 到旁路由(10.0.0.2 能通)
→ ssh <user>@192.168.1.166 # Spark(走 WG 转发进 LAN)
→ ssh root@192.168.1.199 # 旁路由(LAN 内,防火墙放行)
```
> ⚠️ **不能直接 `ssh 10.0.0.2`**:WG 那块的 zone 只放行了「转发到 LAN」,到**路由器自己**的 INPUT 是 REJECT,会得到 `Connection refused`(但 `ping` 通,别被误导)。
**重建隧道**:`/etc/init.d/xray restart`;配置有问题时回滚 `/etc/xray/config.json.bak`。
---
## 部署流程
```
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:
6.1 部署 Nginx(stream 块内联在 /etc/nginx/nginx.conf)→ nginx -t && systemctl reload nginx
6.2 部署 Xray(含 portal-jp)→ xray run -test -c /usr/local/etc/xray/config.json && systemctl restart xray
6.3 SearXNG: docker compose -f /opt/searxng/docker-compose.yml up -d
7. 旁路由: 部署 Xray → /etc/init.d/xray restart
⚠️ 顺序:先 6.2(portal)再 7(bridge);反了可能「注册成功但数据不通」,重启一次 bridge 即恢复
8. 旁路由: 部署 Mihomo → /etc/init.d/mihomo restart
9. 旁路由: 配置 WireGuard + 端口转发 + SNAT(LuCI)
10. NAS: 创建 macvlan 网络 → 启动 qBittorrent 容器
11. NAS: 启动 Minecraft 容器
```
> 所有远程改动都在 `tmux` 里做(见上)。
---
## 验证命令
```bash
# 北京 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|38653' # 443 nginx / 9443 Reality / 38653 NAS dokodemo
systemctl status nginx xray
journalctl -u xray | grep -E 'portal-jp|reverse-proxy-jp' | tail # bridge 注册情况
curl -skI https://drive-jp.salmonstill.cn/ # 应返回 307(香港侧执行)
docker ps | grep searxng # SearXNG
# 旁路由
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
```