假设我有一个以下路由表:
ffgrt@srv28:~$ ip -4 a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet 14.2.13.24/32 scope global lo
valid_lft forever preferred_lft forever
2: ens3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
inet 210.41.21.8/27 brd 210.41.21.31 scope global ens3
valid_lft forever preferred_lft forever
ffgrt@srv28:~$
ffgrt@srv28:~$ ip r
default via 210.41.21.30 dev ens3 onlink
210.41.21.0/27 dev ens3 proto kernel scope link src 210.41.21.8
ffgrt@srv28:~$
14.2.13.24
当我从服务器建立连接时,什么时候将地址(在环回接口上配置)用作源地址?至少根据此源地址选择指南,14.2.13.24
仅当我手动绑定到该地址时才应选择该地址,因为:
- 当我连接到
210.41.21.0/27
网络时,内核将使用src
所选路由路径中的提示,这210.41.21.8
在我的情况下意味着 - 当我连接到除 之外的任何其他网络时
210.41.21.0/27
,内核将选择接口上配置的第一个地址,该地址与目标地址或下一跳路由器位于同一网络中。由于下一跳路由器可通过 via 到达ens3
并且ens3
仅210.41.21.8
配置完毕,因此210.41.21.8
将被使用。
仅当我手动绑定到接口时,接口上配置的 IPv4 地址lo
才用作传出连接的源地址吗?
答案1
为什么它有效
Linux,使用弱主机型号,使在任何接口上分配的任何 IP 地址对整个主机可用,因此使用任何其他接口都是可见的。
因此,如果其他路由条件允许到达该 IP 地址(例如:提供故障转移 IP 地址的数据中心在其路由器上定义了到明显不相关的 IP 地址的附加路由),则在环回接口上分配 IP 地址可以使该 IP 地址可达。可以添加到主机)。
以下是您的情况所发生的情况(假设主界面是以太网0网关是我的GW):
术语1:
# ip address add 14.2.13.24/32 dev lo
term2(在上一个命令之前运行):
$ ip -4 monitor
1: lo inet 14.2.13.24/32 scope global lo
valid_lft forever preferred_lft forever
local 14.2.13.24 dev lo table local proto kernel scope host src 14.2.13.24
^C
$ ip route get from 14.2.13.24 8.8.8.8
8.8.8.8 from 14.2.13.24 via mygw dev eth0 uid 1000
$ ip route get from 8.8.8.8 iif eth0 14.2.13.24
local 14.2.13.24 from 8.8.8.8 dev lo
cache <local> iif eth0
路由同样可以双向工作,前提是我的GW也能够路由此流量。
将此 IP 地址分配给罗只需向主机添加另一个 IP 地址即可。优点是当主界面关闭然后打开时它不会消失,也不必猜测可以将该地址分配给哪些接口,从而简化了一些脚本:罗总是可用并且通常是可用的。
如何在不绑定的情况下使用这个地址
正如OP已经写的那样,默认情况下不会使用此地址,因为所选路由将使用用于到达目的地的接口的主IP地址,并且罗永远不会是这个接口(除了 14.2.13.24 本身,它是暗示的源)。
仍然可以调整路由以选择该地址作为所有或某些目的地的源。
一个目的地的示例:
# ip route add 8.8.8.8 via mygw dev eth0 src 14.2.13.24
除非与其他 IP 地址绑定,否则发送到 8.8.8.8 的数据包默认使用 14.2.13.24。我可以替换或覆盖现有路由,并在任何重要的地方使用此地址作为默认源。
应用程序如何处理多个地址
如果没有路由选择该地址作为源,则作为客户端,必须显式绑定到该地址以从该地址发送流量,使用绑定(2)例如在使用之前连接(2)。
作为服务器(监听服务),它取决于:
TCP 服务将像往常一样运行,无需任何额外的努力:它们从收到连接的 IP 地址进行应答。
UDP 服务需要额外的关注。这并不限于拥有地址的情况罗但适用于任何多宿主系统,这些系统具有可从分配给它们的接口以外的其他接口访问到的一些或多个 IP 地址。
他们可以绑定到该地址,并且仅接收到该地址的数据包,并且回复将使用绑定地址作为源。如果没有显式绑定,将选择主接口的地址(例如:210.41.21.8 而不是 14.2.13.24),并且原始客户端将拒绝回复,因为该地址与查询不匹配。
如果他们仍然选择绑定INADDR_ANY,那么接收数据包的地址无法提前知道(例如:是210.41.21.8还是14.2.13.24?),内核仍然会默认选择主接口的IP地址作为回复。然后应用程序必须以不同的方式工作:在 Linux 上,它应该设置IP_PKTINFOUDP 套接字上的选项(使用setsockopt(2))然后使用接收消息(2)接收辅助信息in_pktinfo告知收到的本地地址。然后,应用程序可以使用以下方法重用这些信息的一部分:发送消息(2)告诉内核要发送什么源地址(无需绑定套接字)。这很复杂,下面是一个例子:设置 UDP 套接字的源 IP。 (在 *BSD 上,IP_RECVDSTADDR以同样的方式使用)。
答案2
上没有传出连接lo
。这不能是源地址。没有连接其他设备。
我能想到的唯一用例是当您有网络/其他服务器14.2.13.24
并且当前设备上运行相同的服务器软件时。您希望测试配置而不在在线服务器上进行实验。将服务器的地址分配给lo
本地服务器并向其发送请求,而不是通过ens3
(并确保为此设置路由)。然后,对于您的测试,您可以在本地连接,而无需更改 DNS 条目(或/etc/hosts
)。
在本地完成测试后,您可以将设置转移到真实的14.2.13.24
,从中删除地址lo
,它(希望)能够工作。