如何在 Linux 中使所有流量通過一個接口

如何在 Linux 中使所有流量通過一個接口

我有一個自寫介面tun0TUN/TAP基於)輸出它收到的內容。
我需要係統的所有流量都流經這個介面。
此介面的作用是:

  1. 找出可能被審查的資料包並透過隧道傳輸它們。
  2. 不受影響地通過所有其他交通。

正如你所猜測的,我正在嘗試建立一個反審查工具。
有關隧道的決定必須在 tun0 進程內做出,
因為只有在那裡我們才可以使用受信任的 DNS。

我需要你的幫助來告訴我如何讓所有流量都流過一個自寫的介面tun0。如果 tun0 需要更改,我要求您提供此類更改。

以下是我嘗試讓所有流量都通過 tun0 並失敗(ping 失敗)的方法。

編譯

  1. gcc tun0.c
  2. sudo ./a.out

配置

  1. sudo ip addr add 10.0.0.1/24 dev tun0
  2. 創建表約翰

    $ cat /etc/iproute2/rt_tables 
    #
    # reserved values
    #
    255     local
    254     main
    253     default
    0       unspec
    #
    # local
    #
    #1      inr.ruhep
    
    200 John
    

順序很重要:

  1. sudo ip rule add from all lookup John
  2. sudo ip route add default dev tun0 table John
  3. sudo ip rule add iif tun0 lookup main priority 500

    $ ip rule
    0:      from all lookup local 
    500:    from all iif tun0 lookup main 
    32765:  from all lookup John 
    32766:  from all lookup main 
    35000:  from all lookup default 
    

故障排除

  1. sudo tcpdump -i wlp2s0 -qtln icmp然後ping -I tun0 8.8.8.8顯示沒有捕獲任何資料包,這意味著沒有資料包透過規則從 tun0 傳輸到 wlp2s0 iif tun0 lookup main

  2. 當我替換tun0lo到處時,它對我有用。

也嘗試過

  1. 關閉反向路徑過濾,rp_filter=0/etc/sysctl.conf

解答疑難解答

iptables -I FORWARD -j LOG --log-prefix "filter/FORWARD " 
iptables -t nat -I OUTPUT -j LOG --log-prefix "nat/OUTPUT " 
iptables -t nat -I PREROUTING -j LOG --log-prefix "nat/PREROUTING " 
iptables -t nat -I POSTROUTING -j LOG --log-prefix "nat/POSTROUTNG "
tail -f /var/log/syslog

答案的修改來源也是這裡

答案1

因此,在您的配置中,您嘗試發送到網路的所有資料包最初源自10.0.0.1(因為它們正在通過tun0介面且其本地地址是10.0.0.1)。您捕獲了數據包,到目前為止一切都很好。
現在,tun0進一步發送資料包。來源位址10.0.0.1並且您希望資料包透過不同的介面離開(wlp2s0在您的情況下)。那是路由所以讓我們先啟用路由:

sysctl -w net.ipv4.ip_forward=1

之後,如果您查看,tcpdumpwlp2s0會發現封包帶有來源位址10.0.0.1,而不是 wlan 介面的來源位址(我猜是您所期望的)。所以我們需要改變來源位址,它被稱為源NAT。在Linux中,借助以下命令很容易網路過濾器/iptables

iptables -t nat -A POSTROUTING -o wlp2s0 -s 10.0.0.1 -j MASQUERADE

也請檢查您的FORWARD連鎖店是否有ACCEPT政策,否則您需要允許轉發類似的東西:

iptables -A FORWARD -i tun0 -o wlp2s0 -s 10.0.0.1 -j ACCEPT
iptables -A FORWARD -i wlp2s0 -o tun0 -d 10.0.0.1 -j ACCEPT

現在一切都應該正常了:linux內核進行路由,它將資料包從tun0介面移動到wlp2s0網路過濾器應將來源 IP 變更10.0.0.1wlp2s0輸出資料包的介面分配位址。它會記住所有連接,並且當回复資料包返回時(如果有的話),它會將wlp2s0介面分配的地址的目標地址更改為10.0.0.1(“conntrack”功能)。
嗯,應該如此,但事實並非如此。它似乎,網路過濾器OUTPUT人們對這種複雜的路由配置以及同一個資料包首先通過鏈然後被路由並到達鏈的事實感到困惑PREROUTING。至少在 Debian 8 盒子上它不起作用。
排除故障的最佳方法網路過濾器其特點是TRACE

