装好 VPN 的托管服务器最终会持有三个地址,而你即将配置的每个位置只对应其中一个。把服务商面板上的数字抄进 DNS、抄进监听器或抄进白名单,正是让一条原本能用的隧道变成谁都连不上的服务的方式。本指南把工作排好顺序,让每个地址都为一个明确用途而选。它还列出了确认你实际发布了什么的命令。

发布任何东西之前,先把三个地址画成图

按功能给它们命名。underlay 地址是机器用来经互联网抵达 VPN 端点的那个地址,它常常是服务商 NAT 之后的私有地址。隧道地址活在 VPN 内部,由服务器或客户端按产品不同下发。公网出口是远程网站在完成转换之后记录下来的那个地址,它不必存在于任何你能查询的接口上。

只显示一个公网地址的面板,对另外两个角色几乎没有说明。underlay 可达性是前提,不是买来的东西:家用路由器后的笔记本没有公网 IPv4 地址也能抵达托管的 VPN 端点。你不能做的是:写一个解析到无人转发的地址的名字,凭空造出一条入站路径。

按服务选地址,而不是按标签选

选数字之前,先写下服务器要做什么。对端维护白名单时,出站 API 调用需要稳定的出口。私有访问需要客户端能路由过去的隧道地址,以及绑定到该地址的监听器。公网托管需要服务商真正提供的入站映射,单靠出口地址给不了。

一台机器可以同时承担这三种用途,却仍然使用三个不同的地址。被打破的是「一个值就能覆盖全部」这个假设:

RequirementValue that belongs thereWhat you see when the roles are swapped
Outbound allowlistingPublic exitRequests reach the service but are rejected
Private client accessTunnel addressClient connects, nothing answers
Inbound web serviceProvider mappingName resolves, connection times out

入站那一行才是人们争论的地方。指向出口地址的记录不会创建监听器、不会开防火墙端口、也不会做端口映射,等着也不会改变这一点。当服务商把专用地址和入站规则一起卖时,这个组合才是你买到的能力;地址本身不是授权。

看清哪个地址是哪个的命令

读机器,不读面板。各系统的接口名不同,所以要把地址和设备对上,而不是信标签。

第一行列出每个 IPv4 地址及其设备,第二行问内核:去往一个已知外部目的地时会用哪个设备:

ip -brief -4 addr show
ip -4 route get 198.51.100.10
curl -4 -s https://ifconfig.me
ss -lntp | grep -E ':(443|1194)'

如果公网流量的路由查询回答了隧道设备,说明你的全局隧道生效了。监听器检查同样重要,因为只绑定 127.0.0.1 的进程永远不会在隧道地址上应答,无论你发布什么名字。

发布出去,然后从外部验证

只发布服务需要的值,不多发:托管用 A 或 AAAA 记录,出站调用用白名单条目,私有访问用客户端配置。然后从真正重要的位置测试,而那绝不是你刚改过的那台机器。

两项检查就能覆盖大部分,两者都便宜到可以留在脚本里:

dig +short vpn.example.net A
curl -4 -sS -o /dev/null -w '%{http_code}\n' https://vpn.example.net/health

一条证明记录存在的 DNS 应答,并不证明请求能到达;一次成功请求也只证明一条路径从一个网络可用。涉及白名单时,要从移动网络重复检查,因为你观察到的出口可能取决于地址族和所走的路径。记下你验证的是哪个族;能用的 IPv4 路径对 IPv6 什么也说明不了。

如果服务是入站的,光有出口地址不够

入站访问需要四样东西对齐:客户端能到达的名字或地址、把数据包送到机器的路由、接受它的监听器,以及不丢弃它的策略。VPN 改变第二项,有时也改变第一项,对第三、第四项毫无作用。当隧道就是投递路径时,客户端连的是隧道地址,而不是出口。

记下每项服务依赖哪个地址,并在服务商每次改动路由模型时重看这条记录。私下能应答、公网却失败,通常不是坏了,而是用错了身份在应答,修法是一次映射决策,而不是改防火墙。

相关文章