tunnel_proxy_rs 使用教程
所有命令与 CLI 实现一致,可直接复制运行。想快速上手?先看「0. 场景速查」,按你的需求复制命令即可。
0. 场景速查(先看这里)
按「你想做什么」选择场景,命令已按 公网端 → 内网端 → 客户端验证 完整给出,可直接复制。每个场景末尾标注对应详细章节。
场景 A · 本机代理上网
在本机起一个 SOCKS5 代理,浏览器/命令行都走它:
# ① 启动 SOCKS5 代理(本机监听)
tunnel_proxy socks5 --listen 0.0.0.0:1080
# ② 验证(另开终端)
curl -x socks5h://127.0.0.1:1080 https://example.com
# 浏览器:设置代理 socks5://127.0.0.1:1080 即可
场景 B · 把内网服务暴露到公网(内网穿透)
内网一台机器(如家里 NAS 的 Web)要让公网朋友直接访问,无需公网 IP:
# ① 公网服务器(有公网 IP 的云主机)
tunnel_proxy pfserver --listen 0.0.0.0:7000 --password mykey --pool 7001-7010 --mode random
# ② 内网机器(无公网 IP):把本机 80 端口映射出去
tunnel_proxy pfclient --server server:7000 --password mykey --target 127.0.0.1:80
# ③ 公网用户访问 http://server:<分配端口>(server 日志会打印端口)
场景 C · 一个公网端口服务多个域名(虚拟主机)
多个网站(app.example.com、api.example.com)共用一个公网端口,按 Host/SNI 分流到不同内网机器:
# ① 公网 server:vhost 共享端口 8080(HTTPS 用 --vhost-https)
tunnel_proxy pfserver --listen 0.0.0.0:7000 --password mykey --mode fixed --port 7001 \
--vhost-http 0.0.0.0:8080
# ② 每台内网机器各注册一个域名
tunnel_proxy pfclient --server server:7000 --password mykey --domain app.example.com --target 127.0.0.1:80
tunnel_proxy pfclient --server server:7000 --password mykey --domain api.example.com --target 127.0.0.1:8080
# ③ 公网用户 curl http://app.example.com:8080 → 内网 A;curl http://api.example.com:8080 → 内网 B
场景 D · 内网服务负载均衡
两台内网机器提供同一服务,希望连接轮询分发、单台挂了自动摘除:
# ① 公网 server(random 模式,组不占端口)
tunnel_proxy pfserver --listen 0.0.0.0:7000 --password mykey --pool 7001-7010 --mode random
# ② 两台内网机器注册到同一组 web
tunnel_proxy pfclient --server server:7000 --password mykey --group web --target 127.0.0.1:8081
tunnel_proxy pfclient --server server:7000 --password mykey --group web --target 127.0.0.1:8082
# ③ 公网用户连 server:<分配端口>,连接轮流分发;某台断线自动移出
--health-check tcp 可定时探活,失败自动摘除。→ 详见 8.5 负载均衡组场景 E · 企业统一出口代理(Router 编排 + 认证 + 限流 + 监控)
公司多人共用一条出口,需要分链、限流、Web 控制台:
# router.yaml(示例)
# services:
# - name: socks
# addr: 0.0.0.0:1080
# proto: socks5
# users: [alice:secret]
# chains: []
tunnel_proxy run --listen 0.0.0.0:1080 --config router.yaml --api 127.0.0.1:18085 \
--api-user admin --api-pass secret
# 浏览器打开 http://127.0.0.1:18085 查看监控(API 需 Basic 认证)
场景 F · 弱网链路稳定传输(KCP / QUIC 承载)
内网穿透链路丢包严重时,隧道改用 KCP(UDP 可靠流 + 可选 FEC):
# 两端 --transport 必须一致
tunnel_proxy pfserver --listen 0.0.0.0:7000 --password mykey --pool 7001-7010 --transport kcp
tunnel_proxy pfclient --server server:7000 --password mykey --target 127.0.0.1:80 --transport kcp
场景 G · 用标准 SSH 客户端建反向隧道(SSH Gateway)
不装 pfclient,直接用系统自带 ssh -R 把内网端口映射到公网:
# ① 公网 server 开启 SSH Gateway
tunnel_proxy pfserver --listen 0.0.0.0:7000 --password mykey --ssh-gateway 0.0.0.0:2222 \
--ssh-gateway-user u --ssh-gateway-pass p
# ② 内网机器执行标准 ssh 命令
ssh -R 7000:127.0.0.1:80 u@server
# ③ 公网用户访问 http://server:7000 → 内网 80
场景 H · 公网端口 = 标准代理入口(把内网代理「搬」到公网)
内网有一台 SOCKS5/SS 代理,想让公网用户直接连:
# 内网 client:把公网端口 8080 变成「后端在内网的 SOCKS5 代理」
tunnel_proxy pfclient --server server:7000 --password mykey --mode client --port 8080 --proto socks5
# 公网用户:curl -x socks5h://server:8080 https://example.com
场景 I · P2P 直连(XTCP,不经服务器转发)
两台都有 NAT 的内网机器直连互访,服务器只做牵线:
# 目标端(内网):注册 XTCP 服务,自动启动 UDP 打洞(KCP 加密数据面)
tunnel_proxy pfclient --server server:7000 --password mykey --xtcp-server xt1 \
--xtcp-secret key1 --target 127.0.0.1:80
# (可选)指定 STUN 服务器:--stun-server stun.xxx.com:3478
# 目标端有 NAT 端口映射时,可直接指定 TCP 直连地址(bind@public 分离):
# bind=0.0.0.0:16666(本机绑定,云 NAT 53030→16666),public=120.220.73.189:53030(对外公布)
tunnel_proxy pfclient --server server:7000 --password mykey --xtcp-server xt1 \
--xtcp-secret key1 --target 127.0.0.1:80 --xtcp-punch "0.0.0.0:[email protected]:53030"
# 访问端(内网):本地监听 9000,UDP 打洞 / TCP 直连失败自动回退中转
tunnel_proxy pfclient --server server:7000 --password mykey --xtcp-server xt1 \
--xtcp-secret key1 --xtcp-listen 127.0.0.1:9000
--xtcp-punch "bind@public"
时优先 TCP 直连(绑定本地端口、公布 NAT 映射公网端口),数据不经服务器中转(严格 P2P)。
→ 详见 8. 反向穿透 pf场景 J · 不暴露公网端口的点对点访问(STCP)
远程访问家里电脑的 SSH/数据库,但不想把端口暴露到公网:
# 目标端(家里):注册服务(不占公网端口)
tunnel_proxy pfclient --server server:7000 --password mykey --stcp-server svc1 \
--stcp-secret key1 --target 127.0.0.1:22
# 访问端(你):本地监听 9000,连接经服务器按密钥中转
tunnel_proxy pfclient --server server:7000 --password mykey --stcp-server svc1 \
--stcp-secret key1 --stcp-listen 127.0.0.1:9000
# 然后 ssh -p 9000 [email protected]
场景 K · 中继寻址 + 令牌一键建隧道(DP02/DP03)
pfserver 也在 NAT 后、client 无法直连时,双方经加密中继按 ID 寻址互连;连接令牌把密码与地址打包,一条命令建隧道:
# ① 中继(DERP-like,按 ID 转发加密包)
tunnel_proxy pfrelay -l 0.0.0.0:7001
# ② pfserver(在 NAT 后)主动连中继注册
tunnel_proxy pfserver --transport relay --relay-addr relay:7001 --relay-id srv1 \
--password mykey --pool 7001-7010
# ③ 生成连接令牌(密码须与 pfserver --password 一致)
tunnel_proxy token-gen --password mykey --relay relay:7001 --relay-id srv1
# ④ 任一台机器拿令牌一键建隧道
tunnel_proxy tc --token tp... --target 127.0.0.1:80
# 公网用户访问 http://server:<分配端口> 即到达内网 80
场景 L · 只放行 ICMP 的网络里建隧道(QUIC-over-ICMP)
网络层封锁、只允许 ICMP 时,把 QUIC 数据报封装进 ICMP Echo 报文逃生(对应 gost icmp://)。需 root/管理员权限:
# ① 服务器(root,Linux/macOS 或 Windows 管理员):监听 ICMP,转发到固定目标
sudo tunnel_proxy icmp -l 0.0.0.0 -t 127.0.0.1:80
# ② 客户端(root):stdio → ICMP → 服务器 → 内网 80
echo "GET / HTTP/1.0\r\n\r\n" | sudo tunnel_proxy icmpclient -s server --id 7
# ③ --id 0 为随机 ID(多客户端区分用固定 ID)
icmp://server:ID 语义。→ 详见 4.1 ICMP 传输场景 M · 多机组成虚拟局域网(VNet,client 访问 server 内网资产)
多台机器经公网 server 打通成一张虚拟局域网:任意 client 用虚拟 IP 直接访问其它 client 及其所在内网资产(ping / TCP / UDP 三层互通)——「局域网互相打通组成小型广域网」。
# ① 公网 server:开启虚拟网络注册表
tunnel_proxy pfserver --listen 0.0.0.0:7000 --password mykey --pool 7001-7010 --virtual-net
# ② 各机器(root/管理员,创建 TUN 网卡加入虚拟网段)
sudo tunnel_proxy vnet --server server:7000 --password mykey --virtual-ip 10.99.0.2
# 另一台机器:
sudo tunnel_proxy vnet --server server:7000 --password mykey --virtual-ip 10.99.0.3
# ③ 互通验证(任一 client)
ping 10.99.0.3 # 三层互通
curl http://10.99.0.3:80 # 访问其它 client / server 侧内网资产
--prefix/--netmask 调整;
每个 client 的虚拟 IP 不能重复。UDP 承载(--transport kcp)在 NAT 后建议
--heartbeat-interval 5 保活 NAT 映射。→ 详见 8.8 虚拟组网 VNet场景 N · client 连接「未被公网 NAT」的 server 端口(反向访问内网)
server 侧某个端口只有内网地址、没有公网映射。client 无需直连该端口,经穿透隧道 从公网访问端绕进去即可——这正是「双向服务」:不只把内网服务暴露到公网(场景 B), 也能从公网反向访问到内网未映射的端口。
# ① 公网 server:fixed 模式固定公网端口
tunnel_proxy pfserver --listen 0.0.0.0:7000 --password mykey --mode fixed --port 7001
# ② 内网 client:把「未公网 NAT 的内网端口」注册到公网(如内网数据库 3306、内网 Web 80)
tunnel_proxy pfclient --server server:7000 --password mykey --target 127.0.0.1:3306
# ③ 任何位置的 client(公网/内网均可):访问 server:7001 即到达内网 3306
mysql -h server -P 7001 -u root -p
场景 O · 多 NAT 服务器联邦组网(VNet v2,私有广域网 + 自定义网络)
两台(或多台)NAT 云服务器各自创建 pfserver,互相联邦(--vnet2-peer),
本地 WSL / Windows 作为 client 连不同 server,四节点组成一张跨域虚拟广域网。
节点可用任意段数、段值超 255 的逻辑地址(如 266.266.266.266.2),
数据面走合法 TUN IPv4;配合 .tprs 自定义后缀 hosts 映射,即可用域名
curl http://266.266.266.266.2.tprs:5000/ 访问任意节点——实验 16 条互访路径全通。
# ① 服务器 A:网络 net1 = 10.99.0.0/24,联邦 peer = 服务器 B
tunnel_proxy pfserver --listen 0.0.0.0:18888 --password mykey --pool 7001-7010 \
--vnet2-net net1:10.99.0.0/24 \
--vnet2-peer SERVER_B_PUBLIC:42770@net1 &
# 服务器 A 本机注册为节点(逻辑地址可超 255,如 266.266.266.266.2)
tunnel_proxy vnet2 --server 127.0.0.1:18888 --password mykey --net net1 \
--vaddr 266.266.266.266.2 --tun-ip 10.99.0.2 --mtu 1400 --name tpvnetA &
# 服务器 A 业务(如 flask 监听 TUN IP:5000)
# ② 服务器 B:网络 net1 = 10.100.0.0/24(同网络名、不同 CIDR,避免池重叠),联邦 peer = 服务器 A
tunnel_proxy pfserver --listen 0.0.0.0:18888 --password mykey --pool 7001-7010 \
--vnet2-net net1:10.100.0.0/24 \
--vnet2-peer SERVER_A_PUBLIC:55471@net1 &
tunnel_proxy vnet2 --server 127.0.0.1:18888 --password mykey --net net1 \
--vaddr 266.266.266.211.2655.2 --tun-ip 10.100.0.2 --mtu 1400 --name tpvnetB &
# ③ 本地 client:WSL 连服务器 A、Windows 连服务器 B,注册到同一网络 net1
sudo tunnel_proxy vnet2 --server SERVER_A_PUBLIC:55471 --password mykey --net net1 \
--vaddr 266.266.266.265.1 --tun-ip 10.99.0.5 --mtu 1400 --name tpvnetW &
tunnel_proxy vnet2 --server SERVER_B_PUBLIC:42770 --password mykey --net net1 \
--vaddr 266.266.266.266.1 --tun-ip 10.100.0.5 --mtu 1400 --name tpvnetW &
# ④ hosts 加 .tprs 映射(每台机器),然后任意出口 curl:
# 10.99.0.2 266.266.266.266.2.tprs 10.100.0.2 266.266.266.211.2655.2.tprs
# 10.99.0.5 266.266.266.265.1.tprs 10.100.0.5 266.266.266.266.1.tprs
curl http://266.266.266.266.2.tprs:5000/ # 访问服务器 A 节点
--pool(random 模式必需)。
坑:vnet2 --hosts /etc/hosts 会覆盖整个 hosts(节点表写独立文件,.tprs 单独追加);
Windows 需 wintun 0.14.1+(0.11 缺导出)+ 管理员权限。→ 详见
docs/vnet2-federation-experiment.md场景 P · 传统 SD-WAN(规范逻辑地址,VNet v1 + vnet2)
用规范私有 IPv4(10.x / 172.16.x / 192.168.x)
作为逻辑地址,把多台机器打通成一张企业级虚拟广域网(SD-WAN):不关心底层公网/NAT,
只关心 Overlay 上的一层标准三层地址,各分支站点经隧道互通。
两个版本都能用规范逻辑地址,按场景选:
- VNet v1(
vnet):规范虚拟 IP(默认10.99.0.0/16), 单网络中心辐射,配置最简,适合中小规模分支互联; - VNet v2(
vnet2):--vaddr支持规范 IP, 多网络广域网,--vnet2-peer联邦跨域,适合多区域大型 SD-WAN。
P.1 VNet v1:规范虚拟 IP 中心辐射
server --virtual-net 组织一个虚拟网段,各机 vnet --virtual-ip
注册规范虚拟 IP(如 10.99.0.2 / 10.99.0.3),同网段三层互通。
# ① 公网 server:开启虚拟网络注册表
tunnel_proxy pfserver --listen 0.0.0.0:7000 --password mykey \
--pool 7001-7010 --virtual-net &
# ② 分支 A:注册 10.99.0.2
sudo tunnel_proxy vnet --server server.example.com:7000 --password mykey \
--virtual-ip 10.99.0.2 &
# ③ 分支 B:注册 10.99.0.3
sudo tunnel_proxy vnet --server server.example.com:7000 --password mykey \
--virtual-ip 10.99.0.3 &
# ④ 任意分支 ping / 访问另一分支
ping 10.99.0.3
curl http://10.99.0.3:8080/
in_vnet 判定),
适合单网段中心辐射;要把多个不同网段拼成大网,用 P.2 的 vnet2 联邦。P.2 VNet v2:规范逻辑地址 + 联邦跨域
各区域一台 pfserver,--vnet2-net 名称:CIDR 定义本区域网段,
区域间 --vnet2-peer 对端:端口@网络名 互相联邦;client 用
vnet2 --vaddr 规范IP 接入所在网络。
# ① 华东 server:网段 10.20.0.0/24,联邦华南(同一网络名 corp)
tunnel_proxy pfserver --listen 0.0.0.0:7000 --password mykey --pool 7001-7010 \
--vnet2-net corp:10.20.0.0/24 \
--vnet2-peer server-c:7000@corp &
# ② 华南 server:网段 10.30.0.0/24,联邦华东
tunnel_proxy pfserver --listen 0.0.0.0:7000 --password mykey --pool 7001-7010 \
--vnet2-net corp:10.30.0.0/24 \
--vnet2-peer server-b:7000@corp &
# ③ 华东分支 client:规范逻辑地址 10.20.0.2
sudo tunnel_proxy vnet2 --server server-b:7000 --password mykey \
--net corp --vaddr 10.20.0.2 --tun-ip 10.20.0.2 &
# ④ 华南分支 client:规范逻辑地址 10.30.0.2
sudo tunnel_proxy vnet2 --server server-c:7000 --password mykey \
--net corp --vaddr 10.30.0.2 --tun-ip 10.30.0.2 &
# ⑤ 跨区域互通(华东 ping 华南,用对端 TUN IP)
ping 10.30.0.2
curl http://10.30.0.2:5000/
corp),
仅 CIDR 不同;否则对端因「网络不存在」拒绝联邦注册。--vaddr 接受任意点分
十进制,传规范 IP 完全合法;--tun-ip 为数据面承载 IP,可省略由 server 从
本域池分配。联邦需双向 --vnet2-peer,server 需 --pool;
Windows 需 wintun 0.14.1+ + 管理员权限。→ 完整文档
docs/sdwan-tutorial.md1. 安装与构建
环境要求
Rust 1.97+ 工具链(用 rustup 安装)。三平台均支持:Linux / macOS / Windows。Windows 下建议使用 MSVC 工具链。
构建
git clone https://github.com/mcdn-git/tunnel_proxy.git
cd tunnel_proxy
cargo build --release
# 产物:target/release/tunnel_proxy
| 构建方式 | 命令 | 产物 | 说明 |
|---|---|---|---|
| 调试 | cargo build | target/debug/tunnel_proxy | 迭代开发,编译快 |
| 发布 | cargo build --release | target/release/tunnel_proxy | 生产使用,含优化 |
| 跨平台静态 | cargo build --target x86_64-unknown-linux-musl --release | 对应 target 目录 | Linux 静态链接,可拷到任意发行版 |
日志与验证
日志级别由 RUST_LOG 环境变量控制(默认 info,tunnel_proxy_core=debug):
RUST_LOG=debug tunnel_proxy socks5 -l 0.0.0.0:1080
# 验证所有子命令与参数
tunnel_proxy --version
tunnel_proxy pfserver --help
tunnel_proxy pfclient --help
tunnel_proxy --help # 查看全部子命令
2. 核心概念
三层架构
tunnel_proxy_rs 把"代理"拆成三层,各自正交、任意组合:
| 层 | 作用 | 例子 |
|---|---|---|
| 协议层 Handler | 决定"数据怎么被代理"(目标解析 + 认证 + 转发语义) | SOCKS5、HTTP、SS、Trojan、Vmess… |
| 传输层 Transport | 决定"底层连接怎么建立"(加密、封装、可靠传输) | TCP、TLS、WS、QUIC、KCP、gRPC… |
| 编排层 Router | 决定"流量往哪走"(分流、选链、限流、准入、观测) | Chain、Bypass、Selector、Limiter… |
例如「经 KCP 传输的 SOCKS5 代理」= 协议 SOCKS5 + 传输 KCP。而「反向穿透 pf」则把整条 mux 会话当作一条"隧道",公网端口的数据流在隧道内复用到内网任意处理端。
数据流
正向代理:客户端 → 传输层(加密/封装)→ 协议 Handler(解析目标)→ 目标服务。
链式:客户端 → 入口节点 → 中间节点1 → … → 出口节点 → 目标,每跳都是「传输 + 协议」组合。
反向穿透:公网用户 → pfserver 公网端口 → 加密 mux 隧道 → pfclient → 内网目标。单条隧道承载控制流(注册/心跳)与所有数据流。
3. 正向代理入口
代理协议作为独立服务启动(HTTP / HTTPS / HTTP/2 / HTTP/3 / Auto / SOCKS4a / SOCKS5 / SS / SS2 / SSR / SSU / SNI / Relay / Trojan / Vmess / Vless / File 等)。客户端把代理地址指向这些端口即可。
SOCKS4 / SOCKS5 / Auto
SOCKS5 是最通用的代理协议,几乎所有工具都支持。tunnel_proxy_rs 的 SOCKS5 支持用户名密码认证与多用户。
# 基础(无认证)
tunnel_proxy socks5 -l 0.0.0.0:1080
# 单用户认证
tunnel_proxy socks5 -l 0.0.0.0:1080 -u alice -p secret
# 多用户(-a 可重复;启用时优先于 -u/-p)
tunnel_proxy socks5 -l 0.0.0.0:1080 -a alice:secret -a bob:hunter2
| 参数 | 默认 | 说明 |
|---|---|---|
-l, --listen | 0.0.0.0:1080 | 监听地址 |
-u, --user | — | 用户名(开启认证) |
-p, --pass | — | 密码 |
-a, --users | — | 多用户 user:pass,可重复 |
验证:
curl -x socks5h://127.0.0.1:1080 https://example.com
curl -x socks5h://alice:[email protected]:1080 https://example.com
SOCKS4 / SOCKS4a:兼容老客户端,无认证。
tunnel_proxy socks4 -l 0.0.0.0:1080
Auto:同一端口自动协商 HTTP / SOCKS4 / SOCKS5(按首字节嗅探)。适合客户端协议不确定的场景。
tunnel_proxy auto -l 0.0.0.0:1080
curl -x socks5h://127.0.0.1:1080 https://example.com # 走 SOCKS5
curl -x http://127.0.0.1:1080 https://example.com # 走 HTTP
HTTP / HTTPS / HTTP2
HTTP:标准 HTTP 代理,支持 Basic 认证与多用户。
tunnel_proxy http -l 0.0.0.0:8080
tunnel_proxy http -l 0.0.0.0:8080 -u user:pass
tunnel_proxy http -l 0.0.0.0:8080 -a user1:pass1 -a user2:pass2
curl -x http://127.0.0.1:8080 http://example.com
HTTPS:HTTP/2 over TLS(默认),--http1 切换为 gost 兼容的 HTTP/1.1 + TLS。缺省自动生成自签证书。
# HTTP/2 over TLS(默认)
tunnel_proxy https -l 0.0.0.0:8444
# 指定证书
tunnel_proxy https -l 0.0.0.0:8444 --cert server.crt --key server.key
# gost 兼容模式:HTTP/1.1 + TLS
tunnel_proxy https -l 0.0.0.0:8444 --http1
| 参数 | 默认 | 说明 |
|---|---|---|
--cert / --key | 自动自签 | PEM 证书 / 私钥 |
--http1 | false | HTTP/1.1 代理(gost https) |
-a | — | 多用户认证 |
curl -x https://127.0.0.1:8444 --proxy-insecure https://example.com
HTTP/2:明文 h2 CONNECT 代理(需支持 HTTP/2 的客户端)。
tunnel_proxy http2 -l 0.0.0.0:8082
SS / SS2 / SSR / SSU
Shadowsocks:经典密码代理。加密方式支持 aes-128-gcm / aes-256-gcm / chacha20-ietf-poly1305。
tunnel_proxy ss -l 0.0.0.0:8388 -m aes-256-gcm -k mypassword
tunnel_proxy ss -l 0.0.0.0:8388 -m chacha20-ietf-poly1305 -k mypassword
| 参数 | 默认 | 说明 |
|---|---|---|
-m, --method | aes-256-gcm | AEAD 加密方式 |
-k, --password | 必填 | 共享密码 |
SS2(Shadowsocks 2022):新一代 AEAD 方案。
tunnel_proxy ss2 -l 0.0.0.0:8390 -m 2022-blake3-aes-256-gcm -k mypassword
SSR(ShadowsocksR):支持三种协议插件(origin / auth_aes128_md5 / auth_sha1_v4)与混淆(plain / http_simple / http_post)。
# 基础 SSR
tunnel_proxy ssr -l 0.0.0.0:8389 -m aes-256-cfb -k mypassword
# 完整:CFB 流密码 + http_simple 混淆 + auth_sha1_v4 协议
tunnel_proxy ssr -l 0.0.0.0:8389 -m aes-256-cfb -k mypassword \
-o http_simple -p auth_sha1_v4
# 混淆校验域名(可选)
tunnel_proxy ssr -l 0.0.0.0:8389 -m aes-256-cfb -k mypassword \
-o http_simple -g www.example.com -p auth_aes128_md5
SSU:SS 的 UDP relay。
tunnel_proxy ssu -l 0.0.0.0:8388 -m aes-256-gcm -k mypassword
Trojan / Vmess / Vless
Trojan:TLS 包裹的 Trojan 协议,流量特征接近 HTTPS。
tunnel_proxy trojan -l 0.0.0.0:8443 -k mypassword
# 验证(需 TLS 客户端)
curl -x https://[email protected]:8443 --proxy-insecure https://example.com
Vmess / Vless:VMess 协议(支持 aes-gcm / chacha20 加密)与轻量版 Vless。
tunnel_proxy vmess -l 0.0.0.0:10086 --uuid 12345678-1234-1234-1234-123456789abc
tunnel_proxy vless -l 0.0.0.0:10086 --uuid 12345678-1234-1234-1234-123456789abc
| 参数 | 说明 |
|---|---|
--uuid | 用户 UUID(v4 格式) |
客户端配合 vmessclient / vlessclient 子命令做本地端到端验证。
SNI / Relay
SNI:按 TLS ClientHello 的 SNI 域名路由到不同后端(类似 frp 的 vhostHTTPSPort,但作为独立服务)。
tunnel_proxy sni -l 0.0.0.0:8443 -f routes.yaml
routes.yaml:
example.com: 127.0.0.1:8080
api.example.com: 127.0.0.1:9090
Relay:独立 relay 协议(VER + CONNECT/BIND/UDP 命令),支持用户认证。
tunnel_proxy relay -l 0.0.0.0:8421
tunnel_proxy relay -l 0.0.0.0:8421 -u alice -p secret
# 客户端(stdio 中继,支持 nodelay)
tunnel_proxy relayclient -s 127.0.0.1:8421 -u alice -p secret -t example.com:80
HTTP3 / WebTransport
基于 QUIC 的代理入口,降低握手延迟、抗丢包。
# HTTP/3 传输上跑 SOCKS5(gost h3socks)
tunnel_proxy h3socks -l 0.0.0.0:4433
# WebTransport 上跑 SOCKS5(gost wtsocks)
tunnel_proxy wtsocks -l 0.0.0.0:4433
混淆传输代理
把代理流量伪装成正常 HTTP/TLS 流量,抵御深度包检测与主动探测。
| 命令 | 伪装方式 | 关键参数 |
|---|---|---|
obfs | HTTP 请求头混淆 | -H 伪装 Host |
obfs4 | 均匀随机流量 + 定长认证帧(防探测) | -k 预共享密码 |
ohttp | HTTP 伪装 + 长度帧 | -H 伪装 Host |
otls | TLS 记录层伪装 | — |
pht | HTTP chunked 帧伪装 | — |
ftcp | 伪 TCP 握手 + 透传 | — |
tunnel_proxy obfs -l 0.0.0.0:1080 -H www.example.com
tunnel_proxy obfs4 -l 0.0.0.0:1081 -k obfpass
tunnel_proxy ohttp -l 0.0.0.0:1082 -H www.example.com
tunnel_proxy otls -l 0.0.0.0:1083
tunnel_proxy pht -l 0.0.0.0:1084
tunnel_proxy ftcp -l 0.0.0.0:1085
4. 传输层
传输层决定"底层连接怎么建":TCP 直连、TLS 加密、WS 伪装、QUIC 低延迟、KCP 抗丢包、gRPC 多路复用…
| 命令 | 协议 | 用途 |
|---|---|---|
ws / wsc | WebSocket | HTTP 隧道伪装,--tls 开启 WSS |
quic / quicclient | QUIC SOCKS5 | UDP 低延迟,弱网抗丢包 |
grpc / grpcclient | gRPC | HTTP/2 多路复用隧道 |
mtls / mtlsclient | mTLS | 双向证书认证,最高安全性 |
kcp / kcpclient | KCP | UDP 可靠流,支持 FEC 前向纠错 |
dtls / dtlsclient | DTLS | UDP 上的 TLS(PSK 认证) |
icmp / icmpclient | ICMP | QUIC-over-ICMP 隧道,需 root/管理员 |
h2 / h2client | HTTP/2 隧道 | TCP 转发经 h2 CONNECT |
h3 / h3client | HTTP/3 隧道 | QUIC 上的 TCP 转发 |
wt / wtclient | WebTransport | HTTP/3 双向流隧道 |
sshd / sshtunnel | SSH | SSH direct-tcpip 隧道 |
mtcp / mux | mux 复用 | 一条 TCP 承载多条流 |
unix | Unix socket | 本机高性能转发 |
tunnel | TCP 隧道 | 通用 TCP 隧道服务 |
# KCP 传输转发(FEC 纠错:data-shards 数据分片 + parity-shards 校验分片)
tunnel_proxy kcp -l 0.0.0.0:29900 -t 127.0.0.1:80 --data-shards 17 --parity-shards 3
# DTLS(PSK 认证)
tunnel_proxy dtls -l 0.0.0.0:29901 -t 127.0.0.1:80 -p psk123
# mux 复用
tunnel_proxy mtcp -l 0.0.0.0:9006
tunnel_proxy mux -l 0.0.0.0:9005 -t 127.0.0.1:80
ICMP 传输(QUIC-over-ICMP)
把 QUIC 数据报封装进 ICMP Echo 报文:客户端发 Echo Request(identifier = 客户端 ID,
0 则随机),服务器回 Echo Reply(flags=ACK,seq = 该客户端最新请求 seq);可靠性由 QUIC
重传 / 乱序重组保证,ICMP 报文本身允许丢失。适合网络层只放行 ICMP 的受限网络
(对应 gost icmp://)。需 root / 管理员权限(raw socket)。
# 服务器(root):监听 ICMP,把收到的数据转发到固定目标
sudo tunnel_proxy icmp -l 0.0.0.0 -t 127.0.0.1:80
# 客户端(root):stdio → ICMP 流 → 服务器 → 内网 80
echo hello | sudo tunnel_proxy icmpclient -s server --id 7
5. 链式代理
Chain 把多个节点串成一条转发链:本机入口 → 逐跳转发 → 链尾连目标。适合"过境中转"等场景。建链失败会整链重试。
tunnel_proxy chain -l 0.0.0.0:2080 -f chain.yaml
节点字段
| 字段 | 说明 |
|---|---|
name | 节点名 |
proto | 协议:Http / Socks5 / Shadowsocks / Shadowsocks2 / ShadowsocksR / Vmess / Vless / Trojan / Relay / Sni |
transport | 传输:Tcp / Tls / WebSocket / Wss / Grpc / Quic / Kcp / Dtls / Http3 / Wt / Obfs4 / Unix / Mtcp / Mtls / Mws / Mwss / Ohttp / Otls / Pht / Ftcp / Utls / Wg |
addr | 节点地址 host:port(Unix 为 socket 路径) |
user / pass | 用户名密码;Vmess/Vless 的 UUID |
method | 加密方式(SS cipher / Vmess aes-gcm·chacha20 / Utls 指纹) |
protocol | SSR 协议插件(origin / auth_aes128_md5) |
tls_cert / tls_key / tls_ca | 客户端证书(mTLS)/ 服务器 CA |
nodes:
- { name: hop1, proto: Socks5, transport: Tcp, addr: "127.0.0.1:1081" }
- { name: hop2, proto: Ss, transport: Tcp, addr: "127.0.0.1:8388",
method: aes-256-gcm, pass: "mypassword" }
- { name: hop3, proto: Trojan, transport: Tls, addr: "127.0.0.1:8443",
pass: "mypassword" }
多 hop 分组
hops 非空时优先走 hop 模式:链按 [hop1组, hop2组, …] 顺序推进,每组内轮询选节点,实现"每段多个可选出口"。
hops:
- nodes: [{ name: a1, proto: Socks5, transport: Tcp, addr: "1.1.1.1:1080" },
{ name: a2, proto: Socks5, transport: Tcp, addr: "2.2.2.2:1080" }]
- nodes: [{ name: b1, proto: Ss, transport: Tcp, addr: "3.3.3.3:8388",
method: aes-256-gcm, pass: "x" }]
客户端验证:curl -x socks5h://127.0.0.1:2080 https://example.com。
6. Router 编排与 API
Router 是完整的流量编排引擎:多条候选链 + 分流 + 选链策略 + 限流 + 准入 + 观测,单进程运行。
tunnel_proxy run -l 0.0.0.0:12081 -C router.yaml --api 127.0.0.1:18085 --reload
配置详解
chains: # 候选代理链(可多条)
- name: hop1
nodes:
- { name: p1, proto: Socks5, transport: Tcp, addr: "127.0.0.1:1077" }
strategy: RoundRobin # RoundRobin / Random / Weighted / Hash
bypass: # 直连名单(绕过代理)
- localhost
- 10.0.0.0/8
- "*.internal"
reverse: false # true = bypass 名单反向为"必须走代理"
max_conn: 1000 # 并发连接上限(0 = 不限)
admission: # 接入 IP 准入(白/黑名单)
deny: ["1.2.3.4"]
rate: 0 # 每连接速率限流(字节/秒,0 = 不限)
traffic: 0 # 每连接总流量上限(字节,0 = 不限)
hosts: { my.local: 127.0.0.1 } # 域名 → IP 映射
dns: 8.8.8.8:53 # 上游 DNS(默认系统 DNS)
dns_proxy: false # 经链解析(防污染)
| 策略 | 行为 |
|---|---|
RoundRobin | 轮询选链 |
Random | 随机选链 |
Weighted | 按节点权重选链 |
Hash | 按目标哈希选链(同目标恒走同链) |
API 控制台
| 端点 | 说明 |
|---|---|
GET /、GET /ui | 内嵌 Web 仪表盘(无外部依赖) |
GET /metrics | 指标(默认 JSON;Accept: text/plain 为 Prometheus 文本) |
GET /metrics/prometheus | 始终 Prometheus 文本 |
GET /status | 完整状态(指标 + 链信息 + 策略) |
POST /api/reload | 触发配置热重载 |
curl http://127.0.0.1:18085/metrics/prometheus
curl -X POST http://127.0.0.1:18085/api/reload
多服务模式
一个进程同时监听多个端口跑不同协议,共享同一 Router(准入/限流/观测)。
services:
- { name: socks, addr: "0.0.0.0:12081", proto: socks5 }
- { name: http, addr: "0.0.0.0:12082", proto: http }
- { name: ss, addr: "0.0.0.0:12083", proto: ss,
method: aes-256-gcm, password: "x" }
7. 端口转发与特殊服务
TCP / UDP 转发
# TCP 转发:本地 9000 → 127.0.0.1:8080
tunnel_proxy forward -l 0.0.0.0:9000 -t 127.0.0.1:8080
# UDP 转发(DNS 等)
tunnel_proxy forward -l 0.0.0.0:9000 -t 127.0.0.1:5353 -T udp
# 经代理链转发(-f chain.yaml)
tunnel_proxy forward -l 0.0.0.0:9000 -t example.com:80 -f chain.yaml
加密转发
RTCP / RUDP:AEAD 加密的 TCP/UDP 转发,防中间人嗅探。客户端以 stdio 中继接入。
# 服务器(监听)
tunnel_proxy rtcp -l 0.0.0.0:12000 -k password
tunnel_proxy rudp -l 0.0.0.0:12000 -k password
# 客户端(stdio 中继)
echo "ping" | tunnel_proxy rtcpclient -s 127.0.0.1:12000 -k password -t 127.0.0.1:80
Runix:加密的 Unix socket / Windows named pipe 承载(gost runix)。
tunnel_proxy runix -l \\.\pipe\runix -k password # Windows
tunnel_proxy runix -l /tmp/runix.sock -k password # Linux/macOS
tunnel_proxy runixclient -s /tmp/runix.sock -k password -t 127.0.0.1:80
DNS / File / Stdio / Redirect / Serial
# DNS 代理(UDP 53)
tunnel_proxy dns -l 0.0.0.0:5353 -u 8.8.8.8:53
nslookup example.com 127.0.0.1 -port=5353
# HTTP 文件服务
tunnel_proxy file -l 0.0.0.0:8081 -d /var/www
curl http://127.0.0.1:8081/index.html
# stdio 转发(SSH ProxyCommand:把 ssh 的 stdin/stdout 当连接)
tunnel_proxy stdio -t 127.0.0.1:8080
# 用法:ssh -o ProxyCommand="tunnel_proxy stdio -t 127.0.0.1:8080" user@host
# 透明代理(Linux root;非 Linux 自动切换 TUN 实现)
tunnel_proxy redirect -l 0.0.0.0:12345 -f router.yaml # TCP
tunnel_proxy redu -l 0.0.0.0:12345 -f router.yaml # UDP
# TUN / TAP 虚拟网卡(管理员权限 + 驱动)
tunnel_proxy tun --address 10.0.0.1 -f router.yaml
# 串口转发(三方向)
tunnel_proxy serial -p COM1 -t 127.0.0.1:8080 # 串口 → TCP 服务
tunnel_proxy serial -p /dev/ttyS0,115200,odd -t COM2 # 串口 → 串口
tunnel_proxy serial -p COM1 -l 0.0.0.0:8080 # TCP 监听 → 串口
8. 反向穿透 pf(重点)
内网穿透:内网服务没有公网 IP,由内网 client 主动连出(可穿 NAT)向公网 server 注册,公网用户访问 server 端口即触达内网。
架构与注册
架构:
公网用户 ──► pfserver(公网:7000) ──加密 mux 隧道──► pfclient(内网) ──► 内网目标
│ 隧道端口 :7000
│ 公网数据端口 :7001-7010
│ vhost 端口 :8080/8443/443
▼
公网可见:<server>:<端口>
工作流程:
- client 连 server 隧道端口,先做 SS2 AES-256-GCM 加密握手,再建立 mux 多路复用会话。
- client 发送注册帧(密钥、分配模式、可选域名/组名/端口),server 校验密钥并分配公网端口。
- 公网用户连公网端口 → server 在 mux 上打开一条数据流 → 转发到内网 client → client 按模式处理。
- 每 30 秒心跳保活(`--heartbeat-interval` 可调);client 断线后按指数退避(默认 1s→60s 封顶,`--reconnect-backoff`/`--reconnect-backoff-max` 可调)自动重连并重新注册,端口映射自动恢复。
TCP 端口映射
# 公网 server:隧道 7000,端口池 7001-7010,随机分配
tunnel_proxy pfserver --listen 0.0.0.0:7000 --password mykey --pool 7001-7010 --mode random
# 内网 client:把本地 80 暴露到公网
tunnel_proxy pfclient --server server:7000 --password mykey --target 127.0.0.1:80
# 公网用户:访问 http://<server>:<分配端口> 即到达内网 80
| 分配模式 | server 侧 | client 侧 | 适用 |
|---|---|---|---|
random(默认) | --pool 7001-7010 池内随机 | — | 多服务共存 |
fixed | --port 7001 固定 | — | 固定对外端口 |
client | --pool 7001-7010 校验 | --port 7001 指定 | client 主动要端口 |
UDP 穿透
tunnel_proxy pfclient --server server:7000 --password mykey --udp 127.0.0.1:5353
# 公网用户:nslookup example.com <server>:<分配端口>
# 实现:每数据报一条 mux 流一问一答(DNS 等场景),载荷带长度前缀分帧
虚拟主机 vhost
多个域名共享一个公网端口,服务器按请求头路由到注册了该域名的内网 client。支持三种协议入口:
| 入口 | server 参数 | 路由依据 | 公网访问 |
|---|---|---|---|
| HTTP | --vhost-http :8080 | Host 头 | curl http://app.example.com:8080 |
| HTTPS | --vhost-https :8443 | TLS SNI | curl -k https://api.example.com:8443 |
| HTTP/3 | --vhost-http3 :443(UDP) | QPACK :authority | curl --http3 https://app.example.com |
tunnel_proxy pfserver --listen 0.0.0.0:7000 --password mykey --mode fixed --port 7001 \
--vhost-http 0.0.0.0:8080 --vhost-https 0.0.0.0:8443 --vhost-http3 0.0.0.0:443
# 每个域名一个 client
tunnel_proxy pfclient --server server:7000 --password mykey --domain app.example.com --target 127.0.0.1:80
tunnel_proxy pfclient --server server:7000 --password mykey --domain api.example.com --target 127.0.0.1:8080
负载均衡组
同组多个 client 提供同一服务,共享一个公网端口;新连接按 RR 轮询分发到组内成员;某 client 断线自动移出,组空则释放端口。
tunnel_proxy pfserver --listen 0.0.0.0:7000 --password mykey --pool 7001-7010 --mode random
tunnel_proxy pfclient --server server:7000 --password mykey --group web --target 127.0.0.1:8081 # 后端 A
tunnel_proxy pfclient --server server:7000 --password mykey --group web --target 127.0.0.1:8082 # 后端 B
# 公网用户连 <server>:<分配端口>,连接轮流分发到 A / B
KCP / QUIC 承载
隧道底层可换 KCP(UDP 可靠流,弱网抗丢包,可开 FEC)或 QUIC(更低握手延迟)。server 与 client 的 --transport 必须一致。
# KCP 承载
tunnel_proxy pfserver --listen 0.0.0.0:7000 --password mykey --pool 7001-7010 --transport kcp
tunnel_proxy pfclient --server server:7000 --password mykey --target 127.0.0.1:80 --transport kcp
# QUIC 承载
tunnel_proxy pfserver --listen 0.0.0.0:7000 --password mykey --pool 7001-7010 --transport quic
tunnel_proxy pfclient --server server:7000 --password mykey --target 127.0.0.1:80 --transport quic
协议模式
公网端口可以直接是标准代理入口——协议解析与目标连接全部发生在内网侧,支持挂载 Router 编排。
# 公网端口 = 后端在内网的 SOCKS5 代理(可带 Router 链)
tunnel_proxy pfclient --server server:7000 --password mykey --mode client --port 8080 \
--proto socks5 --config router.yaml
# 公网用户:curl -x socks5h://<server>:8080 https://example.com
# 其他协议(--proto 支持全部正向入口)
tunnel_proxy pfclient --server server:7000 --password mykey --proto ss \
--method aes-256-gcm --proxy-password xxx
tunnel_proxy pfclient --server server:7000 --password mykey --proto trojan --proxy-password xxx
tunnel_proxy pfclient --server server:7000 --password mykey --proto vmess --uuid 12345678-1234-1234-1234-123456789abc
tunnel_proxy pfclient --server server:7000 --password mykey --proto ssr --method aes-256-cfb \
--proxy-password xxx --obfs http_simple --ssr-proto auth_sha1_v4
# 可用 proto:socks5/socks4/auto/http/http2/https/ss/ss2/ssr/trojan/vmess/vless/sni/file
虚拟组网 VNet
这是 pf 的「组网」能力(与「穿透」相对,构成双向服务):server 开启
--virtual-net 后组织一个虚拟网段,多台机器各跑 vnet(创建 TUN
网卡、注册一个虚拟 IP)加入,任意 client 用虚拟 IP 直接访问其它 client 及其内网资产
(ping / TCP / UDP 三层互通)。数据经 pf mux 隧道由 server 按虚拟 IP 路由转发。
# 公网 server:启用虚拟网络注册表(须有 --pool,供 vnet 会话使用)
tunnel_proxy pfserver --listen 0.0.0.0:7000 --password mykey --pool 7001-7010 --virtual-net
# 机器 A / B / C(root/管理员):各创建 TUN 网卡加入虚拟网段
sudo tunnel_proxy vnet --server server:7000 --password mykey --virtual-ip 10.99.0.2
sudo tunnel_proxy vnet --server server:7000 --password mykey --virtual-ip 10.99.0.3
# 互通验证(机器 A)
ping 10.99.0.3 # 三层 ICMP 互通
curl http://10.99.0.3:8080 # 访问其它机器上的服务
# 甚至可以通过 vnet 访问 server 本机内网服务(route add 到虚拟网段后)
--virtual-ip(必填,唯一)/--prefix(默认
10.99.0.0/16)/--netmask/--mtu(1400)/--name(tpvnet)/
--transport(默认 tcp)。UDP 承载(kcp/quic)在 NAT 后建议
--heartbeat-interval 5 保活 NAT 映射。数据面经 server 中转(V1;P2P 直连为后续)。
→ 详见 docs/protocols.md参数全表
pfserver
| 参数 | 默认 | 说明 |
|---|---|---|
--listen | 0.0.0.0:7000 | 隧道监听地址 |
--password | 必填 | 共享密钥(client 注册凭证) |
--pool | — | 公网端口池 7001-7010(random/client 模式) |
--mode | random | random / fixed / client |
--port | — | 固定公网端口(fixed 模式) |
--vhost-http | — | HTTP vhost 共享端口 |
--vhost-https | — | HTTPS vhost 共享端口 |
--vhost-http3 | — | HTTP/3 vhost 共享端口(UDP) |
--transport | tcp | tcp / kcp / quic / tls / mtls / ws / wss |
--tls-cert / --tls-key | — | TLS 服务端证书/私钥(tls/mtls/ws/wss;缺省自签) |
--tls-client-ca | — | mTLS 客户端 CA(mtls 必填) |
--oidc-secret / --oidc-issuer / --oidc-audience | — | OIDC 认证(frp auth.method=oidc,HS256) |
--tcpmux | — | TCPMUX 单端口(frp tcpmux,CONNECT 目标路由) |
--virtual-net | 关 | 启用虚拟网络注册表(供 vnet 客户端注册虚拟 IP 组网) |
--mark | — | socket 标记(gost mark/so_mark,Linux 策略路由) |
pfclient
| 参数 | 说明 |
|---|---|
--server | 服务器地址 server:7000 |
--password | 共享密钥 |
--mode | 分配模式(须与 server 一致) |
--port | 指定公网端口(client 模式) |
--target | 透明转发目标 host:port(与 --proto / --config / --udp 互斥) |
--udp | UDP 穿透(目标为本地 UDP 服务) |
--domain | vhost 域名注册 |
--group | 负载均衡组名 |
--transport | tcp / kcp / quic / tls / mtls / ws / wss(须与 server 一致) |
--tls-cert / --tls-key | 客户端证书/私钥(mtls 必填) |
--tls-ca / --tls-insecure | 信任的服务端 CA / 跳过校验(自签测试) |
--oidc-token | OIDC access token(server 启用 OIDC 时注册需携带) |
--tcpmux-target | TCPMUX CONNECT 目标(配合 server --tcpmux) |
--mark | socket 标记(gost mark/so_mark,Linux 策略路由) |
--sniffing | 嗅探首包 HTTP Host / TLS SNI 并记录日志(gost sniffing) |
--proto | 协议模式:socks5/socks4/auto/http/http2/https/ss/ss2/ssr/trojan/vmess/vless/sni/file |
--config | Router 编排 YAML(SOCKS5 入口 + 分流/选链) |
--user / --users / --pass | 认证(socks5/auto/http) |
--method / --proxy-password / --uuid | 密码代理参数(ss/ss2/ssr/trojan/vmess/vless) |
--obfs / --ssr-proto | SSR 混淆与协议插件 |
--cert / --key / --http1 | TLS(https/trojan) |
--dir | file 服务根目录 |
--routes | SNI 路由 YAML |
--heartbeat-interval | 心跳间隔秒数(默认 30,vnet/UDP 承载建议 5) |
--heartbeat-timeout | 心跳应答超时秒数(默认 5) |
9. 性能测试
内置 bench 工具:起 echo 目标后测延迟与吞吐(可经代理,可选传输层)。
# 1. 起 echo 服务器(目标)
tunnel_proxy bench echo -l 0.0.0.0:9000
# 2. 测延迟(经 SOCKS5 代理,100 次)
tunnel_proxy bench ping -s 127.0.0.1:1080 -e 127.0.0.1:9000
# 3. 测吞吐(5 秒)
tunnel_proxy bench tput -s 127.0.0.1:1080 -e 127.0.0.1:9000 -d 5
# 传输层可选 tcp / ws / quic(-T)
实测参考(2026-08-29 远程 NAT 联合测试):
- 本地内核链路:SOCKS5 吞吐 582–661 MB/s,延迟平均 0.21ms(P99 0.48ms),300 并发连接全通过;mux 单连接 200 并发流全通过。
- 公网穿透(经远程 pf + 云 NAT 网关):100 并发连接全通过,RTT 平均 104–118ms(物理链路 56ms,穿透开销约 6ms);吞吐受 NAT 网关带宽限速,非本项目瓶颈。
- 稳定性:长连接 30s 正常、断线自动重连 2s 恢复、HA failover 主备自动切换均通过。
完整测试报告:docs/test-report-2026-08-29.md。
10. WireGuard
基于 boringtun 的 WireGuard 实现(标准 Noise IK 握手 + chacha20poly1305 数据面 + 计数器)。密钥为 WireGuard 标准 base64 格式。
# 1. 生成密钥对
tunnel_proxy wg-keygen
# PrivateKey: xxx PublicKey: yyy
# 2. 服务器(UDP 监听,转发到固定目标;-k 服务器私钥,-p 客户端公钥)
tunnel_proxy wg -l 0.0.0.0:29500 -k <服务器私钥> -p <客户端公钥> -t 127.0.0.1:80
# 3. 客户端(stdio 中继;-k 客户端私钥,-p 服务器公钥)
tunnel_proxy wgclient -s server:29500 -k <客户端私钥> -p <服务器公钥>
echo "hello" | tunnel_proxy wgclient -s 127.0.0.1:29500 -k <客户端私钥> -p <服务器公钥>
11. 常见问题
Q:内网穿透连不上公网端口?
确认 server 端口池在防火墙放行、client 的 --mode 与 server 一致、--password 密钥相同。查看 client 日志(RUST_LOG=debug)确认是否完成注册。
Q:vhost 访问返回 404 / 直接断开?
域名未注册。检查 pfclient --domain 域名拼写与访问的 Host/SNI 完全一致。
Q:KCP 模式握手失败?
确认 server 与 client 的 --transport 一致;UDP 端口未被防火墙拦截。
Q:HTTPS 证书告警?
缺省使用自签证书,客户端需 --proxy-insecure 跳过校验;生产请用 --cert/--key 指定受信任证书。
Q:如何让配置改动生效?
run 加 --reload 自动轮询配置文件重载,或 POST /api/reload 手动触发。
12. 质量与文档
质量门禁(CI 强制):clippy 0 warning、fmt 0 diff、325 单元测试全绿、e2e 脚本实测。
cargo clippy --all-targets
cargo fmt --check
cargo test -p tunnel-proxy-core --lib
更多资料:
- test-report-2026-08-29.md — 全功能测试报告(远程 NAT 实测)
- test-report-2026-08-30.md — 生产级深度审计加固报告
- test-report-2026-08-31.md — 生产级完善轮(并发/协议/安全修复 + ICMP e2e 实测)
- compare.html — gost/frp 能力覆盖矩阵
- docs/README.md — 快速开始
- docs/protocols.md — 协议与传输详解(含反向穿透)
- docs/configuration.md — Router/Chain/Node 配置
- docs/api.md — HTTP 控制接口
- docs/deployment.md — 部署与运维