Tor 中继与 VPN 服务器:为什么不能互相替代
Tor 中继上开放的端口不是 VPN 端点。先检查端口实际提供什么服务、中继的角色、SOCKS 监听范围以及配置文件。
你有一个地址,端口有应答,客户端也毫无怨言地接受了它。这些都不能让一台 Tor 中继成为 VPN 端点,而这个错误代价高昂:配置文件导入得很干净,却在之后握手时失败。我按顺序使用下面四项检查;每一项都有停止条件,及早停止才是重点。如果第一项检查不通过,后面几项也帮不上忙。
检查端口实际提供什么服务
开放的端口只能证明有监听者,仅此而已。中继的 ORPort 在 TLS 握手之后说的是 Tor 自己的信元,所以一次成功的 TLS 探测几乎不能说明那里是否接受 VPN 协议:
nc -vz 203.0.113.20 443
openssl s_client -connect 203.0.113.20:443 -brief < /dev/null
要读证书,而不是只看有没有证书。中继提供的是自签名证书,名字故意毫不起眼,因为中继流量应当看起来像普通的 HTTPS;而 VPN 服务器的证书带有你的配置文件所期待的名字。如果对端从不回应 VPN 协议的第一个数据包,那么修改配置文件再多也改变不了结果。
如果该地址无法完成客户端发出的握手,就停在这里。这是协议给出的答案,不是配置问题,也是导入的配置文件永远卡在 'connecting' 的最常见原因。
检查中继的角色,而不是网络的规模
中继角色承担不同的工作。guard 是客户端的第一跳,中间中继在其他中继之间转发线路,exit 是会接触目的地的角色,bridge 则是通过 BridgeDB 分发的非公开入口。Tor 的术语表把这些定义分开保留;可达性是每个角色的一部分,而服务任意客户端的权限不属于其中任何一个。
exit 策略值得一读,因为它是唯一类似转发规则的部分,它约束的是 exit 允许出去的目的地,而不是允许进来的客户端。一条封锁 25 端口的严格 exit 策略说明的是对外发滥用的控制,而不是能否把 OpenVPN 客户端指向这台机器。
如果你是从声誉出发推理,就停下:中继会转发流量,并不等于该地址必须接受你的流量。Tor 通过共识和自有协议选择路径;VPN 客户端不是参与者,也没有可加入的线路。
检查 SOCKS 监听是本地还是公开
Tor 客户端为同一台机器上的应用提供 SOCKS 接口,默认只监听 loopback。那个监听是本地便利,不是中继向互联网提供的服务;把它当成公开代理,正是人们最终运行起自己并不想要的开放中继的原因:
ss -ltnp | grep 9050
curl --socks5-hostname 127.0.0.1:9050 https://check.torproject.org
绑定地址就是线索。127.0.0.1:9050 上的 SocksPort 在正常干活;而监听在 0.0.0.0 上、又能从外部访问的那个,就是开放代理,Tor 自带的访问策略控制正是针对这种暴露,它属于问题,而不是特性。
对于需要 Tor 的应用,把它指向 loopback 端口,并让 Tor 负责解析名字,上面 socks5h 的形式就是这样做的。不要用中继地址去替代那个端口;中继并不提供你的应用所请求的接口。
检查 VPN 配置文件是否对应真实的端点
VPN 配置文件是一堆期待:OpenVPN 需要服务器证书或 CA、客户端证书和密钥,通常还需要 TLS 密钥;WireGuard 则需要对端的公钥、一个端点和允许的 IP。这些都无法从一个地址和一个开放端口推导出来,所以这样拼出来的配置文件会在第一次交换时失败,而不是在连接时失败。
当有人交给你一份配置文件时,请对照你控制的端点或你能识别的服务商进行验证:
wg show
openvpn --config client.ovpn --verb 4
在 OpenVPN 日志里,TLS 协商错误会直接点出不匹配之处;在 wg show 中,没有握手行的对端从未完成过一次握手。两者都比客户端转圈的指示器更有信息量,也都指向密钥材料或协议,而不是 Tor。
检查你真正需要哪种保护
这一项检查决定架构。Tor 浏览器提供 VPN 没有的线路隔离与指纹防御;VPN 则改变目的地看到的地址,并在服务商那里认证你。两者之间如何选择是威胁模型问题,而不是兼容性问题,混为一谈会得到看起来私密、实际并不私密的配置。
串联是有顺序的。承载 Tor 流量的 VPN 是受支持的组合,因为 Tor 客户端只需要出站 TCP。而被隧道进 Tor 内部的 VPN 客户端并不是同一回事,也不是 Tor 客户端实现的东西,所以不要按那种方式规划。
在导入任何东西之前,确认以下四点:
- 端口要完成你的协议握手,而不只是 TCP 连接。
- 你知道主机的角色,不要把转发当成许可。
- 你使用的 SOCKS 监听是 loopback 且属于你自己,不是别人中继上的公开端口。
- 配置文件的密钥或证书属于你要连接的那个端点。