diff --git a/README.md b/README.md index 6e39378..f64a4cf 100644 --- a/README.md +++ b/README.md @@ -59,6 +59,7 @@ | `external_router_ssh` | 38657 | → portal → 旁路由 :22 | | `external_spark_ssh` | 38659 | → portal → Spark (166) :22 | | `external_spark_rdp` | 38660 | → portal → Spark (166) :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 | @@ -97,6 +98,7 @@ | `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` | VLESS+Reality → `salmonstill.cn:443` (SNI=www.apple.com) | 隧道链接 | | `to_beijing_direct` | VLESS+Reality → `salmonstill.cn:443` (SNI=news.apple.com) | 北京直连 | | `direct` | freedom | 直连 | @@ -116,6 +118,7 @@ - 38658 → `direct`(SOCKS5 动态回家,直接连接目标地址) - 38659 → `to_spark_ssh`(Spark SSH 远程) - 38660 → `to_spark_rdp`(Spark xRDP 桌面远程) +- 38662 → `to_spark_38662` - 默认(catch-all)→ **`direct`**(不匹配端口规则的动态请求直连目标) - `socks-lan` 入站 → `to_beijing_direct` @@ -170,29 +173,616 @@ launchctl load ~/Library/LaunchAgents/com.mihomo.proxy.plist ## qBittorrent 透明代理 -详见 [`qbittorrent流量转发.md`](./qbittorrent流量转发.md)。 +### 架构总览 ``` -出站: qBittorrent → SOCKS5 旁路由:1080 (socks-lan) → Xray to_beijing_direct - → salmonstill.cn:443 (SNI=news.apple.com) → proxy_from_lan:9445 → direct → 互联网 -入站: BT Peer → salmonstill.cn:51413 → portal → 隧道 → bridge → to_qbit → 1.200:51413 -``` + 出站(SOCKS5 代理) +qBittorrent(192.168.1.200) 互联网 + ↓ SOCKS5 旁路由:1080 (socks-lan) ↑ + ↓ Xray routing → to_beijing_direct │ + ↓ Reality(VLESS, SNI=news.apple.com) │ + ↓ 北京VPS:443 → Nginx分流 │ + ↓ proxy_from_lan:9445 → direct(freedom) ─────────────────┘ -qBittorrent 设置:SOCKS5 代理 → 旁路由 `192.168.1.199:1080`,监听 `51413`,仅 TCP(关 μTP/UDP)。 + 入站(端口转发) +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` + +新增 `news.apple.com` SNI 映射(用于旁路由 Mihomo 直连代理): + +```nginx +stream { + map $ssl_preread_server_name $backend { + www.apple.com xray; # 旁路由反向代理隧道 + www.microsoft.com mihomo; # 外部客户端代理 → 东京出口 + news.apple.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": ["news.apple.com"], + "privateKey": "GGT9LfN_2JdQG68cwrULgUK-adfT6wIokLzWjaB0fXs", + "shortIds": ["7c947a71b94f369e"] + } + } +} +``` + +> Reality 公私钥复用已有的 `interconn` 入站 keypair,`serverNames` 用新的 `news.apple.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": "news.apple.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=news.apple.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分流(含 news.apple.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 | + ## Minecraft UDP 转发 -详见 [`我的世界udp转发.md`](./我的世界udp转发.md)。独立于 Xray 体系: +### 架构 ``` -公网 :19132 → 北京VPS socat → WireGuard 隧道 → 旁路由 10.0.0.2 - → 端口转发+SNAT → NAS :19132 → Docker (itzg/minecraft-bedrock-server) +公网玩家 (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,无需事先配置端口规则。 @@ -265,8 +855,8 @@ BT Peer → salmonstill.cn:51413 → portal → 隧道 → bridge → to_qbit | `非tun模式的主机mihomo config.yaml` | macOS | `~/Library/LaunchAgents/` (launchctl 管理) | | `tun模式的主机mihomo config.yaml` | Spark (Ubuntu) | `/opt/mihomo/config.yaml` (systemd) | | `subscribe-7891-only.yaml` | 通用 | 精简版模板(单独 7891 端口) | -| `qbittorrent流量转发.md` | — | 方案文档 | -| `我的世界udp转发.md` | — | 方案文档 | +| `qbittorrent流量转发.md` | — | 方案文档(已合并到 README,可删除) | +| `我的世界udp转发.md` | — | 方案文档(已合并到 README,可删除) | --- diff --git a/tokyo-vps-config.json b/xray-代理服务器-config.json similarity index 100% rename from tokyo-vps-config.json rename to xray-代理服务器-config.json diff --git a/xray-北京vps-config.json b/xray-北京vps-config.json index 9f25469..4cd3f72 100644 --- a/xray-北京vps-config.json +++ b/xray-北京vps-config.json @@ -119,6 +119,17 @@ "network": "tcp" } }, + { + "tag": "external_spark_38662", + "listen": "0.0.0.0", + "port": 38662, + "protocol": "dokodemo-door", + "settings": { + "address": "127.0.0.1", + "port": 38662, + "network": "tcp" + } + }, { "tag": "external_222", "listen": "0.0.0.0", @@ -365,6 +376,13 @@ ], "outboundTag": "portal" }, + { + "type": "field", + "inboundTag": [ + "external_spark_38662" + ], + "outboundTag": "portal" + }, { "type": "field", "inboundTag": [ diff --git a/xray-旁路由-config.json b/xray-旁路由-config.json index 2a5f860..4ff3b13 100644 --- a/xray-旁路由-config.json +++ b/xray-旁路由-config.json @@ -114,6 +114,13 @@ "redirect": "192.168.1.166:3389" } }, + { + "tag": "to_spark_38662", + "protocol": "freedom", + "settings": { + "redirect": "192.168.1.166:38662" + } + }, { "tag": "interconn", "protocol": "vless", @@ -304,6 +311,14 @@ "port": "38660", "outboundTag": "to_spark_rdp" }, + { + "type": "field", + "inboundTag": [ + "bridge" + ], + "port": "38662", + "outboundTag": "to_spark_38662" + }, { "type": "field", "inboundTag": [ diff --git a/东京-vps-stream.conf b/代理vps-stream.conf similarity index 100% rename from 东京-vps-stream.conf rename to 代理vps-stream.conf diff --git a/beijing-vps-stream.conf b/北京vps-stream.conf similarity index 100% rename from beijing-vps-stream.conf rename to 北京vps-stream.conf