iptables - 將數據包路由到特定介面的目標?
我的家庭伺服器有兩個主要介面,
eth1
(標準網際網路連接)和tun0
(OpenVPN 隧道)。我想iptables
強制所有由 UID 1002 擁有的本地程序生成的數據包通過退出tun0
,所有其他數據包通過退出eth1
。我可以輕鬆標記匹配的數據包:
iptables -A OUTPUT -m owner --uid-owner 1002 -j MARK --set-mark 11
現在,我想在 POSTROUTING 鏈(可能是 mangle 表)中放置一些規則來匹配標有 11 的數據包並將它們發送到
tun0
,然後是一個匹配所有數據包並將它們發送到的規則eth1
。我找到了 ROUTE 目標,但這似乎只是重寫了源介面(除非我讀錯了)。
iptables 能做到這一點嗎?我是否必須弄亂路由表(通過
ip route
或僅通過舊route
命令)?編輯:我想也許我應該提供更多資訊。我目前沒有其他的 iptables 規則(儘管我將來可能會創建一些規則來執行不相關的任務)。此外,的輸出
ip route
是:default via 192.168.1.254 dev eth1 metric 203 10.32.0.49 dev tun0 proto kernel scope link src 10.32.0.50 85.17.27.71 via 192.168.1.254 dev eth1 192.168.1.0/24 dev eth1 proto kernel scope link src 192.168.1.73 metric 203
我還沒有碰過路由表——這就是它目前的樣子(雖然它看起來很髒)。抱歉,我沒有
route
在這台機器上安裝舊命令。並且
ip addr
(當然,可以忽略 eth0 和 eth2 - 它們是目前未使用的 NIC)的輸出:1: lo: <LOOPBACK,UP,LOWER_UP> mtu 16436 qdisc noqueue state UNKNOWN link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 inet 127.0.0.1/8 scope host lo inet6 ::1/128 scope host valid_lft forever preferred_lft forever 2: eth0: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN qlen 1000 link/ether 1c:6f:65:2a:73:3f brd ff:ff:ff:ff:ff:ff 3: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000 link/ether 00:1b:21:9d:4e:bb brd ff:ff:ff:ff:ff:ff inet 192.168.1.73/24 brd 192.168.1.255 scope global eth1 inet6 fe80::21b:21ff:fe9d:4ebb/64 scope link valid_lft forever preferred_lft forever 4: eth2: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN qlen 1000 link/ether 00:1b:21:6a:c0:4b brd ff:ff:ff:ff:ff:ff 5: tun0: <POINTOPOINT,MULTICAST,NOARP,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UNKNOWN qlen 100 link/none inet 10.32.0.50 peer 10.32.0.49/32 scope global tun0
編輯:我得到了一些工作,但它沒有將標記的數據包轉發到 tun0。基本上,我添加了一個表 (11),並使用了:
ip route add table 11 via 10.32.0.49 dev tun0 ip rule add priority 10000 fwmark 11 table 11
當 I just 時
sudo -u user1000 wget -qO- whatismyip.org
,我會獲得我家的外部 IP 地址,但如果我這樣做sudo -u user1002 wget -qO- whatismyip.org
,我也會獲得我家的 IP 地址(但我應該在 OpenVPN 隧道的另一端獲得 IP)。執行
iptables -vL
確認數據包被標記規則匹配,但它們似乎沒有遵循路由規則。編輯:我在這方面花了很長時間,雖然它仍然不起作用,但我想我更接近了。
iptables 規則必須在
mangle
表的 OUTPUT 鏈中。我想我還需要nat
表的 POSTROUTING 鏈中的 MASQUERADE 規則來設置源地址。但是,在 OUTPUT 的 mangle 之後發生的重新路由無法正常工作。我現在已經在這上面花了 5 個小時,所以我要休息一下,可能會在今晚晚些時候或明天的某個時候回來。
我解決了這個問題。問題在於表 11 中的路由規則。表 11受到影響,但路由規則使其無法執行。這個腳本是我現在使用的,它似乎執行良好(儘管它顯然特定於我的設置)。另外,我創建了一個新表 21,專門用於主上行鏈路 (eth1)。
# Add relevant iptables entries. iptables -t mangle -A OUTPUT -m owner --uid-owner 1002 -j MARK --set-mark 11 iptables -t nat -A POSTROUTING -o tun0 -j MASQUERADE # Flush ALL THE THINGS. ip route flush table main ip route flush table 11 ip route flush table 21 ip rule flush # Restore the basic rules and add our own. ip rule add lookup default priority 32767 ip rule add lookup main priority 32766 ip rule add fwmark 11 priority 1000 table 11 # This next rule basically sends all other traffic down eth1. ip rule add priority 2000 table 21 # Restore the main table. I flushed it because OpenVPN does weird things to it. ip route add 127.0.0.0/8 via 127.0.0.1 dev lo ip route add 192.168.1.0/24 dev eth1 src 192.168.1.73 ip route add default via 192.168.1.254 # Set up table 21. This sends all traffic to eth1. ip route add 192.168.1.0/24 dev eth1 table 21 ip route add default via 192.168.1.254 dev eth1 table 21 # Set up table 11. I honestly don't know why 'default' won't work, or # why the second line here is needed. But it works this way. ip route add 10.32.0.49/32 dev tun0 table 11 ip route add 10.32.0.1 via 10.32.0.50 dev tun0 table 11 ip route add 0.0.0.0/1 via 10.32.0.50 dev tun0 table 11 ip route flush cache
## MeanderingCode 編輯(因為我還不能評論)
感謝您的回答!似乎這可能會變得混亂,因為您必須在此處維護路線資訊(可能會重複或破壞其他可能想要設置路線的東西。
您可能在 OpenVPN 的路由表中遇到“奇怪的事情”,因為伺服器配置為“推送”路由,使所有流量都可以通過 VPN 網路介面路由,而不是通過“裸機”網際網路。或者您的 OpenVPN 配置或任何設置它的腳本/應用程序正在設置路由。
在前一種情況下,您可以編輯您的 OpenVPN 配置並放入包含“route-nopull”的行
。在後一種情況下,檢查 OpenVPN 或任何包裝器的配置(network-manager-openvpn,例如在許多目前的 linux 桌面發行版上
)無論哪種情況,消除設置它的路由配置比刷新表更清潔和安全,具體取決於您何時執行此腳本以及您的系統正在做什麼。
乾杯!
我最近遇到了類似的問題,儘管略有不同。我只想通過 OpenVPN tap0介面路由 TCP 埠 25 (SMTP),同時通過預設介面路由所有其他流量(即使對於同一主機)。
為此,我必須標記數據包並設置處理規則。首先,添加一條規則,使核心路由數據包標記為
2
through table3
(稍後解釋):ip rule add fwmark 2 table 3
您本可以在 中添加一個符號名稱
/etc/iproute2/rt_tables
,但我並沒有這樣做。數字2
和3
是隨機選擇的。事實上,這些可以是相同的,但為了清楚起見,我在這個範例中沒有這樣做(儘管我在自己的設置中這樣做)。添加一個路由以通過不同的介面重定向流量,假設網關是
10.0.0.1
:ip route add default via 10.0.0.1 table 3
很重要!刷新您的路由記憶體,否則您將無法得到響應並雙手摀著頭髮坐了幾個小時:
ip route flush cache
現在,為標記指定數據包設置防火牆規則:
iptables -t mangle -A OUTPUT -p tcp --dport 465 -j MARK --set-mark 2
僅當數據包來自本地電腦時,上述規則才適用。請參閱http://inai.de/images/nf-packet-flow.png。根據您的要求進行調整。例如,如果您只想通過
tap0
介面路由傳出的 HTTP 流量,請將 465 更改為 80。為了防止通過將您的 LAN 地址作為源 IP 發送的數據包
tap0
,請使用以下規則將其更改為您的介面地址(假設10.0.0.2
為 interface 的 IP 地址tap0
):iptables -t nat -A POSTROUTING -o tap0 -j SNAT --to-source 10.0.0.2
最後,放寬反向路徑源驗證。有些人建議您將其設置為
0
,但2
根據https://www.kernel.org/doc/Documentation/networking/ip-sysctl.txt似乎是更好的選擇。如果您跳過此步驟,您將收到數據包(可以使用 確認tcpdump -i tap0 -n
),但不會接受數據包。更改設置以使數據包被接受的命令:sysctl -w net.ipv4.conf.tap0.rp_filter=2