当使用 IP 别名时,操作系统如何确定哪个 IP 地址将用作出站 TCP/IP 连接的源?

当使用 IP 别名时,操作系统如何确定哪个 IP 地址将用作出站 TCP/IP 连接的源?

我有一台运行 Ubuntu Server 的服务器,它在单个 NIC 上有四个 IP 地址。

eth0       192.168.1.100
eth0:0     192.168.1.101
eth0:1     192.168.1.102
eth0:2     192.168.1.103

(使用 192.168.xx 作为示例,假设这些地址通过 NAT 转换为一系列公共 IP 地址)

我们的一个客户通过 FTP 发布他们的库存,因此我们每晚登录从他们的服务器下载一个大文件。他们的防火墙要求我们的(被动)FTP 连接从 192.168.1.100 建立。

假设我的服务器在单个适配器上逻辑上有四个 IP 地址,操作系统如何确定哪个 IP 地址用作出站 TCP/IP 连接的源?

假设我通过 ssh 进入 192.168.1.101 上的服务器并以交互方式运行 FTP。出站 TCP/IP 连接是否会使用 192.168.1.101,因为操作系统知道这是我的 shell 所连接的接口?

如果 FTP 任务通过没有 shell 的 cron 作业以非交互方式运行会怎样?

您可能已经看出来了,这让我很困惑,所以我希望我的问题至少是有意义的。

编辑

为了澄清我为什么问这个问题——我没有对路由表做任何更改,它实际上将“eth0”列为 0.0.0.0 路由的 IFace。然而,所有迹象都表明它实际上使用 eth0:0 作为源。

Destination    Gateway         Genmask         Flags Metric Ref    Use Iface
192.168.1.0    0.0.0.0         255.255.255.0   U     0      0        0 eth0
0.0.0.0        192.168.1.1     0.0.0.0         UG    100    0        0 eth0

我可以摆弄路由表或让客户端更改他们的防火墙规则来获得我需要的行为,但我试图深入了解这是如何工作的,以了解操作系统中是否存在错误,或者只是我对所有部分如何组合在一起的简单理解。

谢谢

答案1

默认情况下,在 Linux 上,如果一个接口有多个位于不同子网的地址,则发往各个子网的流量将具有正确的源 IP。也就是说,如果 eth0 有两个地址 192.168.1.1/24 和 10.1.1.1/8,则发往 10.0.0.0 子网上的任何流量的源 IP 都将为 10.1.1.1,发往 192.168.1.0 子网上的任何流量的源 IP 都将为 192.168.1.1。在这种情况下,您还可以通过使用“ip route”的“src 1.2.3.4”选项明确分配源地址。

不过,就您而言,所有地址都位于同一子网中,因此“主要”地址(如“ip addr list dev eth0”所示)用作该接口上流量的源 IP。我认为在这种情况下,只需使用“ip route”即可控制源 IP,但我发现使用 iptables 重写相关流量的源地址更简单。

如果您想要强制将特定的源地址用于特定的目的地,则可以使用 SNAT 规则来实现:

iptables -t nat -I POSTROUTING -o eth0 -d dest-IP-or-net/mask -s primary-IP-of-eth0 -j SNAT --to-source desired-source-IP

因此,如果您的“主”eth0 IP 是 192.168.100.1,但您希望到 1.2.3.4 的流量具有 192.168.100.2 的来源,则请执行以下操作:

iptables -t nat -I POSTROUTING -o eth0 -d 1.2.3.4/0 -s 192.168.100.1 -j SNAT --to-source 192.168.100.2

请注意,“-s 192.168.100.1”很重要:它可以防止转发流量的源地址被此规则重写。

如果你要在 Linux 上实现复杂的网络配置,你应该阅读 Linux 高级路由和流量控制文档,http://lartc.org

答案2

它使用路由表中的默认网关,除非有特定路由告诉它使用另一个网关:route -n

编辑:我似乎读你的问题太快了......

由于您使用的是被动模式,并且客户端将始终启动连接,因此我认为 IP 标头中的 src ip 字段将始终显示为客户端连接到的任何 IP。如果是主动模式,服务器正在启动连接,我认为它将始终是“主”IP。如果您的地址位于同一子网中,Linux 会将您添加的第一个地址设为“主”地址,其他地址设为次要地址。

不过,我并不完全确定,我会运行 tcpdump -n 并查看它将什么视为源 IP。

EDIT2:好的,我从您运行服务器的角度写了上述内容,因此,由于您是客户端并启动连接,我认为它总是会显示为来自主 IP 地址,但再次尝试并使用 tcpdump 查看。

答案3

我看到你的例子中所有的 IP 都太接近了,不可能不在同一个网络中

您确定您实际上是多宿主的,而不是仅仅拥有 4 个 IP 别名吗?

如果是后者,那么你可以使用类似下面的命令在路由上设置源 IP

/sbin/ip route show 192.168.222.0/24 dev eth0 proto 内核作用域链接 src 192.168.222.178 169.254.0.0/16 dev eth0 作用域链接默认通过 192.168.222.1 dev eth0

sudo /sbin/ip route 替换默认通过 192.168.222.1 src 192.168.222.178

/sbin/ip route show
192.168.222.0/24 dev eth0 proto 内核作用域链接 src 192.168.222.178 169.254.0.0/16 dev eth0 作用域链接默认通过 192.168.222.1 dev eth0 src 192.168.222.178

请参阅手册界面,了解如何使其在重启后保持不变

答案4

您可以通过 ip route get 命令查看将使用哪个设备和源 ip 地址,如下所示:

$ /sbin/ip route get 1.1.1.1
1.1.1.1 via 2.2.2.2 dev eth0  src 2.2.2.2 
    cache  mtu 1500 advmss 1460 hoplimit 64

我还没有在别名环境中尝试过这个,但希望这会有所帮助。

相关内容