我在服务器上有两个接口。输出ip route
如下:
default via 192.168.100.1 dev enp1s0 proto static metric 100
10.8.0.0/24 dev tap0 proto kernel scope link src 10.8.0.1
192.168.100.0/24 dev enp1s0 proto kernel scope link src 192.168.100.201 metric 100
接下来是ip address
(MAC 被隐藏):
...
1: enp1s0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
link/ether **:**:**:**:**:** brd ff:ff:ff:ff:ff:ff
inet 192.168.100.201/24 brd 192.168.100.255 scope global noprefixroute enp1s0
valid_lft forever preferred_lft forever
inet6 fe80::1409:66c6:eb0d:22a1/64 scope link noprefixroute
valid_lft forever preferred_lft forever
2: tap0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UNKNOWN group default qlen 100
link/ether **:**:**:**:**:** brd ff:ff:ff:ff:ff:ff
inet 10.8.0.1/24 brd 10.8.0.255 scope global tap0
valid_lft forever preferred_lft forever
inet6 fe80::85:5fff:fe98:6cb7/64 scope link
valid_lft forever preferred_lft forever
值为/proc/sys/net/ipv4/ip_forward
1;防火墙已禁用。
我想要的是访问192.168.100.1从10.8.0.100。通过访问 Web 服务器(正在监听此机器上的所有端口)curl --interface 10.8.0.100 http://10.8.0.1
工作正常。但curl --interface 10.8.0.100 http://192.168.100.201
输出是Network unreachable
。
Curl 发起 TCP 握手并将数据包推送到10.8.0.100接口。数据包随后到达10.8.0.1。服务器查看数据包目的地,发现它是192.168.100.201。然后它查看路由表并发现192.168.100.201是本地的。现在答案正在返回。发件人是10.8.0.100。查看路由表,我们发现可以通过 访问tap0
,这是本地的。因此现在它进入tap0
并到达 10.8.0.100。
但实际上 -不是。是不是我的思路错了?我以为描述表提供的信息足以确定如何转发数据包。其实这不完整吗?
答案1
首先,使用 -I 参数提供的 IP 地址和接口不是同义词ping
。第一个参数指示source IP
选择哪个。它将根据网络流量(包括本地地址和路由表)对其进行路由。第二个参数指示直接选择要将数据包发送到的接口(它将选择第一个分配的 IP 作为源)。
接下来,您要做的事情与数据包转发无关。转发意味着数据包必须从“外部”到达。由于您是从此主机生成数据包,因此不涉及转发。这是一个本地生成的数据包。由于您的目标 IP 是本地分配的地址之一,当您不强制 ping 将数据包发送到“外部”的特定接口(带-I interface
选项)时,内核将在内部处理此数据包流。它只是不会尝试将其输出到真实接口,因为它的目的地“已经在这里”。所以这就是发生的事情,也是为什么它在一种情况下有效而在另一种情况下无效的原因。
PS:如果您知道自己正在做什么并且两个接口都连接到同一个广播域(我怀疑TAP接口是否如此),还请检查-r
该工具的选项。ping
答案2
问题在于误解了--interface IP
和之间的区别--interface dev
。第一个使用路由表:
数据--interface 10.8.0.100
包将不会被转发到tap0
接口(此 IP 所属的接口)。相反,根据路由表,它将被转发到192.168.100.58
(lan 接口)。因此路由是10.8.0.100 -> 192.168.100.58 -> 192.168.100.201
。即使 SYN 已发送,服务器也不会以 SYN-ACK 做出响应 - 这就是 curl 失败的原因。
使用--interface tap0
ie 链路层地址它将按预期工作:10.8.0.100 -> 10.8.0.1 -> 192.168.100.201
。SYN-ACK 将使用相同路由传回。