從路由器轉發時,數據包在網路介面和 iptables 之間丟棄
我有一個配置有多個介面和多個 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.1
telnet 到有問題的伺服器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 過期(轉發時,對於具有非本地目標的數據包)或類似此處的一些內部過濾(反向路徑一)輕鬆驗證。