你有一台可用的 OpenVPN 服务器,还有一台同时运行 Cloudflare 设备软件的主机,而看似显而易见的下一步就是把客户端流量指向它。一台机器上的两个可用连接加起来也不是一个中转网关。缺的是一个有文档说明、可以转发属于他人数据包的角色,以及一套在这些数据包到达时对其进行分类的策略。

在任何规则之前先有四问:哪些流量进入、它接下来去哪里、回应如何找到回程,以及当第二条路径失效时设计会怎么做。前两个属于能力问题。

同一台主机上的两个服务不构成中转路径

设备客户端是为处理源自其运行主机的流量而构建的。它拦截名称解析或选定的应用流量,并通过自己的隧道发送,它的策略是为该设备的用户和该设备的进程编写的。从 OpenVPN 客户端转发来的数据包不是本地输出,所以同一套规则不会对它分类。这不是可以用更宽的规则掩盖的配置细节,因为它决定软件到底能不能看到这个数据包。

所以设计问题其实是能力问题。要么已安装的产品拥有一个有文档说明、能为其他网络转发流量的角色,要么中转功能完全属于别处。

Cloudflare 的哪个角色有权转发

Cloudflare 的设备客户端提供范围不同的模式:只做名称解析、只处理设备流量,有时两者兼有。这些模式都不会把主机变成私有网段的路由器,而该网段是从另一条隧道进来的。专用的路由角色是另一个产品,有自己的连接器、注册流程和网络模型。

QuestionWhat has to answer it
Does the installed product forward packets from other hosts?A documented routing or connector role, not a device mode
Which prefixes does the connector advertise?Its own configuration and status output
Does the server's own transport still take the old path?ip route get for the endpoint, before and after
Do replies return through the same path?Connection tracking counters on the forward rule

在围绕它设计路由之前,先检查已安装的角色。阅读连接器创建了哪个接口、它是否宣告特定前缀或默认路由,以及本地策略是否同时适用于转发的数据包和本地数据包。如果只处理本地流量,那么无论翻译规则怎么写,OpenVPN 服务器都不能成为中转点。

公共出口的需求也必须在这里精确表述。Cloudflare 为转发的客户端流量提供出口是一个具体用例,必须对照你实际拥有的服务来确认。

让外层隧道独立于新路由

一旦你添加指向新接口的默认路由,服务器自身的出站流量就开始争用它,其中既包括对 OpenVPN 客户端的回应,也包括你到这台机器的 SSH 会话。常见症状是隧道建立后随即断开,或者改动看似生效,管理员却被锁在门外。比较改动前后到端点的 ip route get,并用策略路由或主机路由把服务器自身的传输留在原处。这项比较要在机器本身上做,因为服务器对自己路由的看法才是关键。

只为服务器公网地址开例外本身不够,因为每个远程管理员的回程都是不同的流。先决定哪些流必须挺过这次改动,然后逐一验证,而不是假设第一个能覆盖其余。

把转发和翻译限制在一条流上

收到的数据包走转发路径而不是本地输出路径,所以真正重要的规则在 forward 钩子里。当下一跳接口需要翻译时,把源限制在客户端池、目的限制在允许范围、出口限制在那一个接口。只绑定接口的 masquerade 规则自己并不选路,也不会允许绕过任何其他过滤器的转发。

提前决定失败时关闭的行为,然后进行测试。停掉后续路径,确认客户端失去预期出口,而不是悄悄回落到普通上行链路,因为那正是直到流量从错误的门出去才有人注意到的结果。对名称解析和 IPv6 重复检查,因为只针对 v4 的规则集会留下一条开放的 v6 路径。

写下你最终确定的四个答案,以及证明每一条的观察。你能描述出来的中转路径,才是下次事故复盘时你能为之辩护的路径。

相关文章