为什么 netcat 不使用与 IP 关联的正确接口?

Ale*_*xis 5 networking netcat network-interface

  • 我有两个网络接口, A1.2.3.4和 B 1.2.3.99。(在ifconfig)
  • 我跑去nc -l 1.2.3.99 20101 -v监听接口 B。
  • 我跑nc -v 1.2.3.99 20101 -s 1.2.3.4 -4是因为我想使用界面A

它连接但当我检查时wireshark,没有来自A或的数据包B,仅在lo...

为什么它不使用具有关联 IP 的接口?我该怎么做才能强制他们使用关联的界面?

编辑:

在遵循帕特里克的建议之后:

ip route add local 1.2.3.99 dev B table main
ip route del local 1.2.3.99 dev B table local
ip route add 1.2.3.99 dev B table local
Run Code Online (Sandbox Code Playgroud)

我运行nc -l 1.2.3.99 20101但在创建 tcp 服务器时出现错误Ncat: bind to 1.2.3.99:20101: Cannot assign requested address. QUITTING.

17:10:38 alexis:~  $ ip route list table local
1.2.3.99 dev B  scope link 
...

17:10:40 alexis:~  $ ip route list table main
default via 10.133.0.1 dev eth0 
local 1.2.3.99 dev B  scope host
...
Run Code Online (Sandbox Code Playgroud)

phe*_*mer 15

当您告诉应用程序使用特定 IP 地址时,应用程序使用的是 IP 地址,而不是接口。某些应用程序确实允许您使用特定的接口,但这是一个单独的行为 ( SO_BINDTODEVICE )。

由于应用程序绑定到一个 IP 地址,而不是一个接口,内核可以自由地使用它想要的任何接口。为了确定使用哪个接口,它使用路由表(是的,有多个)。

如果您只想快速确定流量将采用的接口/路由,您可以使用ip route get 1.2.3.99 from 1.2.3.4,它将输出如下内容:

# ip route get 1.2.3.99 from 1.2.3.4
local 1.2.3.99 from 1.2.3.4 dev lo 
    cache <local>
Run Code Online (Sandbox Code Playgroud)

这表明内核将通过lo接口发送流量。

要了解原因,让我们从命令开始ip rule

# ip rule
0:  from all lookup local 
32766:  from all lookup main 
32767:  from all lookup default 
Run Code Online (Sandbox Code Playgroud)

这显示了内核将用于查找流量路由的所有路由表。它从顶部开始,并在第一场比赛结束。这from all意味着规则匹配任何源地址。所以它会先咨询表local。然后我们可以查看这个表:

# ip route show table local
broadcast 127.0.0.0 dev lo  proto kernel  scope link  src 127.0.0.1 
local 127.0.0.0/8 dev lo  proto kernel  scope host  src 127.0.0.1 
local 127.0.0.1 dev lo  proto kernel  scope host  src 127.0.0.1 
broadcast 127.255.255.255 dev lo  proto kernel  scope link  src 127.0.0.1 
broadcast 1.2.3.0 dev eth0  proto kernel  scope link  src 1.2.3.4 
local 1.2.3.4 dev eth0  proto kernel  scope host  src 1.2.3.4 
broadcast 1.2.3.255 dev eth0  proto kernel  scope link  src 1.2.3.4 
local 1.2.3.99 dev eth1  proto kernel  scope host  src 1.2.3.99
Run Code Online (Sandbox Code Playgroud)

(你的可能看起来不一样)

然后,我们通过查看目的地是否与第二个字段匹配来查看是否有任何路由与目标地址(1.2.3.99)匹配。在上面的输出中,最后一个匹配。在这一行中,第一个字段是local,根据man ip-route意思是:

本地 - 目的地被分配给这个主机。数据包被环回并在本地传送。

这意味着流量将流经lo接口。


至于如何让它使用A/B接口,你有两个选择:

1) 应用程序需要为您提供一个参数,您可以在其中指定接口。netcat 有十几种口味,但我系统上的版本没有这样的选项。socat确实如此(我个人推荐socat超过 netcat,因为 netcat 的不一致和可移植性噩梦。它也更强大)。

2)创建一个local匹配之前的非路由local

ip route add local 1.2.3.99 dev B table main
ip route del local 1.2.3.99 dev B table local
ip route add 1.2.3.99 dev B table local
Run Code Online (Sandbox Code Playgroud)

在这些规则中,前 2 条规则将local路由移动到main表中。必须首先将路由添加到main表中,因为主机必须在local某处有一个路由,以便内核接受该地址的流量。将路线放在 2 个表中是可以的。之后,我们再向表中添加一条local没有local指定的新路由,这将导致流量不通过lo接口。


psu*_*usi 1

对本地地址的访问始终使用环回接口,因为网络接口设计用于将数据包发送到线路上的其他节点,而不是您自己。