跳转到内容

故障排查指南

常见 rVPN 问题的解决方案。


症状: 客户端在 Connecting to wss://... 处挂起并最终超时。

检查:

  1. 服务器端口可访问:
Terminal window
# From a different machine
nc -zv your-server.com 443
curl -I https://your-server.com/api/v1/ws
  1. 防火墙允许端口 443:
Terminal window
sudo ufw status # UFW
sudo iptables -L -n | grep 443 # iptables
  1. TLS 证书有效:
Terminal window
openssl s_client -connect your-server.com:443 -servername your-server.com </dev/null 2>/dev/null | openssl x509 -noout -dates
  1. WebSocket 路径正确。客户端连接到 {websocket_path}(例如 /api/v1/ws)。如果你的服务器使用不同路径,请更新 client.toml。

症状: 客户端显示 TLS handshake failedcertificate verify failed

原因和解决方案:

  1. Let’s Encrypt 证书未续期:
Terminal window
sudo certbot certificates
sudo systemctl reload rvpn-server
  1. server_address 中的主机名错误:
# The hostname must match the certificate
server_address = "wss://your-server.com/api/v1/ws" # Certificate must be for your-server.com
  1. SNI 不匹配:
# If connecting through a CDN or by IP
server_address = "wss://10.0.0.1/api/v1/ws"
sni_hostname = "your-server.com" # Certificate hostname
  1. iOS:证书验证问题(旧构建): 更新后请务必重新构建 Rust 库。rVPN 的 TLS 栈使用 BoringSSL,并附带内置的 Mozilla CA 根证书库,不会查询 iOS 钥匙串,因此系统层面的证书轮换或信任变更在应用重新构建之前不会生效。

症状: 客户端立即失败并提示 Connection refused

检查:

Terminal window
# Is the server running?
sudo systemctl status rvpn-server
# Is it listening on the right port?
sudo ss -tlnp | grep 443
# Can you connect locally? (uses whatever bind_address is set to)
curl -I https://127.0.0.1:443/api/v1/ws --insecure

症状: 连接开始但在加密设置期间失败。

原因:

  1. 预共享密钥包不匹配: 客户端和服务器必须使用同一份预共享密钥包。若服务器轮换了密钥而客户端持有旧包,可能失败。
Terminal window
# On server: regenerate prekey bundle
rvpn-server prekey-bundle
# Distribute new prekey-bundle.json to clients
  1. 身份密钥已更改: 若服务器身份密钥被重新生成,所有客户端都需要新的预共享密钥包。

“Too many connections” 或超出速率限制

Section titled ““Too many connections” 或超出速率限制”

症状: 成功连接一段时间后出现 Connection refusedRate limited

检查服务器速率限制:

[server.rate_limit]
max_connections_per_ip = 500 # default
max_handshakes_per_minute = 2000 # default

每个客户端连接占用一个名额。默认值已经很宽松——如果在单个出口 IP 上有非常庞大的客户端队列,请提高这些值;若你正被探测且希望更严格的限制,请调低。


客户端已连接但无法访问互联网

Section titled “客户端已连接但无法访问互联网”

检查 1:服务器上的 IP 转发:

Terminal window
sysctl net.ipv4.ip_forward
# Must return: net.ipv4.ip_forward = 1

若未启用:

Terminal window
sudo sysctl -w net.ipv4.ip_forward=1
echo "net.ipv4.ip_forward = 1" | sudo tee -a /etc/sysctl.conf

检查 2:服务器上的 NAT 规则:

Terminal window
sudo iptables -t nat -L POSTROUTING -v
sudo iptables -L FORWARD -v

你应能看到 MASQUERADE 规则和 FORWARD ACCEPT 规则。

若缺失:

Terminal window
sudo iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
sudo iptables -A FORWARD -i tun0 -o eth0 -j ACCEPT
sudo iptables -A FORWARD -i eth0 -o tun0 -m state --state RELATED,ESTABLISHED -j ACCEPT

检查 3:服务器安全组/防火墙允许出站: 服务器必须能在任何端口向任意 IP 发起出站连接,NAT 才能工作。

检查 4:server.toml 中 NAT 已启用:

[server.network]
nat_enabled = true

检查 5:客户端路由:

Terminal window
# On client, check routing table
ip route show # Linux
route -n get 0.0.0.0 # macOS
# Default route should point to tunnel interface

症状: 可以 ping 外部 IP 但无响应。服务器日志显示帧在被中继,但没有 “Relay completed”。

根源: SOCKS5 响应在隧道就绪之前就已发送。

