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 即可
需要认证:socks5 -u alice -p secret;多用户:-a alice:secret。加密代理用 ss / ssr / trojan 子命令。→ 详见 3. 正向代理入口

场景 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 日志会打印端口)
固定对外端口用 --mode fixed --port 7001;UDP(DNS/游戏)用 --udp。→ 详见 8. 反向穿透 pf

场景 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
vhost client 不占端口池;域名未注册返回 404。→ 详见 8.4 虚拟主机

场景 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 认证)
Router 支持多链轮询、bypass 直连、连接/流量限流、Webhook 事件。→ 详见 6. Router 编排与 API

场景 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
QUIC 同理(更低握手延迟);需要加密传输用 tls/mtls;WebSocket 承载用 ws/wss。→ 详见 8.6 传输承载

场景 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
无需安装任何客户端,SSH 原生支持。→ 详见 8. 反向穿透 pf

场景 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
--proto 支持 socks5/http/ss/trojan/vmess/vless 等全部协议。→ 详见 8.7 协议模式

场景 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
打洞流程:目标端候选地址(local + STUN 公网映射)经 frps 交换 → 访问端 UDP 打洞 → KCP 可靠流 + AES-256-GCM 加密数据面。全锥形/受限锥形 NAT 可穿透; 对称 NAT / CGNAT 无法穿透时自动回退中继。指定 --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]
公网完全不暴露端口,只有持密钥的访问端能连。→ 详见 8. 反向穿透 pf

场景 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
中继只转发 pf 已加密的字节流(SS2 + mux),中继不可解密;公共/自建中继均可。 对称 NAT/CGNAT 下 XTCP 打洞失败也会自动回退经中继。→ 详见 8. 反向穿透 pf

场景 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)
可靠性由 QUIC 重传保证,ICMP 报文本身允许丢失;客户端 ID 对齐 gost 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 侧内网资产
虚拟 IP 默认网段 10.99.0.0/16,可用 --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
server 所在网络完全无需给内网端口做 NAT 映射——穿透隧道的出口在内网 client 侧,内网端口对公网保持不可直连。→ 详见 8.2 TCP 端口映射

场景 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 节点
同网络名 + 不同 CIDR 是联邦组网关键;server 需 --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)

规范私有 IPv410.x / 172.16.x / 192.168.x) 作为逻辑地址,把多台机器打通成一张企业级虚拟广域网(SD-WAN):不关心底层公网/NAT, 只关心 Overlay 上的一层标准三层地址,各分支站点经隧道互通。

