Networking

繞過核心 Ping 自身 IP 地址

  • April 11, 2020

我想知道當我 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 鏈。他們都沒有工作。

我非常感謝任何幫助或想法。

更新:在這裡給出一個更忠實的答案

當我執行“ping 172.31.42.99”時,我會得到“ping 172.31.32.1”的結果。

並且不涉及任何特殊路由或需要 172.31.32.1 作為路由器:簡單 DNAT。

使用 netfilter 輸出掛鉤

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

我們現在有兩個有效的路由(所以每個方向在交換介面時甚至會通過嚴格的反向路徑轉發: eth0lo)。

  • 特殊路線添加:
 # 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 回复。

引用自:https://serverfault.com/questions/1011822