我需要获取用作数据包源的 IP 地址default
通过路由发送。 (编辑)请注意,我指的是路线default
,即标记为default
(ip r
请参阅末尾以了解数据包在我的 VPN 设置下将采用的实际路线)。
我的第一个想法是使用ip r
并从中推断出:
# ip r
0.0.0.0/1 via 10.0.2.1 dev tun0
default via 10.237.76.1 dev enxb827eb4297a4 src 10.237.77.206 metric 202
10.0.2.0/24 dev tun0 proto kernel scope link src 10.0.2.100
10.81.102.133 via 10.237.76.1 dev enxb827eb4297a4
10.237.76.0/22 dev enxb827eb4297a4 proto kernel scope link src 10.237.77.206 metric 202
128.0.0.0/1 via 10.0.2.1 dev tun0
它看起来不错,ip r | grep default | cut -d" " -f7
给了我预期的效果10.237.77.206
。
然后,在另一个系统(都是 debian 衍生品)上我得到了
# ip r
0.0.0.0/1 via 10.0.2.1 dev tun0
default via 10.237.76.1 dev eth0 metric 202
10.0.2.0/24 dev tun0 proto kernel scope link src 10.0.2.5
10.81.102.133 via 10.237.76.1 dev eth0
10.237.76.0/22 dev eth0 proto kernel scope link src 10.237.76.56 metric 202
128.0.0.0/1 via 10.0.2.1 dev tun0
这里的解决方案并不那么简单:我需要提取默认路由 IP ( 10.237.76.1
),将其与适当的路由 ( 10.237.76.0/22 dev eth0 proto kernel scope link src 10.237.76.56 metric 202
) 相匹配,该路由有望包含src
.
最终削减 的输出ip
在 lng 术语中是站不住脚的(输出的变化、发行版或版本之间输出的变化,......)
有没有更便携的方式来获取该IP?
我所说的“便携式”是指:
- 理想情况下“适用于任何 Linux”
- 不太理想但仍然很好“适用于 Debian 及其衍生版本”
请注意,设备位于独占 VPN 中,因此我无法直接分析 VPN 启动时(即大多数时间)数据包将采取的实际路由:该default
路由被其他两条路由屏蔽,这有效地覆盖了整个IP范围。如果我在这里弄错了,请纠正我。
答案1
您可以选择一个您认为始终通过默认路由访问的任意地址,例如 google DNS,然后打印源地址那路线:
ip route get 8.8.8.8 | awk '{ for (nn=1;nn<=NF;nn++) if ($nn~"src") print $(nn+1) }'
答案2
显示您的默认路由源地址:
ip route get 8.8.8.8 | awk ' /^[0-9]/ { print $7 }'
- 选择
{ print $7 }
输出的第 7 个字段ip...
; - 选择
^[0-9]
以数字开头的行会ip
生成两行,以选择正确的行。
注意:我更喜欢第一个解决方案,但是为了显示替代方案而显示其他替代方案。
或者:
ip route get 8.8.8.8 | cut -f7 -d" " | grep '^[0-9]'
再次:
- 选择
cut
第 7 个字段;
或者:
ip route get 8.8.8.8 | grep ^[0-9] | cut -f7 -d" "
或者:
ip route get 8.8.8.8 | fgrep src | cut -f7 -d" "
或者也可以:
ip route get 8.8.8.8 | awk ' /src/ { print $7 }'
为了澄清一点,这里是输出ip
:
$ ip route get 8.8.8.8
8.8.8.8 via 192.168.1.1 dev eth0 src 192.168.1.249
cache
有多种方法可以在 Linux 中获取默认路由,可以通过ip
,procfs
也可以从netstat
。netstat
正在被弃用,并且在我看来,ip
它是任何最新 Linux 发行版中的更好选择。
答案3
基于实际意图(查找原始输出 IP)和所做的答案,这里有一个(相当长的)单行代码应该可以解决问题:
ip route get 8.8.8.8 oif $(ip route | sed -n '/^default/s/^.* dev \([^ ][^ ]*\) *.*$/\1/p') | sed -n 's/^.* src \([^ ][^ ]*\) *.*$/\1/p'
第一步$()
:获取默认路由,仅检索关键字后的接口开发者(因为根据可能取决于或不取决于分布的条件,路由在此步骤中将显示或不显示源IP)
第二步:获取到“众所周知”的公共IP地址的路由,该地址不应有特殊的路由设置篡改它,但要求使用之前检索到的接口,因此实际上要求内核使用埋在下面的实际原始默认0.0.0.0/1
路由128.0.0.0/1
进行计算。检索关键字后的IP源代码
答案4
在我的场景中(设置一个docker容器以正确获取主机的ip)我决定这样:
ip route|awk '/src/ { print $7 }'