跳转到内容

SOCKS5 代理模式

SOCKS5 模式是使用 rVPN 的默认且最灵活的方式。它在本地运行一个 SOCKS5 代理,供单个应用指向使用——而不会影响机器上其他流量。


Terminal window
rvpn -c ~/.config/rvpn/client.toml

默认监听地址:127.0.0.1:1080

运行后你会看到:

INFO SOCKS5 proxy listening on 127.0.0.1:1080

系统设置 → 网络 → 你的连接 → 详细信息 → 代理

启用 SOCKS 代理 并设置:

  • 服务器:127.0.0.1
  • 端口:1080

这会让所有系统流量(Safari、curl 等)通过 VPN。

设置 → 常规 → 网络设置 → 手动代理配置

  • SOCKS 主机:127.0.0.1
  • 端口:1080
  • 选择 SOCKS v5
  • 勾选 Proxy DNS when using SOCKS v5 以防止 DNS 泄漏(若已启用 DNS 代理 则无需)

Chrome 在 macOS 上使用系统代理。在 Linux 上,请使用 SwitchyOmega 扩展:

  1. 安装 SwitchyOmega
  2. 创建新配置 → 协议:SOCKS5,服务器:127.0.0.1,端口:1080
  3. 需要使用 VPN 时切换到该配置
Terminal window
curl --socks5 127.0.0.1:1080 https://api.ipify.org
Terminal window
export ALL_PROXY=socks5://127.0.0.1:1080
export HTTPS_PROXY=socks5://127.0.0.1:1080
export HTTP_PROXY=socks5://127.0.0.1:1080

添加到 ~/.bashrc~/.zshrc 以在会话间保持。


rVPN 还可以在 SOCKS5 代理旁运行一个 HTTP 代理。当应用或环境期望 HTTP_PROXY/HTTPS_PROXY 环境变量指向 HTTP 代理时非常有用(这是 curlgitnpmpip 和 Docker 等 CLI 工具最常见的约定)。

两个代理共享同一 WebSocket 连接池——同时运行两者不会带来额外开销。

[http_proxy]
enabled = true
listen_address = "127.0.0.1:8118"

重启客户端——你应看到:

INFO HTTP proxy listening on 127.0.0.1:8118
INFO SOCKS5 proxy listening on 127.0.0.1:1080

使用 HTTP 代理最常见的方式是通过环境变量。大多数 CLI 工具和编程语言会自动读取:

Terminal window
export HTTP_PROXY=http://127.0.0.1:8118
export HTTPS_PROXY=http://127.0.0.1:8118
export ALL_PROXY=http://127.0.0.1:8118

设置后,curlgitnpmpipwget 和 Docker 等工具无需任何逐应用配置即可通过 VPN:

Terminal window
# No --proxy flag needed — env vars are picked up automatically
curl https://api.ipify.org
git clone https://github.com/user/repo.git
pip install requests

添加到 ~/.bashrc~/.zshrc 以在会话间保持。

Terminal window
curl -x http://127.0.0.1:8118 https://api.ipify.org

HTTP 代理处理两种请求类型:

  • HTTP CONNECT — 用于 HTTPS。客户端发送 CONNECT host:443 HTTP/1.1,代理响应 200 Connection Established,随后流量通过加密隧道流向目标。
  • 明文 HTTP 转发 — 用于未加密的 HTTP。客户端发送 GET http://host/path HTTP/1.1,代理连接目标主机并转发请求。

两条路径均支持分流,并与 SOCKS5 使用相同的连接池。

如需要求 Basic 身份验证:

[http_proxy]
enabled = true
listen_address = "127.0.0.1:8118"
auth_enabled = true
auth_username = "user"
auth_password = "changeme"

