將 cgroup 中的流量路由到 VPN 隧道之外

將 cgroup 中的流量路由到 VPN 隧道之外

我正在嘗試讓一些流量通過 VPN,而其他流量則不這樣做。

具有給定 fwmark 的封包應該發送至我的預設介面 ( wlo1),所有其他流量都會傳送至tun0主表中的隧道介面( ,使用 OpenVPN)。我在 nftables 中加入了這條規則:

table ip test {
    chain test {
        type route hook output priority mangle; policy accept;
        meta cgroup 1234 meta mark set 1
    }
}

在主路由表中,我有以下條目:

default via 10.11.0.1 dev tun0 
10.11.0.0/16 dev tun0 proto kernel scope link src 10.11.0.20 
[WANIP.0]/24 dev wlo1 proto kernel scope link src [WANIP] 
128.0.0.0/1 via 10.11.0.1 dev tun0 
[VPNIP] via [WANGATEWAY] dev wlo1

帶有 fwmark 的封包1會被引導到它們自己的路由表:ip rule add from all fwmark 1 lookup test。在test表中我新增了以下路線:

default via [WANGATEWAY] dev wlo1

當我ping 8.8.8.8從這個 cgroup 運行時,它被卡住了。它似乎能夠發送但無法接收任何資料包。

VPN 流量如預期運作。

究竟發生了什麼事?

答案1

當封包發出時,會做出路由決策:此決策選擇傳出接口要使用的符合來源 IP 位址。

當。路線/輸出鏈條設定一個標記,它會觸發一個重新路由檢查,正如在此看到的示意圖(這是為iptables記住但完全可以用於nftables)。重新路由檢查會變更路由...但不會變更來源 IP 位址。因此還需要做更多的工作。

  • 新增 NAT 規則以變更來源 IP 位址。

這是必須要做的重新路由檢查,所以它是在NAT/後路由。請注意,同一個表可以有不同的鏈類型(與iptables其中表 <=> 型)。

    nft add chain ip test testnat '{ type nat hook postrouting priority srcnat; policy accept; }'
    nft add rule ip test testnat meta mark 1 masquerade

現在正確的資料包確實離開了。

  • 並允許接受回復流,儘管未通過預設路由到達
  1. 你可以放鬆一下反向路徑轉送透過變更為鬆散模式rp_filter

        sysctl -w net.ipv4.conf.wlo1.rp_filter=2
    
  2. 或標記回復流以使用與傳出流相同的路由表。它不會真正提高安全性,但無論如何:

        nft add chain ip test testpre '{ type filter hook prerouting priority mangle; policy accept; }'
        nft add rule ip test testpre iif "wlo1" meta mark set 1
    

唉,如果沒有其他調整,這將無法工作,這是自新版本以來所需要的未記錄的功能2010年出現:

        sysctl -w net.ipv4.conf.wlo1.src_valid_mark=1

筆記:

  • 透過將標記儲存在 conntrack 中,可以在安全性方面做得更好康馬克( ct mark) 僅允許正確的回復流,不允許任何其他流繞過嚴格反向路徑轉送。在嚴格模式下,任何內容都不會通過wlo1除非它是來自傳出流量的回應。以下是完整對應的 nftables 規則檔案(在替換 nftables 規則時與上面的選項 2 一起使用):

      table ip test {
              chain test {
                      type route hook output priority mangle; policy accept;
                      meta cgroup 1234 meta mark set 1 ct mark set meta mark
              }
    
              chain testnat {
                      type nat hook postrouting priority srcnat; policy accept;
                      meta mark 1 masquerade
              }
    
              chain testpre {
                      type filter hook prerouting priority mangle; policy accept;
                      ct mark 1 meta mark set ct mark
              }
      }
    
  • 此外,根據我在烏德範圍入口:https://kernelnewbies.org/Linux_4.10#Networking

  • 如果您可以將 cgroups 用法轉換為一組有限的 uid,則可以僅使用路由堆疊(無需 netfilter 或 nftables)來正確完成此操作,ip rule add ... uidrange ...如上所述。請參閱我對此的回答:透過特定介面 (tum1) 路由用戶流量

相關內容