Linux

伺服器不響應 ping - 收到 ICMP 並且沒有任何反應

  • May 26, 2020

我有一台伺服器,它有 2 個介面連接dhcp到兩個不同的子網。這 2 個不同的子網連接到同一個交換機到 2 個不同的介面。

# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
   link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
   inet 127.0.0.1/8 scope host lo
      valid_lft forever preferred_lft forever
   inet6 ::1/128 scope host 
      valid_lft forever preferred_lft forever
23: enp10s0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
   link/ether c4:00:ad:a4:e3:38 brd ff:ff:ff:ff:ff:ff
   inet 192.168.201.232/24 brd 192.168.201.255 scope global enp10s0
      valid_lft forever preferred_lft forever
25: enp11s0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
   link/ether c4:00:ad:a4:e3:39 brd ff:ff:ff:ff:ff:ff
   inet 192.168.203.3/24 brd 192.168.203.255 scope global enp11s0
      valid_lft forever preferred_lft forever
   inet6 fe80::c600:adff:fea4:e339/64 scope link 
      valid_lft forever preferred_lft forever

路線:

# ip r
default via 192.168.201.1 dev enp10s0 
192.168.201.0/24 dev enp10s0 proto kernel scope link src 192.168.201.232 
192.168.203.0/24 dev enp11s0 proto kernel scope link src 192.168.203.3 

從我的筆記型電腦上我正在 ping,首先到192.168.201.232. 在該設備上使用 tcpdump 我看到icmp請求和響應

# tcpdump -s 0 -i any -vvv -nn 'host 192.168.1.30 and not port 22'
tcpdump: listening on any, link-type LINUX_SLL (Linux cooked), capture size 262144 bytes
11:42:05.240967 IP (tos 0x0, ttl 62, id 53809, offset 0, flags [none], proto ICMP (1), length 84)
   192.168.1.30 > 192.168.201.232: ICMP echo request, id 55768, seq 1, length 64
11:42:05.240994 IP (tos 0x0, ttl 64, id 42288, offset 0, flags [none], proto ICMP (1), length 84)
   192.168.201.232 > 192.168.1.30: ICMP echo reply, id 55768, seq 1, length 64

當我 ping 到192.168.203.3我沒有得到響應,這是 tcpdump 輸出

# tcpdump -s 0 -i any -vvv -nn 'host 192.168.1.30 and not port 22'
tcpdump: listening on any, link-type LINUX_SLL (Linux cooked), capture size 262144 bytes
11:43:57.037535 IP (tos 0x0, ttl 62, id 19363, offset 0, flags [none], proto ICMP (1), length 84)
   192.168.1.30 > 192.168.203.3: ICMP echo request, id 55808, seq 1, length 64
11:43:58.060756 IP (tos 0x0, ttl 62, id 19364, offset 0, flags [none], proto ICMP (1), length 84)
   192.168.1.30 > 192.168.203.3: ICMP echo request, id 55808, seq 2, length 64

這個數據包會發生什麼?

為什麼沒有icmp回應?

我希望icmp響應轉到預設 gw ( 192.168.201.1) 因為我的 ip 是192.168.1.30

裡面什麼都沒有iptables,統計數據也不會隨著netstat -s.

當我刪除 dhcp 並且介面enp10s0沒有得到 ip 時,我有一個路由

# ip r
default via 192.168.203.1 dev enp11s0 
192.168.203.0/24 dev enp11s0 proto kernel scope link src 192.168.203.3 

從我的筆記型電腦ping到192.168.203.3,確實有效。

您有一個多宿主伺服器,它總是會引入額外的路由複雜性。

您的網路可以像這樣路由。它可能或多或少複雜,但可能是這樣的:

                 ┏━━━━━━┓
                 ┃laptop┃
                 ┗━━━━━━┛
              192.168.1.30/24
                     ┊
                   lan1
                     ┊
              192.168.1.1/24
                ┌─────────┐
                │ clients │
                │ router  │
                └─────────┘
                  x.x.x.x
                     ┊ 
                  y.y.y.y 
                ┌─────────┐
 192.168.201.1/24 servers 192.168.203.1/24
  ╭┄┄┄┄┄┄┄┄┄┄┄┄┄│ router  │┄┄┄┄┄┄┄┄┄┄┄┄┄╮
  ┆             └─────────┘             ┆
  ┆                                     ┆
lan201                               lan203
  ┆                                     ┆
  ┆             ┏━━━━━━━━━┓             ┆
  ╰┄┄┄┄┄┄┄┄┄┄┄┄┄┃         ┃┄┄┄┄┄┄┄┄┄┄┄┄┄╯
192.168.201.232/24  server 192.168.203.3/24
                ┃         ┃
                ┗━━━━━━━━━┛

為什麼忽略數據包?

您的問題很可能是由於伺服器啟用了稱為Strict Reverse Path Forwarding的反欺騙保護功能部分。簡而言之,只有當同一介面用於路由返回其回复時,才允許在介面上傳入數據包。

當兩個介面都已配置並且預設路由使用 192.168.201.1 並且您從筆記型電腦 ping 192.168.201.232 時,數據包以“左路徑”到達伺服器並從伺服器返回時也使用“左路徑”。伺服器可以詢問核心它的路由決策是什麼:

到達筆記型電腦的路線:

# ip route get from 192.168.201.232 192.168.1.30
192.168.1.30 from 192.168.201.232 via 192.168.201.1 dev enp10s0 uid 0 
   cache 

使用enp10s0

我們告訴傳入的數據包從同一個介面(enp10s0)到達,因為我們知道這就是之前的路由器會做的事情:

# ip route get from 192.168.1.30 iif enp10s0 192.168.201.232
local 192.168.201.232 from 192.168.1.30 dev lo table local 
   cache <local> iif enp10s0 

因為它與傳出數據包在同一側,所以這個傳入數據包被接受(並路由到本地系統)。

如果現在您 ping 192.168.203.3,數據包將被路由並到達“正確路徑”,並且伺服器的路由配置會告訴以“左路徑”離開伺服器。這是一條非對稱路由,之前的 SRPF 檢查失敗:不同的介面。

您可以再次向核心詢問它對這種情況的決定。雖然回复(如果存在)將按如下方式路由:

# ip route get from 192.168.203.3 192.168.1.30
192.168.1.30 from 192.168.203.3 via 192.168.201.1 dev enp10s0 uid 0 
   cache 

使用預設路由,因此使用 enp10s0

傳入數據包:

# ip route get from 192.168.1.30 iif enp11s0 192.168.203.3
RTNETLINK answers: Invalid cross-device link

被 SRPF 拒絕,因為傳入介面enp11s0與用於與該 IP 地址通信的傳出介面enp10s0不匹配。

如果您通過禁用“左路徑”並從“右路徑”上的 DHCP 繼承預設路由來更改預設路由,則一切都會轉移到enp11s0並再次執行。

如何讓它發揮作用?

  • 什麼可能無濟於事

您可以告訴系統禁用檢查或將其放寬Loose Reverse Path Forwarding。當涉及到預設路由(存在)時,兩種效果都是相似的(即:根本沒有留下太多效果),但是在 Linux 中放鬆它(設置 2)比在其他地方啟用它時禁用它(設置 0)更容易,因為配置中的最大值獲勝。它可能在(YMMV)的系統啟動時啟用,/etc/sysctl.d並且可以在那裡進行編輯。所以:

sysctl -w net.ipv4.conf.enp11s0.rp_filter=2

之前的查詢將不再失敗:

# ip route get from 192.168.1.30 iif enp11s0 192.168.203.3
local 192.168.203.3 from 192.168.1.30 dev lo table local 
   cache <local> iif enp11s0 

現在,伺服器上的兩個 tcpdump,每個介面上一個,應該在 enp11s0 上看到傳入的數據包,在enp10s0上**看到傳出的回复。

如果筆記型電腦收到答复,您就完成了,可以在這裡停下來。

它可能不會。因為沿著路徑,下一個網元,伺服器的路由器很可能實現了嚴格的反向路徑轉發。或者它可以兼作防火牆,並可能認為來自介面的數據包 192.168.203.3 可疑,而該介面只允許 192.168.201.0/24 中的數據包(反欺騙保護,這正是 SRPF 的目標)。所以數據包很可能會在一步之後被丟棄。

  • 什麼會起作用

無論何時涉及多宿主,都必須使用基於策略的路由。它不僅允許以目標地址作為決策選擇器來選擇路由,而且還允許以各種其他標準來選擇路由,最常見的是源地址。這裡還需要源地址。在 Linux 中,這是通過使用額外的路由表(通常使用目標作為選擇器)和使用規則(這裡將使用源作為選擇器)選擇適當的路由表來完成的。由於設置取決於源地址,因此很難將其集成到 DHCP 等動態環境中。雖然這當然是可能的:像dhclientNetworkManager這樣的守護程序每個都有自己的一組掛鉤來插入腳本,您可以通過使用靜態 IP 地址配置並聲明在 DHCP 伺服器上保留的這些地址來節省時間。

主表中的路由應部分複製到附加表中。如果伺服器也是路由器(例如:執行 LXC、Docker、VM…),則應考慮更多路由,並可能將其複製到其他路由表中。當然,如果這些路由是動態的(在容器執行時出現),配置它會變得更加複雜。像往常一樣,ip route get在這裡有很大幫助。

所以。為每一方創建一個路由表(我將為這些表使用不那麼任意的值 201 和 203)並僅複製需要的和與這一方相關的內容。在每一個上添加一個預設路由。好的,只能使用一個預設路由……但每個路由表。這裡只添加預設路由就足以解決路由問題(實際上只需要路由表203)。如果佈局發生變化(例如:路由容器……),以前認為不需要添加的路由應該再次考慮。此外,即使不總是使用,主路由表中仍然必須保留一條預設路由:這將是“預設”預設路由。當伺服器作為客戶端,連接時沒有定義源IP地址時,預設路由會影響自動選擇。

ip route add table 201 default via 192.168.201.1
ip route add table 203 default via 192.168.203.1

使用基於源的規則選擇它們:

ip rule add from 192.168.201.232 lookup 201
ip rule add from 192.168.203.3 lookup 203

結果:

# ip route get from 192.168.203.3 192.168.1.30
192.168.1.30 from 192.168.203.3 via 192.168.203.1 dev enp11s0 table 203 uid 0 
   cache 

出介面通過路由表203切換到enp11s0 。

# ip route get from 192.168.1.30 iif enp11s0 192.168.203.3
local 192.168.203.3 from 192.168.1.30 dev lo table local 
   cache <local> iif enp11s0 

因此,同一介面上的傳入數據包不再使 SRPF 失敗:同一介面。

下一個路由器也不會再感到困惑了。筆記型電腦的 ping 將適用於這兩個地址。

在伺服器上,能夠選擇源地址的客戶端應用程序將間接改變他們的流量選擇的路由(例如:curl --interface 192.168.203.3 192.168.1.30ping -I 192.168.203.3 192.168.1.30但因為它是一個特殊的工具,可能不是ping -I enp11s0 192.168.1.30等)並且它會正常工作。

引用自:https://unix.stackexchange.com/questions/589048