解决方案: 这是旧版本中的 bug。请重新构建并重新部署:

Terminal window
cd rvpn-ios && ./build_rust.sh

检查服务器日志:

INFO rvpn_server: Listening on 0.0.0.0:443
INFO rvpn_server: WebSocket path: /api/v1/ws
INFO rvpn_server: TUN mode enabled

若 TUN 模式未启用,TUN 模式客户端将无法正常连接。


检查:

Terminal window
sudo ip addr show tun0
sudo ip link show tun0

若接口不存在:

  1. 确认 [server.tun]enabled = true
  2. 查看服务器日志中接口创建期间的错误
  3. 尝试更换接口名以避免命名冲突

检查:

Terminal window
# On server
ping 10.200.0.1 # From server to itself via tun0
# On client
ping 10.200.0.1 # Client should be able to reach server's TUN IP

若客户端无法到达 10.200.0.1,说明隧道未正确建立。


检查 1:代理正在运行:

Terminal window
curl --socks5 127.0.0.1:1080 https://api.ipify.org

若此命令返回你的 VPN 服务器 IP,说明代理工作正常。

检查 2:系统代理设置: 确保你的系统或应用配置为使用 127.0.0.1:1080 作为 SOCKS5 代理。

检查 3:浏览器代理设置: Chrome 和 Edge 使用系统代理设置。Firefox 有自己的代理设置。

检查 4:应用特有问题: 一些应用不支持 SOCKS5(只支持 HTTP 代理)。请使用 SOCKS5 转 HTTP 代理适配器,或切换到 TUN 模式。


症状: DNS 泄漏测试显示你的 ISP DNS,而非 VPN DNS。

解决方案: 启用 DNS 代理:

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

将你的系统 DNS 配置为 127.0.0.1。详细设置请参见 DNS 泄漏防范

Chrome 特有问题: Chrome 默认使用自己的安全 DNS 解析器,会绕过系统 DNS 和 VPN 隧道。

  • 桌面/Android:前往 设置 → 隐私和安全 → 安全 → 使用安全 DNS 并关闭它。
  • 清除 Chrome 的 DNS 缓存:访问 chrome://net-internals/#dns 并点击 Clear host cache
  • iOS:强制关闭 Chrome 或清除浏览数据以刷新其缓存。

每流的连接数限制(多路复用取舍)

Section titled “每流的连接数限制(多路复用取舍)”

multiplex 默认值为 false——即推荐的标准模式——因为每流一个 WebSocket 的模式与正常浏览的流量模式融合,并可规避针对多路复用形态的 DPI 分类器。代价是繁忙的浏览器可能开启数十条并发 WebSocket,在共享出口 IP 上会触及服务器的 max_connections_per_ip 限制。

两种处理方式:

  1. 请管理员提高默认值:
    [server.rate_limit]
    max_connections_per_ip = 1000
    max_handshakes_per_minute = 5000
  2. 在客户端启用 multiplex,将所有流共享到同一隧道(延迟更低,但流量特征更明显):
    [socks5]
    multiplex = true

可能原因:

  1. 高延迟: VPN 服务器地理位置较远
  2. 服务器过载: 单台服务器连接过多
  3. 带宽限制: 服务器上行饱和
  4. MTU 问题: 高延迟链路上的分片

解决方案:

  1. 在 client.toml 中降低 MTU:
[tun]
mtu = 1280
  1. 尝试距离更近的服务器
  2. 检查服务器负载:uptimehtop
  3. 若不需要 IPv6 则关闭:
[network]
ipv6_enabled = false
prefer_ipv4 = true

检查:

  1. 服务器地址包含 wss://(非 https://
  2. 身份密钥已生成(设置 -> 身份)
  3. 已导入预共享密钥包
  4. 服务器正在运行且可访问

重新构建 Rust 库:

Terminal window
cd rvpn-ios && ./build_rust.sh

可能原因:

  1. 网络不稳定(Wi-Fi 与蜂窝网络切换)
  2. iOS 在后台挂起应用
  3. VPN 配置文件被撤销

解决方案:

  1. 在 iOS 设置 -> VPN 中启用”始终开启的 VPN”
  2. 检查 iOS 更新
  3. 重新构建并重新安装应用

原因: 服务器的 DHCP 池已耗尽。

解决方案: 在服务器上扩大 DHCP 范围:

[server.network]
dhcp_range = "10.200.0.0/22" # /22 gives 1022 IPs instead of 254

或断开未使用的客户端。


