绕过内核 Ping 自身 IP 地址

绕过内核 Ping 自身 IP 地址

我想知道是否有办法绕过内核并在我 ping 自己的 IP 地址时将 ping 数据包重定向到我的网络网关。

例如,我的私有 IP 地址是 172.31.42.99,网关 IP 是 172.31.32.1。我想要做的是,当我执行“ping 172.31.42.99”时,我将得到“ping 172.31.32.1”的结果。

我不是 IP 路由表或 iptables 的专家,我不确定是否可以通过编辑路由表或 iptables 来实现这一点?

我尝试使用编辑路由表sudo ip route add 172.31.42.99/32 via 172.31.32.1,也尝试编辑 nat 表中的 iptables PREROUTING 链。但都没有成功。

我非常感谢任何帮助或想法。

答案1

更新:在这里给出更忠实的答案

当我执行“ping 172.31.42.99”时,我将得到“ping 172.31.32.1”的结果。

并且不涉及任何特殊路由或需要 172.31.32.1 作为路由器:简单的 DNAT。

使用 netfilter OUTPUT 钩子

Linux 网络堆栈在不同的路由步骤之间插入了 netfilter 钩子,如下所示示意图。必须注意的是,传入数据包与传出的本地数据包的处理位置不同。前者的 netfilter 钩子位于 PREROUTING 钩子中,而后者的钩子位于 OUTPUT 钩子中:nat 规则应该放在那里,而不是 nat/PREROUTING 中,因为后者看不到此流量。因为我不知道还有什么,为了以防万一,我将其插入到任何其他规则之前:

iptables -t nat -I OUTPUT -p icmp -d 172.31.42.99 -j DNAT --to-destination 172.31.32.1

在 OUTPUT 钩子中执行的操作可以触发重新路由检查(如上图所示):更改给定数据包的原始路由。请注意,这不会改变 IP 数据包的其他特征:例如,源 IP 不会改变。对于 OP 的特定情况,这很好,源已经正确。对于许多其他情况,通常还必须进行其他尴尬的更改(例如 nat/POSTROUTING 中的 SNAT)。

# ping 172.31.42.99
PING 172.31.42.99 (172.31.42.99) 56(84) bytes of data.
64 bytes from 172.31.42.99: icmp_seq=1 ttl=64 time=0.090 ms
64 bytes from 172.31.42.99: icmp_seq=2 ttl=64 time=0.122 ms
64 bytes from 172.31.42.99: icmp_seq=3 ttl=64 time=0.105 ms
^C
--- 172.31.42.99 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 89ms
rtt min/avg/max/mdev = 0.090/0.105/0.122/0.017 ms

同时:

# conntrack -E -p icmp
    [NEW] icmp     1 30 src=172.31.42.99 dst=172.31.42.99 type=8 code=0 id=2029 [UNREPLIED] src=172.31.32.1 dst=172.31.42.99 type=0 code=0 id=2029
 [UPDATE] icmp     1 30 src=172.31.42.99 dst=172.31.42.99 type=8 code=0 id=2029 src=172.31.32.1 dst=172.31.42.99 type=0 code=0 id=2029

(一段时间之后)

[DESTROY] icmp     1 src=172.31.42.99 dst=172.31.42.99 type=8 code=0 id=2029 src=172.31.32.1 dst=172.31.42.99 type=0 code=0 id=2029

等效使用nftables代替iptables可能是:

# nft add table ip mynat
# nft add chain ip mynat dnaticmp '{ type nat hook output priority -100; policy accept; }'
# nft add rule ip mynat dnaticmp ip protocol icmp ip daddr 172.31.42.99 dnat to 172.31.32.1

先前的答案基于对路由表的技巧

...这可能不是 OP 的本意

我在这里给你足够的绳子让你自己上吊。

先决条件(由 OP 满足):172.31.32.1 必须是路由器(并且其预期行为仅在下面使用Linux路由器,因此如果行为发生变化,它可能也必须是 Linux 路由器)。

我将假设(未在 OP 中指定)IP 网络为 172.31.32.0/20,并且系统的网络接口称为eth0

你没能通过改变来改变结果的原因可见的路由是指在向接口添加地址时,一些路由也会自动添加... 当地的路由表。此表具有最低的优先级,因为它是从规则优先级 0:

# ip rule show
0:      from all lookup local
32766:  from all lookup main
32767:  from all lookup default

# 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 172.31.32.0 dev eth0 proto kernel scope link src 172.31.42.99 
local 172.31.42.99 dev eth0 proto kernel scope host src 172.31.42.99 
broadcast 172.31.47.255 dev eth0 proto kernel scope link src 172.31.42.99 

# ip route get from 172.31.42.99 172.31.42.99
local 172.31.42.99 from 172.31.42.99 dev lo uid 0 
    cache <local> 

这里的目标是覆盖本地案例的上一个条目。唯一的方法是将规则 0“移动”到更高的优先级值,以便能够在之前插入一些内容:

# ip rule add pref 100 from all lookup local
# ip rule delete pref 0

并添加一条规则,该规则将覆盖到较新的路由表的路由,但仅适用于本地起源的输出情况,这转化为特殊语法的iif lo真正含义传出而不是从界面lo

# ip rule add pref 50 iif lo lookup 500

以及所需的路由(通过将路由器的 IP 设置为网关来处理 ARP 解析):

# ip route add table 500 172.31.42.99/32 via 172.31.32.1

我们现在有两条有效路线(因此每个方向甚至都会通过)严格反向路径转发交换接口时:eth0)。

  • 特别航线新增:

      # ip route get from 172.31.42.99 172.31.42.99
      172.31.42.99 from 172.31.42.99 via 172.31.32.1 dev eth0 table 500 uid 0 
          cache 
    
  • 并且,只有从现在起才在另一个方向上有效:

      # ip route get from 172.31.42.99 iif eth0 172.31.42.99
      local 172.31.42.99 from 172.31.42.99 dev lo table local 
          cache <local> iif eth0 
    

结果:

# ping 172.31.42.99
PING 172.31.42.99 (172.31.42.99) 56(84) bytes of data.
From 172.31.32.1: icmp_seq=1 Redirect Host(New nexthop: 172.31.42.99)
64 bytes from 172.31.42.99: icmp_seq=1 ttl=63 time=0.147 ms
From 172.31.32.1: icmp_seq=2 Redirect Host(New nexthop: 172.31.42.99)
64 bytes from 172.31.42.99: icmp_seq=2 ttl=63 time=0.129 ms
From 172.31.32.1: icmp_seq=3 Redirect Host(New nexthop: 172.31.42.99)
[...]

这之所以有效,是因为 172.31.32.1 是路由器。单次 ping 的实际结果如下:

  • 系统将 ICMP 请求发送到配置的网关:路由器,
  • 路由器检测到系统配置错误,并且同一 LAN 中有一个更好的直接目的地(恰好是系统本身)来处理此请求,并发送 ICMP 重定向以告知其更正其行为。非路由节点只会丢弃数据包,
  • 路由器仍将 ICMP 回显请求路由到目的地 172.31.42.99:返回给发送者,
  • 系统收到 ICMP 回显(具有有效路由,甚至通过了严格反向路径转发规则),并以与之前相同的方式发回 ICMP 回复,
  • 路由器再次发送 ICMP 重定向,
  • 路由器仍然路由 ICMP 回复,
  • 系统(和命令 ping)收到 ICMP 回复。

相关内容