客户端必须发送 Proxy-Authorization: Basic ... 请求头(当凭据放在 URL 中时,浏览器和 curl -x 会自动处理:http://user:[email protected]:8118)。

SOCKS5HTTP 代理
协议任意(TCP + UDP)仅 HTTP 和 HTTPS
环境变量ALL_PROXY=socks5://...HTTP_PROXY=http://...
浏览器支持macOS/Firefox 原生通用(所有浏览器)
CLI 工具支持部分工具(curl、Node)大多数工具(curl、git、pip、npm、Docker)
身份验证SOCKS5 用户名/密码HTTP Basic 认证
最佳适用按应用路由、UDP系统范围环境变量、CI/CD

大多数情况下,使用 HTTP 代理搭配环境变量——它与 CLI 工具和构建系统兼容性最广。仅在需要按应用路由或 UDP 支持时使用 SOCKS5。


分流让你只将部分流量路由通过 VPN,其余直连。这对需要通过 VPN 访问被封站点、同时保持本地网络和国内流量不受影响的场景非常有用。

client.toml 中启用自动绕过中国 IP 的分流:

[split_tunnel]
enabled = true
builtin_bypass_countries = ["CN"]

启用后,前往中国 IP 的流量(基于 APNIC 数据——约 8800 个网络)直连,其他所有流量路由通过 VPN。

[split_tunnel]
enabled = true
bypass_networks_file = "~/.config/rvpn/bypass-networks.txt"

bypass-networks.txt — 每行一个 CIDR:

192.168.0.0/16
10.0.0.0/8
172.16.0.0/12
[split_tunnel]
block_ads = true

在 DNS 层面拦截已知的广告和跟踪域名。不发送任何字节,不建立任何连接。


重要: 若不使用 DNS 代理,即使在使用 SOCKS5 代理时你的 DNS 查询也可能泄漏给 ISP。完整说明请参见 DNS 泄漏防范

默认情况下,DNS 查询由你的系统 DNS 服务器解析—— VPN 隧道之外。这意味着即使流量已被代理,你的 ISP 仍能观察到你查询了哪些域名。

rVPN 内置一个 DNS 代理,会通过同一条加密 WebSocket 隧道将所有查询在服务器端解析。它也支持分流:绕过域名在本地解析,被拦截的广告/跟踪域名会立即返回 NXDOMAIN,永不触碰网络。

[dns_proxy]
enabled = true
listen_address = "127.0.0.1:53"

注意: 端口 53 需要 root 或 CAP_NET_BIND_SERVICE。无特权测试请使用端口 5353(见下文)。

重启客户端——你应看到:

INFO DNS proxy listening on 127.0.0.1:53

sudo 运行客户端(以便绑定端口 53),然后添加 127.0.0.1 作为 DNS 服务器:

系统设置 → 网络 → 你的连接 → 详细信息 → DNS → +127.0.0.1

或通过命令行(将 Wi-Fi 替换为你的接口名):

Terminal window
sudo networksetup -setdnsservers Wi-Fi 127.0.0.1

完成后恢复原始 DNS:

Terminal window
sudo networksetup -setdnsservers Wi-Fi empty

以 root 运行客户端(或授予 CAP_NET_BIND_SERVICE 能力),并设置 listen_address = "127.0.0.1:53",然后将解析器指向它。

/etc/resolv.conf(直接):

nameserver 127.0.0.1

systemd-resolved — 添加到 /etc/systemd/resolved.conf

[Resolve]
DNS=127.0.0.1

然后重启:sudo systemctl restart systemd-resolved

[dns_proxy]
enabled = true
listen_address = "127.0.0.1:5353"

验证是否可用:

Terminal window
dig @127.0.0.1 -p 5353 example.com

响应将来自你的 VPN 服务器,而不是本地 ISP。


SOCKS5 代理支持两种连接到服务器的模式:

每个 SOCKS5 流打开各自独立的 WebSocket 连接,并进行自己的 X3DH 握手和 Double Ratchet。这是推荐模式。

为什么这是默认:

  • 流量模式与常见工具一致——每个连接都是独立的 WebSocket,类似正常的 HTTPS 浏览
  • 短连接更难被流量分类器识别和封锁
  • 故障隔离更简单——一个连接掉线不会影响其他连接
[socks5]
multiplex = false # default

所有 SOCKS5 流共享同一个 WebSocket 连接,共享一个 Double Ratchet 会话。每个 SOCKS5 CONNECT 通过同一隧道上的 CreateFlow/CloseFlow 控制消息创建逻辑”流”。

优点:

  • 单次 TLS 握手,单次 X3DH 密钥交换——相对每连接约 600ms 的开销约为 250ms
  • 0-RTT 流创建——数据无需等待服务器 ACK 即刻发送
  • 更低的服务器资源占用(一个 WebSocket、一个 ratchet,而非每流一个)
  • 服务器每个 mux 会话最多支持 2000 个并发流
  • 压测成功率 100%(相比标准模式约 85%)

权衡:

  • 单个长期存在的二进制流是一种独特的流量模式,分类器可能识别
  • 所有流共用一个连接——若断开,全部需重连

工作原理:

  1. 首个 SOCKS5 CONNECT 打开 mux WebSocket 隧道({server_path}/mux
  2. 执行 X3DH 握手建立共享的 Double Ratchet
  3. 后续流通过同一隧道发送 CreateFlow 控制消息
  4. 客户端立即发送数据(0-RTT)——服务器在连接目标时缓冲
  5. 数据通过多路复用帧流动

安全性: 0-RTT 优化不是 TLS 0-RTT。TLS 握手和 X3DH 密钥交换在任何数据流动前均已完成。重放保护由 Double Ratchet 提供——每条消息有唯一的 message_number,且 ratchet 拒绝 number < current 的消息(见 ratchet.rs:decrypt)。消息密钥在使用后即销毁,因此重放会失败并提示 “Message too old”。

配置:

[socks5]
multiplex = true
# mux_path defaults to {server_path}/mux automatically

如需显式覆盖 mux 端点:

[socks5]
multiplex = true
mux_path = "/api/v1/ws/mux"
标准多路复用
每会话 WebSocket 数每流 1 个1
X3DH 握手数每流 1 次1
服务器端流数无限制最多 2000
服务器端 WS 连接数N1
流量模式类正常 HTTPS单个长期存在的流
成功率(HK,15 分钟)约 85%100%
p50 延迟(HK)约 575ms约 315ms
p95 延迟(HK)约 2000ms约 1060ms
最佳适用DPI 规避、流量伪装可靠性、高吞吐

注意: 标准模式为每个 TCP 流打开一个 WebSocket。在繁忙网络下(例如浏览器打开许多标签),可能耗尽服务器的 max_connections_per_ip 限制。如需,请提高服务器的速率限制:

[server.rate_limit]
max_connections_per_ip = 500
max_handshakes_per_minute = 2000

要在特定接口上监听(例如与本地网络中其他设备共享代理):

[socks5]
listen_address = "0.0.0.0:1080"

安全提示: 仅在可信网络上暴露 SOCKS5 端口。默认没有身份验证。

添加身份验证:

[socks5]
listen_address = "0.0.0.0:1080"
auth_enabled = true
auth_username = "user"
auth_password = "changeme"

Terminal window
sudo nano /etc/systemd/system/rvpn-client.service
[Unit]
Description=rVPN Client
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
User=YOUR_USER
ExecStart=/usr/local/bin/rvpn -c /etc/rvpn/client.toml
Restart=on-failure
RestartSec=5
[Install]
WantedBy=multi-user.target
Terminal window
sudo systemctl daemon-reload
sudo systemctl enable --now rvpn-client

创建 /usr/local/etc/rc.d/rvpn_client

#!/bin/sh
# PROVIDE: rvpn_client
# REQUIRE: NETWORKING
# KEYWORD: shutdown
. /etc/rc.subr
name="rvpn_client"
rcvar="rvpn_client_enable"
command="/usr/local/bin/rvpn"
command_args="-c /usr/local/etc/rvpn/client.toml"
pidfile="/var/run/rvpn-client.pid"
load_rc_config $name
run_rc_command "$1"
Terminal window
chmod +x /usr/local/etc/rc.d/rvpn_client
echo 'rvpn_client_enable="YES"' >> /etc/rc.conf
service rvpn_client start