Networking

從路由器轉發時,數據包在網路介面和 iptables 之間丟棄

  • July 20, 2020

我有一個配置有多個介面和多個 VLAN 的伺服器。它適用於所有本地網路,但由於某種原因它會丟棄通過我的路由器轉發的數據包。它甚至不一致。有時我可以讓它工作幾天,然後它又開始丟包。我很想繼續探勘,但我能從Google得到的唯一結果是需要幫助設置 iptables 的人。

配置

$ cat /etc/issue
Ubuntu 18.04.4 LTS \n \l
$ cat /etc/netplan/50-cloud-init.yaml
network:
   version: 2
   ethernets:
       enp10s0:
           dhcp4: true
           dhcp6: true
       enp6s0:
           dhcp4: false
           dhcp6: false
   vlans:
       vlan18:
           id: 18
           link: enp6s0
           dhcp4: true
           optional: true
       vlan150:
           id: 150
           link: enp6s0
           dhcp4: true
           optional: true
       vlan155:
           id: 155
           link: enp6s0
           dhcp4: true
           optional: true

有問題的介面是enp10s0. 我enp6s0在 VLAN 中使用了一段時間,但將其移至單獨的 NIC 以隔離變數。那並沒有改變什麼。

$ netstat -s enp10s0
Ip:
   Forwarding: 2
   4207683 total packets received
   11 with invalid addresses
   0 forwarded
   0 incoming packets discarded
   4197424 incoming packets delivered
   2183348 requests sent out
   21 outgoing packets dropped
Tcp:
   1634 active connection openings
   1615 passive connection openings
   150 failed connection attempts
   1100 connection resets received
   43 connections established
   4207863 segments received
   2190261 segments sent out
   596 segments retransmitted
   0 bad segments received
   222 resets sent

測試

設置

我將以下第一行添加到我的 iptables INPUT 鏈中:

-p tcp -m tcp --dport 22 -j LOG --log-prefix "IPTABLES SEEN: "

我使用 tcpdump 觀察流量:

tcpdump -n -e -vv -i enp10s0 port 22

第 1 步:證明它在本地有效

從我的路由器10.8.10.1telnet 到有問題的伺服器10.8.10.11 port 22

iptables 日誌:

Jul 15 23:58:04 meji kernel: IPTABLES SEEN: IN=enp10s0 OUT= MAC=60:a4:4c:60:ce:ce:e0:63:da:21:c1:a5:08:00 SRC=10.8.10.1 DST=10.8.10.11 LEN=60 TOS=0x00 PREC=0x00 TTL=64 ID=44677 DF PROTO=TCP SPT=48770 DPT=22 WINDOW=14600 RES=0x00 SYN URGP=0

tcpdump 日誌:

23:58:04.335447 e0:63:da:21:c1:a5 > 60:a4:4c:60:ce:ce, ethertype IPv4 (0x0800), length 74: (tos 0x0, ttl 64, id 44677, offset 0, flags [DF], proto TCP (6), length 60)
   10.8.10.1.48770 > 10.8.10.11.22: Flags [S], cksum 0xbb2d (correct), seq 978415077, win 14600, options [mss 1460,sackOK,TS val 25150304 ecr 0,nop,wscale 7], length 0

SYN ACK 會按照您的預期進行,一切都很好。

第二步:對比路由器轉發的連接

我使用nc -vz遠端伺服器 ( 34.73.148.195) 連接到相同的 IP/埠。

tcpdump 日誌:

00:54:44.427670 e0:63:da:21:c1:a5 > 60:a4:4c:60:ce:ce, ethertype IPv4 (0x0800), length 74: (tos 0x0, ttl 56, id 18829, offset 0, flags [DF], proto TCP (6), length 60)
   34.73.148.195.50176 > 10.8.10.11.22: Flags [S], cksum 0x8c20 (correct), seq 1566819019, win 65320, options [mss 1420,sackOK,TS val 1249821436 ecr 0,nop,wscale 6], length 0

iptables 日誌:

沒有。沒有任何記錄。

沒有 SYN ACK 和重傳嘗試過了一會兒。網卡沒有報告錯誤,iptables 什麼也看不到,我只能摸不著頭腦。我什至可以從這裡往哪裡看?開始探勘核心?網路驅動?


額外要求的資訊

$ ip route show
default via 10.8.8.1 dev vlan18 proto dhcp src 10.8.8.11 metric 100 
default via 10.8.50.1 dev vlan150 proto dhcp src 10.8.50.5 metric 100 
10.8.8.0/24 dev vlan18 proto kernel scope link src 10.8.8.11 
10.8.8.1 dev vlan18 proto dhcp scope link src 10.8.8.11 metric 100 
10.8.10.0/24 dev enp10s0 proto kernel scope link src 10.8.10.11 
10.8.50.0/24 dev vlan150 proto kernel scope link src 10.8.50.5 
10.8.50.1 dev vlan150 proto dhcp scope link src 10.8.50.5 metric 100 
10.8.55.0/24 dev vlan155 proto kernel scope link src 10.8.55.5 

