它做什么curl --interface tun0
?根据 man:Perform an operation using a specified interface. You can enter interface name, IP address or host name.
它似乎使用 SO_BINDTODEVICE 来实现这一点。这是我感到困惑的地方:根据我的理解,当程序想要将数据包发送到特定目的地时,由路由表决定使用哪个接口作为源。此选项似乎以某种方式覆盖了它。那么如果路由表中没有路由会使用该接口并到达该目的地,会发生什么?
案例一(由sing-box设置的隧道):
ip a:
tun0: <POINTOPOINT,MULTICAST,NOARP,UP,LOWER_UP> mtu 9000 qdisc fq state UNKNOWN group default qlen 500
link/none
inet 172.18.0.1/30 brd 172.18.0.3 scope global tun0
valid_lft forever preferred_lft forever
inet6 fe80::717d:757a:23db:789b/64 scope link stable-privacy
valid_lft forever preferred_lft forever
ip route:
172.18.0.0/30 dev tun0 proto kernel scope link src 172.18.0.1
curl example.com --interface tun0
按照预期进行操作(但是怎么做到的?)并通过 tun0 请求 example.com。
情况二(wireguard接口):
ip a:
wg0: <POINTOPOINT,NOARP,UP,LOWER_UP> mtu 1420 qdisc noqueue state UNKNOWN group default qlen 1000
link/none
inet 10.230.116.1/24 scope global wg0
valid_lft forever preferred_lft forever
ip route:
10.230.116.0/24 dev wg0 proto kernel scope link src 10.230.116.1
结果是:connect to 142.44.215.161 port 80 failed: No route to host
它怎么知道那里实际上没有路线?
我理解这些隧道是由用户空间(或内核空间)程序操作的。这是否像 FuseFS 一样,当这些程序不喜欢目标 IP 时,它们可以简单地返回“不,不允许”(或“是的,无论如何我都可以这样做”,即使根据路由表,它们不应该发送到那里)?这是否意味着在使用 SO_BINDTODEVICE 时完全忽略路由表?如果我使用 eth0 而不是 tun0 会怎样?它是一个物理接口,它会使用路由表来确定是否可以路由此数据包吗?最后,可以这样做curl example.com --interface 172.18.0.1
。令人惊讶的是,这并不等同于--interface tun0
,并且不会成功。这是为什么?