通过 HTTP 代理使用 OpenVPN:先读 CONNECT 回复
CONNECT 代理只转发字节,两端都需要 TCP。在怀疑证书之前先读 407、403 和 503,并保持服务器验证开启。
把 VPN 客户端指向公司 HTTP 代理,第一个有用的事实是:代理并不说 VPN 的协议。它向您指定的地址打开一条普通 TCP 连接,然后退到一边,让客户端和服务器在那条流上自行交换。客户端需要的一切,从传输类型到服务器的监听,都必须与这种安排相符。两种不匹配解释了大多数失败:面向 CONNECT 代理的 UDP 配置文件,以及被误认为 VPN 错误的代理回复。
代理承载什么,不承载什么
代理只是一个传输跳点。它不会变成您的浏览器代理,不会缓存您通过隧道访问的网站,除非有人刻意配置检查,否则它看不到内部流量。它打开的隧道按设计对它是不透明的。
这也意味着代理无法修复没有对应监听器的服务器。获准到达某个目的地,与该目的地上有服务在监听,是两件不同的事,只有前者属于代理管理员。
载体在两端都必须是 TCP
常规 CONNECT 代理只转发字节流,因此客户端必须使用流式传输。该情形的客户端片段如下:
proto tcp-client
remote vpn.example.net 1194
http-proxy proxy.corp.example 3128服务器端需要在 remote 行指定的端口上有一个真正的 TCP 监听器。在配置文件中把 proto udp 改成 proto tcp-client 只会创建一个期待流的客户端,并不会在对端创建流。如果同一台服务器在该端口上也通过 UDP 应答,那是另一个监听器,而不是同一个监听器的第二种模式。
存在独立 TCP 实例时,它的隧道设备、地址池和路由都是各自的资源。复制一份可用的配置并改动传输字样,会让这些资源仍指向原实例,于是产生一条认证成功却什么都不路由的连接。
先读代理回复,再看 VPN 结果
客户端的第一次交换是一条请求行,其中写明目标主机和端口。对这一行的回复告诉您究竟有没有字节流,而且它出现在任何证书或凭据被检查之前:
CONNECT vpn.example.net:1194 HTTP/1.1
Host: vpn.example.net:1194| Proxy reply | What it means | Where to look next |
|---|---|---|
407 Proxy Authentication Required | The proxy wants its own credentials | The client's proxy auth options, not the VPN account |
403 Forbidden | The destination or method is not permitted | The proxy's access policy for that host and port |
503 Service Unavailable | The proxy could not complete the upstream connection | The proxy's own logs and the server's listener |
对 CONNECT 返回 200 类回复意味着流已存在。它并不说明网关证书是否受信任、共享密钥是否匹配,也不说明用户账号是否有效。这些检查稍后在流内部进行,失败时给出的是客户端自己的消息,而不是 HTTP 状态行。请在客户端日志中寻找代理握手之后的第一个 OpenVPN 事件,而不是窗口关闭前的最后一行。
代理凭据和 VPN 凭据往往是不同团队掌握的不同身份。407 不是 VPN 账号的密码错误,证书被拒也不是代理权限问题。
CONNECT 不暴露什么
显式的 CONNECT 隧道不是拦截。代理转发字节,并不终止 VPN 的 TLS 会话,所以客户端对服务器证书的验证仍然有意义,应当保持开启。为了通过代理而关闭验证,解决的是另一个问题。
也存在组织刻意终止并检查 TLS 的独立安排。那些需要各自的信任配置和各自的策略决定,并不是普通 http-proxy 行所要求的。
TCP 套 TCP 的代价
让隧道走 TCP,会让外层流保持有序并重传,而内层流量通常也是 TCP。两套恢复机制并不协调,因此一个丢失的段可能让共享这条外层流的一切停住,直到它被重传。这是为兼容性付出的真实交换,不是免费的升级。
当网络别无选择时使用代理路径,在策略允许的地方优先直连 UDP。无论如何,改动之后要确认同一个代理、目的地和配置文件能走到下一阶段;在那个地址加载页面的浏览器用的是另一种协议,并不能证明隧道的事。