OpenWrt 的 VPN 区域、转发与地址伪装:到底需要哪一个?
区域输入、转发与地址伪装回答的是不同问题。在打开 WAN 区域之前,先判断你的 VPN 流量究竟需要哪一项。
每当 VPN 遇上 OpenWrt,三件事总会被混在一起:开放端口、允许转发和开启地址伪装。它们回答的是不同问题,通常只有一项才是真正需要的。按流量所扮演的角色来读每一项控制,猜测就会变成判断,也会告诉你改动出错时该期待什么症状。先说出失败的是哪个角色,而不是你记得的那个复选框。
动手改控制项之前,先命名流量角色
区域输入决定什么能到达路由器本身。区域输出覆盖路由器自己产生的流量,区域转发是穿过区域流量的默认值,地址伪装则决定出站时是否改写源地址。这是四个不同的问题,而区域策略用同一个值一次性回答全部,所以整区改动是件粗笨的工具。一条具名规则可以只回答其中一个,而不碰其余。
有用的地图是按流量角色划分的,因为出问题时你能观察到的正是角色。下面每个角色都有一项决定它的控制,以及一个指向它的症状:
| Traffic role | Control that decides it | Where it lives in the config | Symptom when it is wrong |
|---|---|---|---|
| A client reaching a listener on the router | Input policy of the zone that carries the connection, or a rule for the port | option input in the zone stanza, or a named rule | The handshake never completes and the tunnel log says nothing |
| A tunnel client reaching the router itself | Input policy of the tunnel zone | option input in the VPN zone | A ping to the gateway fails |
| A tunnel client reaching another LAN host | Forwarding from the tunnel zone to the LAN zone | config forwarding plus the zone assignment | The gateway answers and the file share times out |
| The router's own traffic leaving the WAN | Output policy, and translation if the far side needs it | option output and option masq | The tunnel never establishes, or replies vanish |
路由器上的监听服务只需要一条狭窄的输入规则
路由器上的 OpenVPN 服务器接收发往路由器本身的流量,因此它的外层连接取决于承载它的区域的输入策略。放行所配置的传输方式与端口,其余一律保持拒绝。单条端口规则比整区放行小得多,而且一年之后你还能解释它。
有两件事让这条规则值得保留:它点名了服务实际使用的端口,而且就写在区域定义旁边,下一个人能看懂它为何存在。下面几行只是形态,端口代指服务器上配置的值。服务迁移时两处都要改,因为留在旧端口上的规则要等到审计才会被发现。
config zone
option name 'wan'
option input 'REJECT'
option forward 'REJECT'
option output 'ACCEPT'
option masq '1'
config rule
option name 'allow-openvpn'
option src 'wan'
option proto 'udp'
option dest_port '1194'
option target 'ACCEPT'重载之前先校验,因为防火墙文件里的语法错误可能让路由器失去可用的规则集。使用 fw4 的版本里,检查是独立命令,它会大声失败,而不是默默接受坏掉的一段。确认通过之后再重载,并把上一份文件留在能还原的位置。
fw4 check
service firewall reload客户端请求走的是转发,不是输入
认证之后,隧道客户端请求 LAN 服务产生的是被转发的流,因此决定它的是隧道区域与 LAN 区域之间的转发关系。把隧道接口指派给目标区域,再声明方向、来源与服务。区域指派才让转发规则有意义,两者必须合起来读。把隧道区域写成来源、LAN 区域写成目的地的转发关系读起来是一个有意的决定,而两次整区放行读起来像事故。
到达路由器本身仍然走输入路径,所以 ping 网关并不能说明它后面的文件共享。这两种失败住在不同的配置块里,要用不同的改动修复。改任何一条之前,把两条路径分别写下来。
地址伪装是路由决定,不是许可
地址伪装改写选定出站流量的源地址。它可以挽救远端没有回程路由的出口设计,也会让按地址记录或授权的服务看不到单个客户端的地址。关掉它是一个关于回程的路由选择,而不是堵住入站漏洞的安全开关。开着转换能工作、一关就失败的隧道,通常缺的是回程路由,不是防火墙规则。
走路由的替代方案需要在远端有回程路由,而不是做转换。两种方案都不提供防火墙许可或应用账户,所以关掉地址伪装几乎从不能修好一个哪儿都到不了的隧道客户端。IPv4 与 IPv6 策略也要分开处理,因为一个转换设置描述不了两个协议族。
用一条放行和一条拒绝的请求来证明判断
发一条应当放行的请求和一条应当拒绝的请求,然后指出做出每一次决定的那项控制。碰巧加载出来的页面不是证据;证据是匹配上的规则,以及它匹配在哪个链里。拒绝和成功一样重要,因为它说明策略在做事,而不是一切都放行。
当前版本上有两条命令能给出这个证据。请求被接受时,匹配规则上的计数器会动;如果你为该规则开了日志,日志会显示丢弃:
nft list chain inet fw4 forward_wan
logread -f | grep -i -E 'DROP|REJECT'改任何防火墙策略之前,先留一条仍能用的管理通路,并遵循配置负责人的校验与回滚流程。把人锁在路由器之外的改动不是测试结果,而是第二次事故。每次观察都记下区域与流量角色,让这对结果解释策略,而不是描述一次侥幸的页面加载。