一台机器同时运行网站和 OpenVPN 服务器,诱人的做法是让一个主机名指向它,然后把流量交给橙色云去处理。代理处理的是 HTTP 和 HTTPS。它处理不了 OpenVPN 会话,无论该会话使用哪个端口。两个域名,一个直连、一个走代理,成本为零,却能消除这一整类困惑。

两个域名,两种传输

给网站一个经过代理的记录,使其 HTTP 和 HTTPS 流量经过 Cloudflare。给 VPN 一个仅 DNS 的记录,直接解析到公网 VPN 入口,并让客户端使用为其配置的 UDP 或 TCP 端口。

两个域名最终可以指向同一台源站机器。区别在于客户端与那台机器之间发生了什么,而这个区别正是拆分的目的。

Cloudflare 的网络端口参考列出了普通 Web 代理接受哪些端口。那份清单说的是这些端口上的 HTTP 与 HTTPS,而不是碰巧共用同一端口号的任意协议。

端口不是协议

把 OpenVPN 挪到 TCP 443 并不会让它变成 HTTPS。代理仍然期望连接开始时是 HTTP 请求,而 OpenVPN 客户端发来的却是二进制控制报文。连接会以看起来像网络封锁的方式失败,因为日志里什么有用的信息都没有。

如果需求确实是要把 Cloudflare 的产品放进 VPN 的数据路径,请评估一个明确记录支持所需协议的方案。不要以为橙色云就是通用的 TCP 或 UDP 隧道,它是为 Web 流量服务的反向代理,有特定职责。

仅 DNS 的记录是那种无聊但管用的答案,也是最该先想到的。

一台机器仍然需要两个监听器

域名分开并不能让两个进程同时绑定同一个地址、端口和传输方式。如果 Web 服务器已经占用了所有地址上的 TCP 443,OpenVPN 实例就不能再拿下它,除非刻意安排。

把 VPN 监听器绑到另一个端口,或另一个地址,或在前面放一个有文档的复用器,并接受随之而来的运维成本。这些选择中的每一个都应该出现在防火墙规则里,因为没人记录的监听器,恰恰是事故中被漏掉的那个。把选定的绑定写进描述隧道的同一本运行手册。下一个人就不必在凌晨两点重新发现它。

证书跟随它所保护的那条连接

浏览器到 Cloudflare 的 TLS 连接,与 Cloudflare 到源站的连接,是两段独立的关系,各自使用各自的证书。浏览器看到的是边缘证书。源站向 Cloudflare 出示自己的证书,而 Cloudflare Origin CA 证书正是为第二段关系准备的。

该源站证书在 Full (strict) 模式下受 Cloudflare 信任,并不是浏览器普遍信任的证书。如果有人直接访问仅 DNS 的主机名并收到警告,那是信任路径改变后的预期结果,而不是加密停止的证据。

因此被直接访问的网站需要一条其浏览器信任的证书链。这可以与一个源站根本不打算被访问的代理站点并存。

OpenVPN 自带服务器身份与客户端认证,有自己的证书颁发机构和自己的控制信道保护。网站上的小锁并不能提供其中任何一项,两套配置流程应当保持分离。

暴露面跟着域名走

仅 DNS 的 VPN 记录会公开它指向的地址。如果该地址也是 Web 源站,源站就没有被隐藏;因为另一个域名走了代理就宣称它被隐藏,是那种一直存在到有人扫描为止的错误。

确定哪些 Web 请求可以直接到达源站,并在源站上强制执行,然后按 VPN 监听器自身的条件放行它。管理页面、配置下载和数据监听器可以有三套不同的暴露要求,即使一个软件包同时提供这三项。

把生成的链接保持在公网 Web 域名和 HTTPS 方案上,把客户端配置保持在 VPN 域名上,并使用真实的协议和端口。正常运行时,两种服务都不应依赖去改动对方的代理设置。

工作顺序:网站用带代理的域名,VPN 用仅 DNS 的域名,分开的监听器,每段关系各自的证书,最后用一个测试证明每个域名只到达它应该到达的服务。

相关文章