通过 VPN 转发 LAN 连接后 TCP 握手失败

通过 VPN 转发 LAN 连接后 TCP 握手失败

我们有一些安全的 Web 服务,包括网站,只有连接到服务所有者提供的 VPN 时才能访问,并且由于 VPN 帐户一次只允许一个用户连接,我们计划将 LAN 中的一台机器配置为网关,以处理流向安全服务的流量:

  1. VPN 通过运行 Ubuntu 18.04 bionic 的机器上的 OpenConnect 客户端连接。

    • 已验证 VPN 连接后会自动添加正确的路由,因为我们可以从安全服务器地址获得 ping 响应,还可以获得curl安全网站的内容。
  2. 要启用 LAN 转发,我们运行:

    sysctl net.ipv4.ip_forward
    
    # tun0: VPN | eth0: LAN
    iptables -A INPUT    -i tun0         -m conntrack --ctstate ESTABLISHED,RELATED          -j ACCEPT
    iptables -A FORWARD  -i eth0         -o tun0                                             -j ACCEPT
    iptables -A FORWARD  -i tun0         -o eth0 -m conntrack --ctstate ESTABLISHED,RELATED  -j ACCEPT
    iptables -t nat      -I POSTROUTING  -o tun0 -d <secured_host>                           -j MASQUERADE
    
  3. 我们在路由器上为运行 VPN 的机器添加了一条静态路由,以设置到安全服务的流量的下一跳。
  4. 当从 LAN 中的其他机器进行测试时,我们现在可以ping从安全服务器获取响应,但我们无法在浏览器中打开网站,如果我们尝试curl从安全的 Windows 服务器打开,我们会得到:
    curl: (35) schannel: failed to receive handshake, SSL/TLS connection failed
    
  5. 检查tcpdump运行VPN的机器显示:

    sudo tcpdump net <secured_host> -i eth0
      sudo:     unable to resolve host VpnGateway: Resource temporarily unavailable
      tcpdump:  verbose output suppressed, use -v or -vv for full protocol decode
    
      listening on eth0, link-type EN10MB (Ethernet), capture size 262144 bytes
      04:42:56.343467 IP <LAN_machine>.54061 > <secured_host>.https: Flags [SEW], seq 1815972292, win 64240, options [mss 1418,nop,wscale 8,nop,nop,sackOK], length 0
      04:42:56.358208 IP <secured_host>.https > <LAN_machine>.54061: Flags [S.], seq 916191674, ack 1815972293, win 4254, options [mss 1460,sackOK,eol], length 0
      04:42:56.359305 IP <LAN_machine>.54061 > <secured_host>.https: Flags [.], ack 1, win 64240, length 0
      04:42:56.361243 IP <LAN_machine>.54061 > <secured_host>.https: Flags [P.], seq 1:190, ack 1, win 64240, length 189
      04:42:56.388369 IP <secured_host>.https > <LAN_machine>.54061: Flags [.], ack 190, win 4443, length 0
      04:43:06.388820 IP <secured_host>.https > <LAN_machine>.54061: Flags [R.], seq 5583, ack 190, win 0, length 0
      04:43:06.391505 IP <LAN_machine>.54061 > <secured_host>.https: Flags [.], ack 1, win 64240, length 0
      04:43:06.405569 IP <secured_host>.https > <LAN_machine>.54061: Flags [R.], seq 1, ack 190, win 0, length 0
    
      8  packets captured
      10 packets received by filter
      0  packets dropped by kernel
    
    sudo tcpdump net <secured_host> -i tun0
      tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
    
      listening on tun0, link-type RAW (Raw IP), capture size 262144 bytes
      04:42:56.343504 IP <tun0_net>.54061 > <secured_host>.https: Flags [SEW], seq 1815972292, win 64240, options [mss 1418,nop,wscale 8,nop,nop,sackOK], length 0
      04:42:56.358199 IP <secured_host>.https > <tun0_net>.54061: Flags [S.], seq 916191674, ack 1815972293, win 4254, options [mss 1460,sackOK,eol], length 0
      04:42:56.359329 IP <tun0_net>.54061 > <secured_host>.https: Flags [.], ack 1, win 64240, length 0
      04:42:56.361251 IP <tun0_net>.54061 > <secured_host>.https: Flags [P.], seq 1:190, ack 1, win 64240, length 189
      04:42:56.388362 IP <secured_host>.https > <tun0_net>.54061: Flags [.], ack 190, win 4443, length 0
      04:43:06.388779 IP <secured_host>.https > <tun0_net>.54061: Flags [R.], seq 5583, ack 190, win 0, length 0
      04:43:06.391523 IP <tun0_net>.54061 > <secured_host>.https: Flags [.], ack 1, win 64240, length 0
      04:43:06.405552 IP <secured_host>.https > <tun0_net>.54061: Flags [R.], seq 1, ack 190, win 0, length 0
    
      8 packets captured
      8 packets received by filter
      0 packets dropped by kernel
    

我还应该做什么才能使事情顺利进行?

答案1

路由 VPN 的一个常见问题是 MTU。由于 VPN 封装,您的 tun0 接口的 MTU 较低(低于正常的 1500),本地发起的连接知道这一点,并相应地调整通告的 TCP MSS(最大段大小)。但您其他 LAN 主机上的软件没有知道这一点(这些主机只知道它们自己的以太网接口)并且仍然基于完整的 1500 字节 MTU 与 MSS 建立 TCP 连接。

通常情况下,这不会成为问题——每当 HTTPS 服务器尝试向您发送较大的数据包时,远程 VPN 网关都会以 ICMP“数据包太大”做出响应,服务器会进行调整。但如果远程网络的防火墙配置错误,会阻止“不寻常的”ICMP 数据包,则不会发生这种情况,服务器只会继续尝试永远重新传输相同的大数据包。

有客户端解决方法——你可以使用 iptables 动态编辑 TCP 握手:

-t mangle -A POSTROUTING -o tun0 -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --set-mss 1400

相关内容