私は自作インターフェース tun0(タップ受信したものを出力するインターフェースです。
システムのすべてのトラフィックがこのインターフェースを通過する必要があります。
インターフェースの役割は次のとおりです。
- 検閲される可能性のあるパケットを特定し、それらをトンネル化します。
- その他のトラフィックはすべてそのまま通過します。
ご想像のとおり、私は検閲防止ツールを構築しようとしています。
トンネリングに関する決定は、tun0 プロセス内で行う必要があります。
信頼できる DNS を使用できるのは、そこでのみだからです。
すべてのトラフィックを自分で作成したインターフェース tun0 に流す方法を教えてください。tun0 に変更が必要な場合は、その変更を提供してください。
以下は、すべてのトラフィックを tun0 を通過させようとしたが失敗した (ping が失敗) 場合の例です。
コンパイル
gcc tun0.c
sudo ./a.out
設定
sudo ip addr add 10.0.0.1/24 dev tun0
テーブル John を作成
$ cat /etc/iproute2/rt_tables # # reserved values # 255 local 254 main 253 default 0 unspec # # local # #1 inr.ruhep 200 John
順序は重要です:
sudo ip rule add from all lookup John
sudo ip route add default dev tun0 table John
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
トラブルシューティング
sudo tcpdump -i wlp2s0 -qtln icmp
そして、ping -I tun0 8.8.8.8
パケットがキャプチャされていないことが表示される場合、ルールを介して tun0 から wlp2s0 にパケットが送信されていないことを意味しますiif tun0 lookup main
。tun0
どこでも置き換えたらlo
うまくいきました。
試してみた
- リバースパスフィルタリングをオフにすると
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/POSTROUTING
SNAT
アプローチ #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 デバイスからのパケットを分析するよりもずっと簡単だと思います。