两个版本都能用规范逻辑地址,按场景选:

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/
v1 是严格模式:目标必须在虚拟网段内才转发(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/
联邦两端 server 必须用同一网络名(上例统一 corp), 仅 CIDR 不同;否则对端因「网络不存在」拒绝联邦注册。--vaddr 接受任意点分 十进制,传规范 IP 完全合法;--tun-ip 为数据面承载 IP,可省略由 server 从 本域池分配。联邦需双向 --vnet2-peer,server 需 --pool; Windows 需 wintun 0.14.1+ + 管理员权限。→ 完整文档 docs/sdwan-tutorial.md

1. 安装与构建

环境要求

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 buildtarget/debug/tunnel_proxy迭代开发,编译快
发布cargo build --releasetarget/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, --listen0.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 证书 / 私钥
--http1falseHTTP/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, --methodaes-256-gcmAEAD 加密方式
-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 流量,抵御深度包检测与主动探测。

命令伪装方式关键参数
obfsHTTP 请求头混淆-H 伪装 Host
obfs4均匀随机流量 + 定长认证帧(防探测)-k 预共享密码
ohttpHTTP 伪装 + 长度帧-H 伪装 Host
otlsTLS 记录层伪装
phtHTTP 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 / wscWebSocketHTTP 隧道伪装,--tls 开启 WSS
quic / quicclientQUIC SOCKS5UDP 低延迟,弱网抗丢包
grpc / grpcclientgRPCHTTP/2 多路复用隧道
mtls / mtlsclientmTLS双向证书认证,最高安全性
kcp / kcpclientKCPUDP 可靠流,支持 FEC 前向纠错
dtls / dtlsclientDTLSUDP 上的 TLS(PSK 认证)
icmp / icmpclientICMPQUIC-over-ICMP 隧道,需 root/管理员
h2 / h2clientHTTP/2 隧道TCP 转发经 h2 CONNECT
h3 / h3clientHTTP/3 隧道QUIC 上的 TCP 转发
wt / wtclientWebTransportHTTP/3 双向流隧道
sshd / sshtunnelSSHSSH direct-tcpip 隧道
mtcp / muxmux 复用一条 TCP 承载多条流
unixUnix socket本机高性能转发
tunnelTCP 隧道通用 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
实测(2026-08-31):WSL 与远程云服务器真实 raw socket 端到端 2/2 PASS, 详见 test-report-2026-08-31.md

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 指纹)
protocolSSR 协议插件(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>:<端口>

工作流程:

  1. client 连 server 隧道端口,先做 SS2 AES-256-GCM 加密握手,再建立 mux 多路复用会话
  2. client 发送注册帧(密钥、分配模式、可选域名/组名/端口),server 校验密钥并分配公网端口。
  3. 公网用户连公网端口 → server 在 mux 上打开一条数据流 → 转发到内网 client → client 按模式处理。
  4. 每 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 :8080Host 头curl http://app.example.com:8080
HTTPS--vhost-https :8443TLS SNIcurl -k https://api.example.com:8443
HTTP/3--vhost-http3 :443(UDP)QPACK :authoritycurl --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
未注册域名:HTTP 返回 404;HTTPS / HTTP3 直接断开(无法发明文错误)。vhost client 不占端口池。

负载均衡组

同组多个 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 到虚拟网段后)
vnet 参数:--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

参数默认说明
--listen0.0.0.0:7000隧道监听地址
--password必填共享密钥(client 注册凭证)
--pool公网端口池 7001-7010(random/client 模式)
--moderandomrandom / fixed / client
--port固定公网端口(fixed 模式)
--vhost-httpHTTP vhost 共享端口
--vhost-httpsHTTPS vhost 共享端口
--vhost-http3HTTP/3 vhost 共享端口(UDP)
--transporttcptcp / kcp / quic / tls / mtls / ws / wss
--tls-cert / --tls-keyTLS 服务端证书/私钥(tls/mtls/ws/wss;缺省自签)
--tls-client-camTLS 客户端 CA(mtls 必填)
--oidc-secret / --oidc-issuer / --oidc-audienceOIDC 认证(frp auth.method=oidc,HS256)
--tcpmuxTCPMUX 单端口(frp tcpmux,CONNECT 目标路由)
--virtual-net启用虚拟网络注册表(供 vnet 客户端注册虚拟 IP 组网)
--marksocket 标记(gost mark/so_mark,Linux 策略路由)

pfclient

参数说明
--server服务器地址 server:7000
--password共享密钥
--mode分配模式(须与 server 一致)
--port指定公网端口(client 模式)
--target透明转发目标 host:port(与 --proto / --config / --udp 互斥)
--udpUDP 穿透(目标为本地 UDP 服务)
--domainvhost 域名注册
--group负载均衡组名
--transporttcp / kcp / quic / tls / mtls / ws / wss(须与 server 一致)
--tls-cert / --tls-key客户端证书/私钥(mtls 必填)
--tls-ca / --tls-insecure信任的服务端 CA / 跳过校验(自签测试)
--oidc-tokenOIDC access token(server 启用 OIDC 时注册需携带)
--tcpmux-targetTCPMUX CONNECT 目标(配合 server --tcpmux)
--marksocket 标记(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
--configRouter 编排 YAML(SOCKS5 入口 + 分流/选链)
--user / --users / --pass认证(socks5/auto/http)
--method / --proxy-password / --uuid密码代理参数(ss/ss2/ssr/trojan/vmess/vless)
--obfs / --ssr-protoSSR 混淆与协议插件
--cert / --key / --http1TLS(https/trojan)
--dirfile 服务根目录
--routesSNI 路由 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 联合测试)

完整测试报告: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

更多资料: