Routing

在VPN 隧道外的cgroup 中路由流量

  • March 30, 2020

我試圖讓一些流量通過 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 流量按預期工作。

到底發生了什麼?

當一個數據包被發出時,會做出一個路由決策:這個決策選擇輸出介面匹配的源 IP 地址來使用。

路由/輸出鏈設置標記時,它會觸發重新路由檢查,如本示意圖所示(這是為iptables設計的,但對**nftables完全可用)。重新路由檢查會更改路由…但不會更改源 IP 地址。所以必須做更多的工作。

  • 添加 NAT 規則以更改源 IP 地址。

這必須在重新路由檢查之後完成,所以它在nat/postrouting中完成。請注意,同一個表可以有不同的鏈類型(與iptables where table <=> type 相反)。

   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
  1. 或標記回复流以使用與傳出流相同的路由表。它不會真正提高安全性,但無論如何:
   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 的connmark ( ct mark) 中以僅允許正確的回复流而不是其他任何東西繞過嚴格的反向路徑轉發,可以在安全方面做得更好。在嚴格模式下,除非是來自傳出流量的回复,否則不會再通過*wlo1到達任何內容。*這是完整的相應 nftables 規則文件(與上面的選項 2. 一起使用,同時替換 nftables 規則):
 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://unix.stackexchange.com/questions/576911