![为什么使用curl 127.0.0.1 --interface eth0时eth0无法访问loopback接口](https://linux22.com/image/208120/%E4%B8%BA%E4%BB%80%E4%B9%88%E4%BD%BF%E7%94%A8curl%20127.0.0.1%20--interface%20eth0%E6%97%B6eth0%E6%97%A0%E6%B3%95%E8%AE%BF%E9%97%AEloopback%E6%8E%A5%E5%8F%A3.png)
以下是重现此问题的方法:
- 在端口 80 上启动监听服务:
nc -l 80 -k
- 使用curl 访问此服务:
curl 127.0.0.1 --interface eth0
eth0
在和lo
:上使用 tcpdump 捕获数据包tcpdump -i eth0 port 80 -nn -v
,tcpdump -i lo port 80 -nn -v
输出tcpdump
显示数据SYN
包已发送eth0
,但没有得到任何回复,tcp 客户端只是重传,SYN
直到达到重传限制。
但是,当我将目标 ip 更改为192.168.16.4
(也是绑定到 eth0 的本地 ip)时,访问成功,并且 tcpdump 输出显示数据包SYN
是从lo
.
这是ifconfig
输出:
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 192.168.16.4 netmask 255.255.240.0 broadcast 192.168.31.255
inet6 fe80::f820:20ff:fe16:588c prefixlen 64 scopeid 0x20<link>
ether fa:20:20:16:58:8c txqueuelen 1000 (Ethernet)
RX packets 16248748 bytes 2161348902 (2.0 GiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 15203841 bytes 4648786129 (4.3 GiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
lo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536
inet 127.0.0.1 netmask 255.0.0.0
inet6 ::1 prefixlen 128 scopeid 0x10<host>
loop txqueuelen 1000 (Local Loopback)
RX packets 4832071 bytes 2872871764 (2.6 GiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 4832071 bytes 2872871764 (2.6 GiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
以及路由表内容:
$ route -n
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
0.0.0.0 192.168.16.1 0.0.0.0 UG 100 0 0 eth0
169.254.169.254 192.168.16.2 255.255.255.255 UGH 100 0 0 eth0
192.168.16.0 0.0.0.0 255.255.240.0 U 100 0 0 eth0
$ 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 192.168.16.0 dev eth0 proto kernel scope link src 192.168.16.4
local 192.168.16.4 dev eth0 proto kernel scope host src 192.168.16.4
broadcast 192.168.31.255 dev eth0 proto kernel scope link src 192.168.16.4
我用来strace
记录系统调用日志时curl
,它显示该--interface eth0
选项的含义:setsockopt(3, SOL_SOCKET, SO_BINDTODEVICE, "eth0\0", 5)
我已经看到了讨论https://github.com/iputils/iputils/issues/198(ping -I
以同样的方式进行)和https://stackoverflow.com/questions/46036667/route- Between-network-interfaces-ubuntu
我在想:
- 为什么
curl 127.0.0.1 --interface eth0
无法访问服务,SYN
数据包发生了什么以及何时被丢弃? - 为什么
curl 192.168.16.4 --interface eth0
使用lo
接口来通信却curl 127.0.0.1 --interface eth0
使用eth0
- 如果我想做的话,我应该做的事情
curl 127.0.0.1 --interface eth0
是可行的。
更新:
我使用的 Linux 内核版本是4.18.0
.对于curl 192.168.16.4 --interface eth0
,tcpdump -i lo
输出为:
$ tcpdump -i lo port 80 -nn
dropped privs to tcpdump
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on lo, link-type EN10MB (Ethernet), capture size 262144 bytes
09:15:38.915880 IP 192.168.16.4.40850 > 192.168.16.4.80: Flags [S], seq 1020241664, win 43690, options [mss 65495,sackOK,TS val 2673572844 ecr 0,nop,wscale 7], length 0
09:15:38.915891 IP 192.168.16.4.80 > 192.168.16.4.40850: Flags [S.], seq 3808229193, ack 1020241665, win 43690, options [mss 65495,sackOK,TS val 2673572844 ecr 2673572844,nop,wscale 7], length 0
09:15:38.915900 IP 192.168.16.4.40850 > 192.168.16.4.80: Flags [.], ack 1, win 342, options [nop,nop,TS val 2673572844 ecr 2673572844], length 0
09:15:38.915928 IP 192.168.16.4.40850 > 192.168.16.4.80: Flags [P.], seq 1:77, ack 1, win 342, options [nop,nop,TS val 2673572844 ecr 2673572844], length 76: HTTP: GET / HTTP/1.1
09:15:38.915931 IP 192.168.16.4.80 > 192.168.16.4.40850: Flags [.], ack 77, win 342, options [nop,nop,TS val 2673572844 ecr 2673572844], length 0
答案1
它看起来非常像 XY 问题,但是:
您的系统上有两个接口:
eth0
,IP地址为192.168.16.4lo
,IP 地址为 127.0.0.1
当然,所有直接连接到该接口的 IP 地址都可以通过该接口访问。对于eth0
,可以是 192.168.16.0/20 中的任何内容,对于lo
,可以是 127.0.0.1 中的任何内容。
对于不在直接耦合范围内的任何数据,数据将首先发送到网关,然后网关将其进一步路由到目的地。到目前为止,一切都很好。
但是,127.0.0.0/8 是为环回网络保留的。路由器不会进一步路由。因此,即使您将其发送到网关,它也不会被进一步路由。
即使路由器将其路由得更远,也无法访问您的lo
接口。对于eth0
,路由器可以通过您插入的电缆进行访问。您的接口没有此类访问权限lo
;它只能在您的本地系统上访问。
所以,对于你的问题:
- 为什么
curl 127.0.0.1 --interface eth0
无法访问服务,SYN 数据包发生了什么以及何时被丢弃?
它被删除的位置有点取决于您的操作系统。但它不会比网关更远。
- 为什么
curl 192.168.16.4 --interface eth0
使用lo
接口来通信却curl 127.0.0.1 --interface eth0
使用eth0
这根本不会发生。curl 192.168.16.4 --interface eth0
不使用lo
。
- 如果我想做的话,我应该做的事情
curl 127.0.0.1 --interface eth0
是可行的。
内核补丁,如果你正在systemd
运行,也在那里打补丁。curl
应该可以。您还需要在路由器上安装自定义软件。您需要在系统上启用路由(当然应用了上述内核补丁以及 的修改版本zebra
)。我的建议是:想都别想。认真地重新评估为什么你想尝试这个。
作为补充,作为对
但是curl 192.168.16.4 --interface eth0确实使用了lo接口
您可能会在设备上看到的systemd
是(使用curl dullaart.website
):
07:41:06.008577 IP localhost.domain > localhost.45840: 6127 1/0/0 PTR localhost. (64)
07:41:12.433744 IP localhost.52411 > localhost.domain: 39930+ A? dullaart.website. (34)
07:41:12.433795 IP localhost.52411 > localhost.domain: 49165+ AAAA? dullaart.website. (34)
07:41:12.550329 IP localhost.domain > localhost.52411: 39930 1/0/0 A 212.1.212.17 (50)
07:41:12.582833 IP localhost.domain > localhost.52411: 49165 0/0/0 (34)
这是在 中指定的服务器上完成的名称解析/etc/resolve.conf
,即
nameserver 127.0.0.53
那是在环回网络上。
如果您转到自己的系统(就像您在问题的输出中所做的那样),某些系统(但不是全部)可能会用作lo
快捷方式。curl
这是可以做到的,因为内核知道两个接口背后是同一个系统。因此,当且仅当您的目标是您自己的系统时才curl
可以使用。lo