通過特定介面 (tum1) 為使用者路由流量
問題:如何通過 tun1 為特定使用者路由流量?
到目前為止我已經嘗試過:我遵循:
sudo iptables -t nat -A POSTROUTING -m owner --uid-owner user1 -j SNAT --to-source 192.168.1.1
結果:流量沒有到達 tun1,我可以在 wireshark 中看到,“host google.com”沒有結果。
2:
sudo iptables -t nat -A POSTROUTING -m owner --uid-owner test --out-interface tun1
結果:流量通過預設路由,即無需通過 tun1 (vpn) 即可到達 Internet。
更多資訊:
ip a 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000 link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 inet 127.0.0.1/8 scope host lo valid_lft forever preferred_lft forever inet6 ::1/128 scope host valid_lft forever preferred_lft forever 3: enx0c5b8f279a64: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UNKNOWN group default qlen 1000 link/ether 0c:5b:8f:27:9a:64 brd ff:ff:ff:ff:ff:ff inet 192.168.8.100/24 brd 192.168.8.255 scope global dynamic noprefixroute enx0c5b8f279a64 valid_lft 53043sec preferred_lft 53043sec inet6 fe80::5f5a:e5de:ae93:e80b/64 scope link noprefixroute valid_lft forever preferred_lft forever 9: tun1: <POINTOPOINT,MULTICAST,NOARP,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 500 link/none inet 10.0.0.1/24 scope global tun1 valid_lft forever preferred_lft forever inet6 fe80::c626:a226:a66c:2b0/64 scope link stable-privacy valid_lft forever preferred_lft forever
ip route list default via 192.168.8.1 dev enx0c5b8f279a64 proto dhcp metric 100 10.0.0.0/24 dev tun1 proto kernel scope link src 10.0.0.1 169.254.0.0/16 dev enx0c5b8f279a64 scope link metric 1000 192.168.8.0/24 dev enx0c5b8f279a64 proto kernel scope link src 192.168.8.100 metric 100 linkdown
我完全同意 dirk 的評論:使用網路命名空間可以讓路由更容易,沒有特殊情況。但這是一個我希望與平常不同的答案,它需要 Linux 核心 >= 4.10。
關於失敗的嘗試:
POSTROUTING
顧名思義,是在路由決策完成後完成的。這條鏈永遠不會改變路線。應該用於本地發起的流量的是mangle/OUTPUT
(以及在 nftables 上的特殊type route hook output
鏈)。然後它仍然需要通過使用標記與路由堆棧進行互動並糾正極端情況,可能還需要使用CONNMARK
而不是僅使用MARK
. 讓它正常工作仍然很困難。無論如何,這是一種不依賴但依賴於 2016 年核心 4.10
iptables
出現的網路路由堆棧功能的方法:uidrange
添加對每個 UID 路由的支持。它允許管理員配置規則,例如:
# ip rule add uidrange 100-200 lookup 123
. 自 5.0 以來,所有 Android 設備都在使用此功能。它主要用於強制實施每個應用程序的路由策略(在 Android 上,每個應用程序都有自己的 UID),而不必求助於重新路由 iptables 中的數據包,這會破壞 getsockname() 和 MTU/MSS 計算,並且通常會破壞端到端結束連接commit , commit , commit由於路由堆棧將立即選擇正確的路由並因此選擇匹配的源 IP,因此不需要
SNAT
此 IP。仍然需要一個較小的“不干淨”部分:它需要在tun設備上使用鬆散的反向路徑過濾器,因為雖然目標使用者獲得與其他使用者不同的路由表,但從該介面返回的流量不屬於任何使用者,所以不會使用這個路由表。在此範例中, user1的 UID 將為 1234,並且任意選擇的表 1001234 用於備用路由。
將相關的主要路由複制/更改到表 1001234 並放寬路由。每次重新建立隧道時都必須重新添加這些路由和設置,因為當介面消失和/或關閉時路由和設置會失去:
ip route add table 1001234 10.0.0.0/24 dev tun1 src 10.0.0.1 ip route add table 1001234 default dev tun1 #no need of a gateway on a layer 3 interface sysctl -w net.ipv4.conf.tun1.rp_filter=2
這只需要一次,然後將立即影響使用者:
ip rule add uidrange 1234-1234 lookup 1001234
不要添加任何
iptables
nat 規則。當然,仍然需要足夠的防火牆規則。請注意,如果使用者查詢本地服務(例如:在 127.0.0.1:53 上可用的本地 DNS 記憶體守護程序),守護程序進行的查詢將不會使用隧道,因為守護程序具有不同的 uid。