不开放端口也能访问 NAT 后面的工作站
没有入站端口的工作站仍可经由集线器、中继或应用代理访问。先比较各方案究竟承诺了什么,再作选择。
运营商 NAT 和上锁的办公路由器后面的两个端点都没有可转发的入站端口,而人的第一反应往往还是去要一个。更好的问题是:哪一侧能主动向外发起连接,又是哪一个可达服务被允许承载流量。四种方案对这个问题给出不同答案,路径被阻断时也以不同方式失败。在它们之间做选择,比的是保证,而不是协议名字。
四种方案,四种不同的承诺
下表是简版。把中间一列读成你可以验证的承诺,把最右一列读成没有人做过的承诺。
| Design | Who initiates | Promise you get | Promise you do not get |
|---|---|---|---|
| Routed VPN hub | Both ends, outbound to the hub | A routed path to permitted prefixes | Access to services no policy allows |
| Peer traversal with ICE | Both peers to a rendezvous service | A path tested between the two peers | A direct path through every NAT |
| TURN relay | Client outbound to a relay | Transport that survives symmetric NAT | Peer discovery or a usable directory |
| Application broker | Workstation outbound to a broker | One audited application session | Subnet-wide reachability |
适用哪一行取决于任务,而不取决于偏好。一次远程桌面会话、一个管理用 shell,以及对整个私有子网的访问 是三件并不需要同一个入口的事,哪怕它们恰好落在同一台机器上。
集线器改变的是谁向外发起连接,而不是允许什么
在采用路由式集线器的方案里,远端笔记本与工作站,或它前面的站点网关,各自向双方都能到达的服务建立一条出站隧道。工作站的路由器上没有任何东西会接受未经请求的连接,这正是该方案能穿过 NAT、并在站点没有固定地址时仍然可用的原因。随后集线器按自己的策略在两个内网地址之间路由流量。
代价是集线器必须存在、必须从两侧都能到达,而且必须有人运维。出站过滤必须放行该传输,而一个把它挡住的网络会直接让方案失败,哪怕根本不需要端口转发。
微妙之处在于:可达性与授权是在不同地方做出的两个独立决定。一条通往某个前缀的路由,并不说明该身份可以使用工作站上的哪个服务;一条放行隧道的防火墙规则,也不说明该账户能否登录。两者都要配置、都要测试,并把授权决定留给拥有该资源的系统,而不是留给路由表。
穿越只有在两端协议栈都实现时才有效
对等穿越是特定系统具备的能力,不是一个能改善 VPN 的设置。Interactive Connectivity Establishment 会收集若干个候选地址,并成对测试直到某一对可用:本地接口上的主机候选、由 NAT 暴露的信息构造出的服务器反射候选,以及在转发服务器上分配的转发候选。仅有私有地址并不是路径,因为对端无法路由到那里。
在否定中继这个选项之前,值得先把它弄明白。RFC 8656 把 TURN 描述为这样一种协议:客户端向服务器请求一个中继传输地址,服务器在该客户端与其对等方之间转发流量。因此承载数据的是中继,这与只帮助端点相遇的目录有本质区别。与对端交换中继地址是应用必须完成的协调步骤。
你无法承诺的是直连路径。对称 NAT 和部分企业防火墙会让打洞失败,一旦如此,系统要么退回中继,要么失败。你也不能据此断定两个经过转换的端点永远无法通信;带中继兜底的受支持协议栈之所以存在,正是因为它们常常可以。先决定可用性与直连性哪个更重要,然后去核实部署实际选中的是哪条路径,而不是假定一切顺利。
代理比网络更窄
当需求只是单个应用时,应用代理或由工作站发起的反向连接可能是最小的答案。工作站向外连接到代理,代理验证远端用户,只承载那一个应用会话。不会创建通往工作站所在子网的路由,因此远端会话被攻破也不会顺带获得通往它旁边每台设备的路径。
这种窄也有代价:每增加一个应用都需要各自的集成,而应用对本地网络所做的任何假定,例如它在附近服务器上打开的共享文件夹,都可能无法到达。代理还会把策略与日志集中到一处,这在那一处变成故障点之前是有益的。
先比较信任边界,再测试路径
终止隧道的集线器能够读取它路由的流量。当应用做端到端加密时,中继可以承载独立受保护的交换,而代理通常会终止它呈现的会话。在因为两者都加密就认定两种方案等价之前,先确定保护究竟在哪里结束。
接下来检查工作站向外实际能到达什么,因为上面每种方案都依赖于此。在工作站上运行这条命令,并换成你打算使用的主机名。
ss -lntup
nc -vz hub.example.com 443
curl -sS -o /dev/null -w "%{http_code}\n" https://hub.example.com
只有在获准身份下预期远端操作成功、未获批准的身份被拒绝,并且直连或中继路径不可用时的行为已知且已记录之后,才接受该方案。还要包含一次重连,以及工作站正常的启动环境,因为在办公室通过局域网发起的会话,检验不了远程访问真正依赖的任何东西。