Linux ですべてのトラフィックを 1 つのインターフェースを経由させる方法

Linux ですべてのトラフィックを 1 つのインターフェースを経由させる方法

私は自作インターフェース tun0タップ受信したものを出力するインターフェースです。
システムのすべてのトラフィックがこのインターフェースを通過する必要があります。
インターフェースの役割は次のとおりです。

  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. テーブル John を作成

    $ 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. tun0どこでも置き換えたらloうまくいきました。

試してみた

  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

tcpdumpその後、 forを見ると、wlp2s0パケットが送信元アドレスで送信され10.0.0.1、wlanインターフェースの送信元アドレスではないことがわかります(おそらく予想通りです)。そのため、送信元アドレスを変更する必要があります。ソースNATLinuxでは、ネットフィルター/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.1に変更する必要がありますwlp2s0。すべての接続を記憶し、応答パケットが返送されたときに (返送された場合)、インターフェイス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/POSTROUTINGSNAT

アプローチ #1

混乱を解消する最良の方法ネットフィルターアプリケーション内でパケットの送信元IPアドレスを変更することですtun0.c。これは最も自然な方法でもあります。10.0.0.1 を 10.0.0.2 に変更外に向かう途中で10.0.0.2 から 10.0.0.1帰り道。送信元アドレス変更コードで
修正しました。tun0.c新しいファイルはこちらそしてパッチファイルはこちらIPヘッダーの変更にtun0.cは、チェックサム修正、私はいくつかのコードを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

「 」IP アドレスに注意してください10.0.55.1。これは異なります。ここでは任意の 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 ボックスでは動作しますが、より自然でハックを使用しない最初のアプローチを採用することをお勧めします。


アプリケーションを次のように構築することも検討できます。透過プロキシtun デバイスからのパケットを分析するよりもずっと簡単だと思います。

関連情報