Linuxですべてのトラフィックが1つのインターフェイスを通過するようにする方法


11

受け取ったものを出力する自己記述のインターフェースtun0TUN / TAPベース)を持っています。
システムのすべてのトラフィックがこのインターフェイスを流れる必要があります。
インターフェイスの役割は次のとおりです。

  1. 検閲される可能性のあるパケットを把握し、それらをトンネルします。
  2. 他のすべてのトラフィックをそのまま通過させます。

ご想像のとおり、私は反検閲ツールを構築しようとしています。 信頼できるDNSを使用できるのはそこだけなので
、トンネリングに関する決定はtun0プロセス内で行う必要が
あります。

すべてのトラフィックが自己記述型インターフェース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捕捉されないパケットを示さない、それはパケットを介しwlp2s0にtun0から送信されない意味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

回答から変更されたソースもここにあります

回答:


10

そのため、構成では、最初に発信元としてネットワークに送信しようとするすべてのパケット10.0.0.1tun0インターフェースを経由していて、そのローカルアドレスがであるため10.0.0.1)です。パケットをキャプチャすると、すべてはこれまでのところ問題ありません。
次に、tun0パケットをさらに送信します。送信元アドレスはで10.0.0.1あり、パケットは別のインターフェース(wlp2s0あなたの場合)を通過するようにします。それがルーティングなので、最初にルーティングを有効にしましょう。

sysctl -w net.ipv4.ip_forward=1

その後、見てみると、パケットが、wlanインターフェースの送信元アドレスではなく送信元アドレスで送信されtcpdumpているwlp2s0ことが10.0.0.1わかります(私が推測しているとおりです)。したがって、送信元アドレスを変更する必要があり、これを送信元NATと呼びます。Linuxでは、netfilter / 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インターフェイスからに移動しますwlp2s0netfilterは、ソースIP 10.0.0.1を、wlp2s0出力パケット用のインターフェイス割り当てアドレスに変更する必要があります。すべての接続を記憶し、応答パケットが戻った場合(それらの場合)、アドレスをwlp2s0割り当てられたインターフェースの宛先アドレスを変更します10.0.0.1(「conntrack」機能)。
まあ、それはすべきですが、そうではありません。netfilterは、この複雑なルーティング構成と、同じパケットが最初にOUTPUTチェーンを通過し、次にルーティングされてチェーンに到達するという事実と混同されているようPREROUTINGです。少なくとも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チェーンにそれ以上行かないことを見ることができます(そしてnat/POSTROUTING実際に実行するチェーンによってキャッチされませんSNAT)。
以下は、これを機能させるためのいくつかのアプローチです。

アプローチ#1

netfilterを混乱させない最善の方法は、tun0.cアプリケーションのパケットのソースIPアドレスを変更することです。それは最も自然な方法でもあります。途中で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

次に、SNATiptables -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.1IPアドレスに注意してください-それは異なります。ここでは任意のIPを使用できますが、問題ではありません。以前にソースIPを変更すると、パケットnat/POSTROUTINGwlp2s0インターフェイス上のチェーンに到達します。そして今では、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ボックスで機能するルーティングネットフィルターのもう1つの「ハック」ですが、より自然でハックを使用しないため、最初のアプローチを取ることをお勧めします。


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


私は使用しなければなり-j SNATませんでした-s SNAT
-ilyaigpetrov

動作しますが、パフォーマンスは非常に断続的です(10秒間停止してから動作を継続する場合があります)。それがなぜ起こるのか、そしてこれをどのように修正するのかを理解します。
ilyaigpetrov 2017年

1
すみません、それは私のタイプミスでした。私は私の答えに別のアプローチを追加しました。パフォーマンスの問題について何も知りません。ちなみに、iptables DNATで透過プロキシを使用してトラフィックをフィルタリングして迂回しないのはなぜですか?
tifssoft 2017年

マークアプローチを再現できません。追加しただけですが、機能しませんでしたsudo ip rule add iif tun0 lookup main priority 500。私はこのアプローチが好きで、再現できないのが残念です。
ilyaigpetrov 2017年

1
あなたの新しいアプローチをありがとう、私はそれを一歩一歩追いかけ、それは完璧に機能しました。しかし、なぜipsを変更する必要があるのか​​理解できません。最も重要なのはそれが機能することです。TCPプロキシを使用した私の計画が失敗した場合、私はあなたの答えに戻ることができます。あなたはここで多くのネットワーキングスキルを示しました、そしてあなたのスキルが切望されることは間違いありません。幸運を!
ilyaigpetrov 2017
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.