症状: 应用显示 “Connected” 但没有流量,或者在从 App Store 更新或从 Xcode 重新构建后连接立即失败。

原因: macOS 独立于应用在系统设置中保留 VPN 配置文件。更新后,保存的配置文件的隧道扩展引用因扩展代码签名变化而失效。应用尝试启动旧扩展,但它已不复存在。

解决方案:

  1. 打开系统设置 > VPN(或较新 macOS 上的系统设置 > 通用 > VPN 与过滤)。
  2. 删除 rVPN 条目。
  3. 重新打开 rVPN 应用并连接。应用会自动创建全新的配置文件。

此问题在 1.2.4 及更高版本中已解决,该版本会在启动时自动检测并替换陈旧的配置文件。


“Failed to start VPN” 或连接静默失败

Section titled ““Failed to start VPN” 或连接静默失败”

检查:

  1. 打开 rVPN 应用并前往设置(Cmd+,)。确认配置文件的 Identity KeyPrekey Bundle 都显示绿色对勾。
  2. 服务器地址必须以 wss:// 开头且末尾无空白。
  3. 服务器必须正在运行且在 443 端口可访问。

若配置文件缺少密钥:

  1. 在配置文件编辑器中生成新的身份密钥。
  2. 从你的服务器管理员处导入预共享密钥包。

若密钥齐全但仍然失败:

  1. 从系统设置 > VPN 中删除 VPN 配置文件。
  2. 删除 rVPN 应用。
  3. 从 App Store 重新安装。
  4. 重新配置并重新连接。

macOS 应用运行本地 DNS 代理用于分流的 DNS 解析。若 DNS 失败:

  1. 检查服务器地址是否可从你的网络访问。
  2. 尝试在配置文件编辑器中关闭分流以测试全隧道模式。
  3. 查看服务器日志中的 DNS 代理错误。

Rust 层日志(绕过 macOS 日志脱敏):

Terminal window
cat ~/Library/Group\ Containers/group.org.rvpn.client/rvpn_tunnel_rust.log

系统级日志(在 macOS 12+ 上可能被脱敏):

Terminal window
log show --predicate 'subsystem == "org.rvpn.tunnel"' --last 5m --level debug

也可以使用 Console.app:按子系统 org.rvpn.tunnel 过滤。


检查:

[split_tunnel]
enabled = true # Must be true for any bypass to work
builtin_bypass_countries = ["CN"]

确认规则已加载: 客户端日志应在启动时显示绕过规则:

INFO rvpn_client: Split tunnel enabled, X networks bypassed

检查路由表:

Terminal window
ip route show # Linux
route -n get 0.0.0.0 # macOS

确保被绕过的网络不在 VPN 路由表中。


原因:

  1. 流媒体服务可能使用 GPS/区域设置信号,不仅是 IP
  2. 账户支付货币和历史会影响内容
  3. CDN IP 可能与国家绕过数据不匹配

解决方案:

  1. 清除浏览器/应用的 cookie 和缓存
  2. 使用浏览器扩展伪造时区和区域设置
  3. 可能需要全隧道模式(不做绕过)

检查到服务器的延迟:

Terminal window
ping your-server.com

若到服务器的延迟本身就高,问题在于地理距离,而非 VPN。

优化:

  1. 使用距离更近的服务器
  2. 在卫星或高延迟链路上降低 MTU:
[tun]
mtu = 1280

检查:

  1. 服务器带宽:使用 iperf3 测试到服务器
  2. 客户端硬件:加密对旧设备的 CPU 是密集任务
  3. 网络拥塞

优化:

[performance]
worker_threads = 4
crypto_worker_count = 4
recv_buffer_size = 262144
send_buffer_size = 262144

获取详细的客户端日志:

Terminal window
RUST_LOG=debug rvpn -c ~/.config/rvpn/client.toml

获取服务器日志:

Terminal window
RUST_LOG=debug sudo rvpn-server -c /etc/rvpn/server.toml
Terminal window
# systemd journal
sudo journalctl -u rvpn-server -f
# kernel logs (for TUN interface issues)
dmesg | grep tun
Terminal window
# Trace path to server
traceroute your-server.com
# Trace path from server to target
# (on server) sudo tcpdump -i tun0 -n
日志消息含义
Listening on 0.0.0.0:443服务器启动成功
WebSocket path: /api/v1/wsWebSocket 端点已配置
TUN mode enabled服务器 TUN 接口已激活
X3DH handshake complete加密已建立
NAT enabled服务器将对客户端流量进行 NAT 伪装
Relay completed一次数据中继会话已完成
Too many connections已超出速率限制