自己作成インターフェースtun ( TUN/TAP ベース)があり、受信したものを出力します。
システムのすべてのトラフィックがこのインターフェイスを通過する必要があります。
インターフェイスの役割は次のとおりです。
ご想像のとおり、私は反検閲ツールを構築しようとしています。
トンネリングに関する決定は、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
は、キャプチャされたパケットがないことを示しています。つまり、iif tun0 lookup main
ルールを介してtun0からwlp2s0にパケットが送信されていません。
どこでも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
回答から変更されたソースも here です。
したがって、構成では、最初に10.0.0.1
から発信されたネットワークに送信しようとするすべてのパケット(tun0
インターフェースを経由し、ローカルアドレスが10.0.0.1
であるため)。パケットをキャプチャすると、これまでのところすべてが正常です。
今、tun0
はさらにパケットを送信します。 送信元アドレスは10.0.0.1
であり、パケットを別のインターフェース(この場合はwlp2s0
)から送信します。 ルーティングなので、最初にルーティングを有効にします。
sysctl -w net.ipv4.ip_forward=1
その後、wlp2s0
のtcpdump
を確認すると、パケットが送信元アドレス10.0.0.1
で送信され、wlanインターフェースの送信元アドレスでは送信されないことに気づくでしょう(期待どおり)私は推測する)。したがって、送信元アドレスを変更する必要があり、それはsource NATと呼ばれます。 Linuxでは、 netfilter/iptables を使用すると簡単です。
iptables -t nat -A POSTROUTING -o wlp2s0 -s 10.0.0.1 -j MASQUERADE
また、FORWARD
チェーンにACCEPT
ポリシーがあることを確認してください。そうでない場合は、次のようにallow forwardingする必要があります。
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 kernel がルーティングを行い、パケットをtun0
インターフェースからwlp2s0
に移動します。 netfilter は、ソースIP 10.0.0.1
を、出力パケット用のwlp2s0
インターフェイスに割り当てられたアドレスに変更する必要があります。すべての接続を記憶し、応答パケットが戻ると(それらの場合)、wlp2s0
インターフェースに割り当てられたアドレスの宛先アドレスを10.0.0.1
に変更します(「conntrack」機能)。
まあ、そうすべきですが、そうではありません。 netfilter は、この複雑なルーティング構成と、同じパケットが最初にOUTPUT
チェーンを通過し、次にルーティングされてPREROUTING
chain。少なくともDebian 8ボックスでは動作しません。
netfilter をトラブルシューティングする最良の方法は、TRACE
機能です。
modprobe ipt_LOG
iptables -t raw -A OUTPUT -p icmp -j TRACE
iptables -t raw -A PREROUTING -p icmp -j TRACE
ICMPパケットのトレースのみを有効にします。他のフィルターを使用してデバッグできます。
それは、パケットが通過するテーブルとチェーンを示します。そして、パケットがFORWARD
チェーンを通過しないことがわかります(実際にSNAT
を実行するnat/POSTROUTING
チェーンによってキャッチされていません)。
これを機能させるためのいくつかのアプローチを以下に示します。
netfilter を混乱させない最善の方法は、tun0.c
アプリケーションでパケットのソースIPアドレスを変更することです。また、これは最も自然な方法です。外向きにchange 10.0.0.1 to 10.0.0.2に、帰りに10.0.0.2 to 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
は、そのサブネットに属するパケットのみを送受信します。また、インターフェイスベースの代わりにソースベースのルーティングを行うことができます。
パケットがtun0
インターフェースに到達する前にSNAT
を実行することが可能です。しかし、それはあまり正しくありません。この場合は、必ず reverse path filtering をオフにする必要があります。
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
ここでは、送信元アドレスを変更するだけですbeforeパケットは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に依存していません。
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
routing と netfilter の「ハック」は、Debian 8ボックスで動作しますが、それでも最初のアプローチを使用することをお勧めしますより自然で、ハックを使用しません。
透過プロキシとしてアプリケーションを構築することも検討できます。 tunデバイスからのパケットを分析するよりもはるかに簡単だと思います。