|
在CentOS上做带源地址的源地址ping,最直接的源地址命令就是 ping -I。这个参数后面跟网卡名或IP都行。源地址比如机器有两块网卡,源地址eth0是源地址192.168.1.10,eth1是源地址10.0.0.5,你想从eth1出去探测8.8.8.8,源地址那就敲 ping -I eth1 8.8.8.8,源地址或者 ping -I 10.0.0.5 8.8.8.8。源地址前者让内核去查eth1绑定的源地址地址,后者直接把源IP写死。源地址两种写法都能跑,源地址但行为上有细微差别,源地址后面会讲到。源地址 为什么需要指定源地址?源地址多网卡服务器默认路由只走一条路。假设默认网关在eth0上,你ping任何外网地址,内核都从eth0发包。可如果eth1连着一个内网专线,你要测那条链路的连通性,不指定源地址的话,流量根本不会走eth1。看起来ping通了,实际上测的是eth0的路径。这种坑我踩过好几次,盯着抓包结果纳闷为什么源IP不对,后来才反应过来是路由表决定的。 说回 -I 参数的两种用法。指定网卡名的时候,ping会绑定到该网卡,源地址由内核根据网卡配置自动选取。指定IP的时候,ping直接bind那个地址,但内核仍然会根据目标地址查路由表来决定从哪块网卡发出去。如果指定的IP不在路由出口的网卡上,包可能发不出去,或者收到ICMP重定向。所以更稳妥的做法是写网卡名,除非你明确知道自己在干什么。 实际操作中还有一个常见需求:同时指定源地址和目标地址的接口。比如 ping -I 10.0.0.5 -c 4 8.8.8.8。这里 -c 4 只发四个包,省得一直刷屏。输出里第一行会显示 PING 8.8.8.8 (8.8.8.8) from 10.0.0.5,确认源地址生效了。如果没有这一行,说明 -I 没起作用,得检查是不是权限不够——普通用户跑 -I 绑非本机地址会被拒,root下没问题。 IPv6的情况稍微不同。CentOS 7之后默认启用IPv6,ping 命令实际是 ping6 的别名或者独立二进制。指定源地址用 ping -I eth1 -6 fe80::1 这种格式,网卡名后面可以跟 %eth1 来标识链路本地地址的作用域。比如 ping -I eth1 fe80::1%eth1。不写作用域的话,内核不知道从哪块网卡发,直接报 Address family not supported 或者 Invalid argument。 抓包验证一下最放心。开一个终端跑 tcpdump -i eth1 icmp,另一个终端跑 ping -I eth1 8.8.8.8。如果tcpdump能看到ICMP echo request从eth1出去,源IP是eth1的地址,那就对了。反过来,如果只看到eth0有包,说明路由表把流量劫走了,-I 没生效。这种情况通常是因为目标地址匹配了eth0所在子网的路由条目,内核优先选了更具体的路由。 还有个冷门参数 -S,在部分发行版的ping里用来指定源IP,但CentOS自带的iputils版本不支持。别跟 -I 搞混了。另外 ping -I 后面跟的如果是广播地址或者组播地址,行为又不一样,那个场景基本用不到,跳过。 最后提一句,CentOS 8和Stream用 nmcli 管理网络之后,网卡名可能变成 ens192 这种。命令本身没变,把eth1换成实际接口名就行。ip addr 看一眼就知道。别对着老教程里的eth0硬套,接口名对不上,ping直接报 unknown iface,连包都发不出去。 |