Iptables

netfilter 無法正確替換 UDP 響應包的目標 IP

  • June 23, 2020

我們正在執行小型 kuberentes 集群(CentOS 7,Kuberenetes 1.13 + Flannel),經過一些調整 TCP 配置(見下文),我們注意到 DNS 無法正常工作。

我不認為我們的更改直接對我所觀察到的內容負責,kubernetes 也對此負責。我查了 IP 表,AFAIK 一切看起來都很好。我觀察到的是:

  1. Pod 10.23.118.10 發送 UDP(53) 包到 DNS ClusterIP 10.22.0.10
  2. 然後將包的目標 IP 從 ClusterIP (10.22.0.10) 更改為 DNS 伺服器 pod (10.23.118.2) (DNAT) 的 IP
  3. 伺服器獲取請求,對其進行處理,然後將響應發送回 10.23.118.10
  4. 此時 netfilter 應該在轉發包之前將源 IP 10.23.118.2 替換為 10.22.0.10,但由於某種原因它沒有這樣做
  5. Libc 收到包並拒絕它,因為它看到響應來自 10.23.118.2 而不是 10.22.0.10 或者我們得到 ICMP 包,說埠不可達。

在此處輸入圖像描述

奇怪的是,只有當 DNS 請求被發送到在同一台機器上執行的 pod 時才會發生這種情況。如果 DNS 請求來自其他機器上執行的 pod,則一切正常。

我想我們不是唯一看到這一點的人。你有過類似的情況嗎?我不確定這是 linux 的 netfilter 或 docker/kubernetes 中的錯誤是否會在配置橋接介面時破壞某些東西。我應該在哪裡尋找更多資訊?

這是我們嘗試應用的 TCP 配置:

net.core.somaxconn = 1000
net.core.netdev_max_backlog = 5000
net.core.rmem_max = 16777216
net.core.wmem_max = 16777216
net.ipv4.tcp_wmem = 4096 12582912 16777216
net.ipv4.tcp_rmem = 4096 12582912 16777216
net.ipv4.tcp_max_syn_backlog = 8096
net.ipv4.tcp_slow_start_after_idle = 0

問題似乎是 CentOS 7 預設配置。

重新載入配置sysctl -p --system時,它也會重新載入/usr/lib/sysctl.d/00-system.conf。在/usr/lib/sysctl.d/00-system.conf中,我們可以看到以下內容:

# Disable netfilter on bridges.
net.bridge.bridge-nf-call-ip6tables = 0
net.bridge.bridge-nf-call-iptables = 0
net.bridge.bridge-nf-call-arptables = 0

一旦完成(在網橋上禁用 netfilter),NAT-ing 將無法在docker0網橋上正常工作。

有趣的是,一旦您重新啟動 docker 並使用 查詢系統sysctl -a,您可以看到以下內容:

net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1

我只能假設這個設置是在啟動過程中由 docker 本身更改的。

這解釋了為什麼重新啟動 docker 通常會有所幫助。

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