modprobe ipt_LOG
iptables -t raw -A OUTPUT -p icmp -j TRACE
iptables -t raw -A PREROUTING -p icmp -j TRACE

我只啟用了ICMP資料包的跟踪,您可以使用其他過濾器來調試。
它將顯示資料包經過哪些表和鏈。我可以看到資料包沒有進一步經過FORWARD鏈(並且它沒有被nat/POSTROUTING實際捕獲的鏈捕獲SNAT)。
以下是實現這項工作的幾種方法。

方法#1

解開迷惘的最好辦法網路過濾器就是在應用程式中改變封包的來源IP位址tun0.c。這也是最自然的方式。我們需要將 10.0.0.1 更改為 10.0.0.2外出途中以及10.0.0.2 至 10.0.0.1回去的路上。
我已經tun0.c用來源位址更改程式碼進行了修改。這是新文件這是補丁文件為您tun0.c。 IP 標頭的變更也涉及校驗和校正,所以我從中獲取了一些程式碼OpenVPN項目。以下是我在乾淨重啟並啟動後執行的命令的完整清單 tun0_changeip.c

ifconfig tun0 inet 10.0.0.1/30 up
sysctl -w net.ipv4.ip_forward=1
ip route add default dev tun0 table John
ip rule add from all lookup John
ip rule add from 10.0.0.2 lookup main priority 500
iptables -t nat -A POSTROUTING -o wlp2s0 -s 10.0.0.2 -j MASQUERADE

請注意,您無需關閉反向路徑過濾在這種情況下,因為一切都是合法的 -tun0只接收和發送屬於其子網路的資料包。您也可以執行基於來源的路由而不是基於介面的路由。

方法#2

可以SNAT在資料包到達tun0介面之前執行此操作。但這不是很正確。您肯定需要關閉反向路徑過濾在這種情況下:

sysctl -w net.ipv4.conf.tun0.rp_filter=0
# It won't work without also changing the "all" value
sysctl -w net.ipv4.conf.all.rp_filter=0

現在,執行以下操作SNAT: iptables -t nat -A POSTROUTING -o tun0 -s 10.0.0.1 -j SNAT --to-source ip.address.of.your.wlan.interface

這裡我們只是改變來源位址數據包到達tun0設備。tun0.c程式碼「按原樣」重新發送這些資料包(具有更改的來源位址),並且它們成功地透過 wlan 介面路由。但是您可能在 wlan 介面上有一個動態 IP 並且想要使用MASQUERADE(以便不明確指定介面位址)。以下是您可以使用的方法MASQUERADE

iptables -t nat -A POSTROUTING -o tun0 -s 10.0.0.1 -j SNAT --to-source 10.0.55.1
iptables -t nat -A POSTROUTING -o wlp2s0 -s 10.0.55.1 -j MASQUERADE

請注意“ 10.0.55.1” IP 位址 - 它是不同的。你可以在這裡使用任何IP,沒關係。如果我們之前更改來源 IP,封包將到達介面nat/POSTROUTING上的鏈。wlp2s0現在它不依賴 WLAN 介面的靜態 IP。

方法#3

您也可以使用fwmark.這樣你就不需要SNAT,但你只會擷取傳出的資料包:
首先我們需要停用反向路徑過濾因為tun0它將轉送屬於另一個網路的封包:

sysctl -w net.ipv4.conf.tun0.rp_filter=0
# It won't work without also changing the "all" value
sysctl -w net.ipv4.conf.all.rp_filter=0

Now let's alter the routing rules a bit:
# Delete old rules
ip rule del iif tun0 lookup main
ip rule del from all lookup John

# Packets will start going from wlan interface so they will have source address of it
iptables -t mangle -A OUTPUT -o wlp2s0 -j MARK --set-mark 1
ip rule add fwmark 0x1 lookup John

這是另一個“黑客”路由網路過濾器這適用於我的 Debian 8 機器,但我仍然建議採用第一種方法,因為它更自然且不使用任何 hack。


您也可以考慮將您的應用程式建置為透明代理。我認為這比分析來自 tun 設備的資料包要容易得多。

相關內容