更多 iptables 的東西。但是當我清除所有規則並將所有策略更改為接受時,我仍然遇到同樣的問題。我相信我已經消除了 iptables 規則作為罪魁禍首。

# iptables -vL
Chain INPUT (policy DROP 442K packets, 81M bytes)
pkts bytes target     prot opt in     out     source               destination         
348M  494G ACCEPT     all  --  any    any     anywhere             anywhere             state RELATED,ESTABLISHED
1692K  301M ACCEPT     all  --  lo     any     anywhere             anywhere             /* Loopback Interface */
327K   24M ACCEPT     all  --  vlan18 any     anywhere             anywhere
174K   14M ACCEPT     all  --  vlan155 any     anywhere             anywhere
   0     0 ACCEPT     tcp  --  enp10s0 any     anywhere             anywhere             tcp dpt:ssh state NEW,ESTABLISHED /* Ssh Passthrough */

Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target     prot opt in     out     source               destination         

Chain OUTPUT (policy ACCEPT 190M packets, 17G bytes)
pkts bytes target     prot opt in     out     source               destination  
# iptables --list --table raw
Chain PREROUTING (policy ACCEPT)
target     prot opt source               destination         

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination         
# iptables --list --table mangle
Chain PREROUTING (policy ACCEPT)
target     prot opt source               destination         

Chain INPUT (policy ACCEPT)
target     prot opt source               destination         

Chain FORWARD (policy ACCEPT)
target     prot opt source               destination         

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination         

Chain POSTROUTING (policy ACCEPT)
target     prot opt source               destination         
# iptables --list --table nat
Chain PREROUTING (policy ACCEPT)
target     prot opt source               destination         

Chain INPUT (policy ACCEPT)
target     prot opt source               destination         

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination         

Chain POSTROUTING (policy ACCEPT)
target     prot opt source    

系統靜默丟棄數據包的原因有多種,但這種情況非常簡單:您認為結果是ip r g 34.73.148.195什麼?由於除了 10.8.10.0/24 之外,您沒有任何通過 enp10s0 的路由,因此您可以禁用 rp_filter …或添加一些/正確的預設路由:

ip r a default via 10.8.10.1 dev enp10s0 metric 50

畢竟是路由器,不是vlan18 或 vlan150 上的*本地網路,不是嗎?*為什麼要通過vlan18或vlan150到達外界?

由於 enp10s0 也是 DHCP 配置的,問題是您的路由器沒有在您的伺服器上設置預設路由。這解釋了缺乏一致性的原因——如果路線出現,你就獲得了連通性,如果它消失了,你就沒有。

作為記錄:在這樣的伺服器上使用 DHCP 是一個非常糟糕的主意。即使預設路由配置為靜態且度量較低,如上所述,一台流氓 DHCP 伺服器也可以輕鬆插入更多特定網路;考慮在 vlan18/150 上提供的 10.8.10.0/31(或實際上高達 /25 的任何內容) - 這樣的地址肯定會通過 enp10s0 將您排除在正確的(?)預設路由之外。如果路由器是您的,並且您想將其用作預設路由並仍將 DHCP 配置保留在其他(本地)介面上,請考慮使用 /31(或至少“經典”/30)連接地址。

無論如何,您的伺服器是否應該可以通過各自路由器上的其他轉發規則通過 vlan18 或 vlan150 從外部訪問?如果是這樣,您將不得不處理基於策略的路由,因為響應數據包必須通過傳遞入站數據包的介面發送。畢竟,您在這裡沒有公共 IP,因此它不適用於非對稱路由(通常不被禁止)。

實際上,由於您不能進行非對稱路由(沒有公共 IP)並且沒有基於策略的路由,因此您不應該禁用 rp_filter - 這只會隱藏真正的問題。無論如何它都不會工作 - 由您的路由器轉發的數據包(可能是 DNAT-ed)將被傳送到您的伺服器,但響應將傳送到 vlan18 或 vlan150,而不是具有適當的 conntrack 條目並擁有地址的路由器連接開始於。

至於這個問題 - 你可能會隱藏所有與 iptables 相關的東西。每次您看到“靜默”下降,即在 iptables 計數器中不可見時,甚至不必費心進一步調查 netfilter 層中的問題。這可能是 NIC 丟棄(緩衝區問題、CPU 不足) - 可以通過 tcpdump、TTL 過期(轉發時,對於具有非本地目標的數據包)或類似此處的一些內部過濾(反向路徑一)輕鬆驗證。

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