- 我有两个网络接口 A
1.2.3.4
和 B1.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
我运行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
...
答案1
当您告诉应用程序使用特定的 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>
这表明内核将通过lo
接口发送流量。
要了解原因,让我们从命令开始ip rule
:
# ip rule
0: from all lookup local
32766: from all lookup main
32767: from all lookup default
这显示了内核将用来查找流量路由的所有路由表。它从顶部开始,到第一个匹配处停止。表示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
(你的可能看起来会有所不同)
然后,我们通过查看目的地是否与第二个字段匹配来查看是否有任何路由与目的地地址 (1.2.3.99) 匹配。在上面的输出中,最后一个匹配。在此行中,第一个字段是local
,其man ip-route
含义是:
本地 - 目的地被分配给该主机。数据包被环回并在本地传送。
这意味着流量将流过该lo
接口。
至于如何让它使用A
/B
接口,你有 2 个选择:
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
在这些规则中,前 2 条规则将local
路由移至表中main
。main
必须首先将路由添加到表中,因为主机必须local
在某个地方有一条路由,以便内核接受该地址的流量。将路由放在 2 个表中就可以了。之后,我们向local
表中添加一条没有local
指定的新路由,这将导致流量不通过该lo
接口。
答案2
在netcat-openbsd
debian 和 opensd 上,您可以选择要使用的路由表。
选项是-V
.
对于常规netcat
我相信这是不可能的。
使用 socat,您可以使用在调用时声明它的特定接口。
答案3
对本地地址的访问始终使用环回接口,因为网络接口设计用于将数据包发送到线路上的其他节点,而不是您自己。