为什么源 IP 不是我认为的那样?

为什么源 IP 不是我认为的那样?

我在服务器上设置 VPN 时注意到,所有发出的数据包的源 IP 始终是服务器的公共 IP。但根据我对路由表的理解,它应该是 VPN 的 IP。而且,如果我使用ping -I 10.8.0.1 10.8.0.42它,它又是我服务器的公共 IP。我在这里遗漏了什么?

tcpdump -n -i enp3s0 dst 213.225.3.191这是使用以下命令执行 ping 时的输出ping -I 10.8.0.1 213.225.3.191

17:34:36.285695 IP 5.9.142.112 > 213.225.3.191: ICMP echo request, id 10747, seq 34, length 64

tcpdump -n -i tun0这是使用以下命令执行 ping 时的输出ping -I 10.8.0.1 10.8.0.42

17:43:45.152792 IP 5.9.142.112 > 10.8.0.42: ICMP echo request, id 10834, seq 1, length 64

输出ip route

default via 5.9.142.97 dev enp3s0 proto static 
5.9.142.97 dev enp3s0 proto kernel scope link src 5.9.142.112 
10.8.0.0/30 via 10.8.0.2 dev tun0 
10.8.0.0/24 via 10.8.0.2 dev tun0 
10.8.0.2 dev tun0 proto kernel scope link src 10.8.0.1 

输出route

Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
default         static.97.142.9 0.0.0.0         UG    0      0        0 enp3s0
static.97.142.9 0.0.0.0         255.255.255.255 UH    0      0        0 enp3s0
10.8.0.0        10.8.0.2        255.255.255.252 UG    0      0        0 tun0
10.8.0.0        10.8.0.2        255.255.255.0   UG    0      0        0 tun0
10.8.0.2        0.0.0.0         255.255.255.255 UH    0      0        0 tun0

输出iptables -L -v -n -t nat

Chain PREROUTING (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         

Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         

Chain POSTROUTING (policy ACCEPT 584K packets, 39M bytes)
 pkts bytes target     prot opt in     out     source               destination         
    4   336 MASQUERADE  all  --  *      enp3s0  10.0.0.0/8           0.0.0.0/0           
    0     0 MASQUERADE  all  --  *      enp3s0  10.0.0.0/8           0.0.0.0/0           
  285 18732 SNAT       all  --  *      *       10.0.0.0/8           0.0.0.0/0            to:5.9.142.112
    0     0 MASQUERADE  all  --  *      enp3s0  10.0.0.0/8           0.0.0.0/0           
    0     0 MASQUERADE  all  --  *      tun0    0.0.0.0/0            0.0.0.0/0           
    0     0 MASQUERADE  all  --  *      tun0    10.0.0.0/8           0.0.0.0/0           
    0     0 MASQUERADE  all  --  *      tun0    0.0.0.0/0            0.0.0.0/0           
    0     0 SNAT       all  --  *      *       0.0.0.0/0            10.8.0.42            to:10.8.0.1

Chain OUTPUT (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         

答案1

为了完全理解 Linux 中的数据包流iptables,您需要此图或类似内容以供参考。在图中,ping位于应用程序层的“本地进程”框中。

使用您当前的路由表,系统将“认为”只有发往 10.8.0.0/24 的流量才会被路由到 VPN 隧道接口;其他所有流量都必须enp3s0通过 VPN 隧道传出。

当您运行 时ping -I 10.8.0.1 213.225.3.191,目标 IP 不在 10.8.0.0/24 块中,因此enp3s0将使用 。但出站路由经过网关 5.9.142.97,用于到达该网关的路由条目包括src 5.9.142.112,指定要使用的源地址。

如果这不会改变源 IP,则 iptables 后路由表中的第一个 MASQUERADE 规则将会改变。

4    336 MASQUERADE  all  --  *      enp3s0  10.0.0.0/8           0.0.0.0/0      

该规则匹配所有从接口传出的数据包enp3s0(由路由决策决定),其源 IP 在 10.0.0.0/8 范围内,而 10.8.0.1 匹配该范围。由于这是一条 MASQUERADE 规则,它会将传出数据包的源 IP 地址更改为数据包传出的网络接口的 IP 地址。第一个匹配获胜,因此该数据包通过后路由表处理完毕,然后通过 退出系统enp3s0

结果将与你看到的完全一致:

17:34:36.285695 IP 5.9.142.112 > 213.225.3.191: ICMP echo request, id 10747, seq 34, length 64

当您运行 时ping -I 10.8.0.1 10.8.0.42,这是 的有效目的地tun0,并且源地址对它也是有效的。路由决策完成。

在 iptables/netfilter NAT 后路由表中,前两个规则被限制为匹配通过 传出的流量enp3s0,因此它们不适用。但随后传出的数据包会命中此 SNAT 规则:

285 18732 SNAT       all  --  *      *       10.0.0.0/8           0.0.0.0/0            to:5.9.142.112

任何协议,检查。规则中未指定接口,因此它适用于tun0。检查。源地址在 10.0.0.0/8 内,检查。目标地址任何地址,检查。它匹配。这是一条 SNAT 规则,因此它修改了年代源 IP 地址。它会更改源 IP至 5.9.142.112。这可能不是你想要的,但规则就是这么说的。

第一个匹配获胜,因此数据包现在已完成后路由表处理:此数据包的后续条目将不再处理。由于 NAT 后路由表是传出路径上的最后一个表,因此数据包将按原样退出系统。

结果与此传出的数据包完全匹配tun0

17:43:45.152792 IP 5.9.142.112 > 10.8.0.42: ICMP echo request, id 10834, seq 1, length 64

如果您计划通过 VPN 传输所有互联网流量,则您的路由表应该包含:

  • 物理网络接口的路由5.9.142.97 dev enp3s0 proto kernel scope link src 5.9.142.112。您已经拥有该路由,因为它将在配置物理网络接口时自动生成。
  • 通过网关 5.9.142.97 向 VPN 隧道远程端点的公共 IP 地址(不是 10.8.0.2)输入 /32(或 genmask 255.255.255.255)enp3s0条目。这样即使您将默认网关路由指向 VPN 接口,VPN 封装的数据包也能通过您的实际网络接口发出并到达远程 VPN 端点。否则,传出的 VPN 流量将被反复重新封装,从而形成路由循环,阻止 VPN 流量真正到达远程 VPN 端点。
  • VPN 隧道本身的条目: 。配置接口10.8.0.2 dev tun0 proto kernel scope link src 10.8.0.1时,该条目也可能会自动生成。tun0
  • 通过 10.8.0.2 的默认网关条目,将任何没有定义更具体路由的流量(即基本上所有尚未经过 VPN 封装的、流向远程 VPN 端点的流量)指向 VPN 隧道。
  • 10.8.0.0/30 via 10.8.0.2仅此而已。默认网关条目将执行和条目的工作10.8.0.0/24 via 10.8.0.2

除非您的系统充当其他系统的 VPN 网关,否则您可能根本不需要 NAT POSTROUTING 表中的任何条目。

相关内容