转发 TCP 1723 往往只能解决 PPTP 的前半部分,剩下的部分依旧不通,所以 Windows 在尝试时仍返回错误 807。下一个念头是为端口 47 添加规则,而正是这一步白白浪费一下午:GRE 是 IP 报头里的协议号,不是转发表能匹配的端口。在路由器放行协议 47 并将它与同一次呼叫绑定之前,隧道无法启动。下面几节先区分这两条通道,再逐一测试。

端口表里没有协议号这一行

PPTP 使用两种以不同方式失败的会话。TCP 1723 上的那一种是发起呼叫、传递链路信息,并在用户断开时拆除它。载荷一侧运行在 GRE 内部,IP 报头用协议号 47 标记它,在这条隧道里 PPP 协商链路,而 MS-CHAPv2 校验凭据。

由于 GRE 不携带传输层报头,它不暴露任何端口,因此为端口编写的规则没有可匹配的对象。转发 1723 的路由器为该 TCP 会话建立一条映射就到此为止。处理后半段的固件把这一特性称为 PPTP passthrough 或 PPTP ALG,有些固件两者都不提供,也从不提及这个缺口。复选框上的标签远不如协议 47 究竟是否被识别重要。

数据通路中断时 Windows 报告什么

错误 807 表示连接无法完成,实践上意味着呼叫到达了服务器,而数据通道没有建立。这是对传输层的判断,而不是对账户的判断。错误 691 才指向凭据或认证协议不匹配,所以它把你带到完全不同的方向。

在碰密码之前先处理传输层。为了追查 807 而更改凭据,会把真正的故障留在原处,并让下一次尝试更难解读。

为什么第二个客户端会破坏原本正常的隧道

由于没有端口可供区分,NAT 设备无法像区分两个 HTTPS 会话那样区分两个 PPTP 客户端。因此许多消费级设备只允许一次 PPTP 呼叫,并按源地址跟踪它。原本单独工作的笔记本电脑,在第二台机器拨出后就不再完成连接,从客户端一侧看故障像是随机的。这种模式属于固件,任何配置文件改动都不会改变它。

在两个客户端都拨号时观察连接表。如果只有第一台主机始终持有映射,路由器就到达了它所能支持的边界,客户端任何设置都推不动它。

证明是哪一半在失败

在改动路由器之前先确认 TCP 1723 能够到达,因为那个答案决定你在测试哪一半。在 Windows 客户端上针对你自己的服务器名运行这些命令。第一条打印端口是否应答,第二条在不弹对话框的情况下拨号,这让重复尝试可以比较。

Test-NetConnection vpn.example.com -Port 1723
rasdial "Work VPN"

端口测试结果为真,意味着控制通道是通的,GRE 是剩下的嫌疑对象。结果为假,意味着路由、过滤器或转发出了问题,任何 GRE 改动都救不了。数据一侧必须在能看到的地方观察,也就是服务器端或路由器上。

tcpdump -ni any proto 47

Wireshark 里的等价写法是显示过滤器 ip proto 47,把它交给不熟悉 shell 的人更容易。GRE 到达却没有回应发出,意味着返回路径需要修复。

什么才真正修复这个错误

在路由器开放该设置的地方,启用 PPTP passthrough,或者在接受规则的固件上显式允许协议 47。在 RouterOS 上,forward 规则直接匹配协议,这是基于端口的转发永远做不到的。消费级固件通常把同样的决定藏在复选框后面,有时放在安全设置而不是端口转发下面。如果没有这样的控制项,客户端上没有任何东西能补偿。

/ip firewall filter add chain=forward protocol=gre action=accept
/ip firewall filter print where protocol=gre

替换 PPTP 是另一种选择,而且往往更便宜。自己终结 VPN 的路由器为入站客户端避免了双重 NAT,而基于端口的 NAT 已经处理的协议根本不需要 passthrough:UDP 上的 OpenVPN、TCP 443 上的 SSTP,或用 NAT-T 把 ESP 包进 UDP 4500 的 L2TP/IPsec。PPTP 还依赖 MS-CHAPv2,其有记录的弱点使它在错误消失后仍不适合新的部署。

记下是哪条规则起了作用,因为当第二位用户申请访问时,同一个站点会遇到同一个限制。协议层面的修复应当写进网络笔记,下一位工程师会去那里查看。

相关文章