web-dev-qa-db-ja.com

2つのタップインターフェースのブリッジ

私はまったくの初心者です。これは、カーネルネットワーキングを使った初めての実験です。 2つのtapインターフェース間にブリッジを作成し、トラフィックを送信しようとしています。これは、特定の目的よりも実験的なものです。

$ brctl showstp br0
br0
bridge id      8000.46846e0c0ff9
designated root    8000.46846e0c0ff9
root port         0            path cost          0
max age          20.00         bridge max age        20.00
hello time        2.00         bridge hello time      2.00
forward delay        15.00         bridge forward delay      15.00
ageing time         300.00
hello timer           1.98         tcn timer          0.00
topology change timer     0.00         gc timer         115.04
flags          


tap1 (1)
port id        8001            state            forwarding
designated root    8000.46846e0c0ff9   path cost        100
designated bridge  8000.46846e0c0ff9   message age timer      0.00
designated port    8001            forward delay timer   10.34
designated cost       0            hold timer         0.98
flags          

tap2 (2)
port id        8002            state            forwarding
designated root    8000.46846e0c0ff9   path cost        100
designated bridge  8000.46846e0c0ff9   message age timer      0.00
designated port    8002            forward delay timer    0.00
designated cost       0            hold timer         0.98
flags          

ブリッジbr0を作成し、tap1tap2の両方を追加しました。 libpcapを使用してtap1にARPパケットを挿入するプログラムがあります。 Wiresharkは、tap1に入るパケットを正しく表示します。ただし、tap2にはパケットが表示されません。 ebtablesに次のルールを追加してみました。

Sudo ebtables -I INPUT --log --log-level debug

ログにパケットは表示されません。ご意見をいただければ幸いです。

編集:より多くの情報を追加します。偽のパケットを注入することは確かにアプリケーションです。ここでの私の意図は、完全にソフトウェアで、VMなしで、パケットがLinuxカーネルスタックを介して転送される方法をシミュレートすることです。新しいネットワーク名前空間を作成していません。おそらくそれが問題ですか?

私には2つのプロセスしかありません。 「読み取り」プロセスには、tap2に対して開かれたファイル記述子があり、常にそこから読み取ろうとします。書き込みプロセスには、tap1に対して開かれたファイル記述子があり、ユーザープロンプトがARPクエリを送信するのを待ちます。 ARPクエリにはランダムな送信元IPアドレスがあります。送信元MACアドレスはtap1のMACアドレスとして設定されます。 tcpdumpの出力は次のとおりです。

tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on tap1, link-type EN10MB (Ethernet), capture size 262144 bytes
^[[A07:19:57.752990 ARP, Request who-has google-public-dns-a.google.com tell 0.0.248.17, length 28
    0x0000:  ffff ffff ffff ba9c 0589 16ad 0806 0001
    0x0010:  0800 0604 0001 ba9c 0589 16ad 0000 f811
    0x0020:  0000 0000 0000 0808 0808

tap1tap2にIPアドレスがないように構成しました。それが問題でしょうか?

brctl addbr br0
ip tuntap add name tap1 mode tap
ip tuntap add name tap2 mode tap
brctl addif br0 tap1
brctl addif br0 tap2
ifconfig tap1 0.0.0.0 up
ifconfig tap2 0.0.0.0 up
ifconfig br0 10.0.1.1 netmask 255.255.255.0 broadcast 10.0.1.255
ip link set br0 up
ip link set tap1 up
ip link set tap2 up

その答えをもとに、tap2にいろいろなアプリケーションを添付してみました。これに気づきました。tap1またはtap2を使用しているアプリケーションがない場合、両方のインターフェースでLOWER_UPフラグが設定されていません。

4: br0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN mode DEFAULT group default 
    link/ether 46:84:6e:0c:0f:f9 brd ff:ff:ff:ff:ff:ff
25: tap1: <NO-CARRIER,BROADCAST,MULTICAST,PROMISC,UP> mtu 1500 qdisc pfifo_fast master br0 state DOWN mode DEFAULT group default qlen 500
    link/ether ba:9c:05:89:16:ad brd ff:ff:ff:ff:ff:ff
26: tap2: <NO-CARRIER,BROADCAST,MULTICAST,PROMISC,UP> mtu 1500 qdisc pfifo_fast master br0 state DOWN mode DEFAULT group default qlen 500

アプリケーションを起動すると、LOWER_UPフラグが設定されます。

4: br0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP mode DEFAULT group default 
    link/ether 46:84:6e:0c:0f:f9 brd ff:ff:ff:ff:ff:ff
25: tap1: <BROADCAST,MULTICAST,PROMISC,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast master br0 state UP mode DEFAULT group default qlen 500
    link/ether ba:9c:05:89:16:ad brd ff:ff:ff:ff:ff:ff
26: tap2: <BROADCAST,MULTICAST,PROMISC,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast master br0 state UP mode DEFAULT group default qlen 500
    link/ether 46:84:6e:0c:0f:f9 brd ff:ff:ff:ff:ff:ff

大変申し訳ございませんが、問題を理解するのに十分な情報があることを願っています。

1
SPMP

念のため、あなたが完全な初心者だと言ったので:tun(レイヤー3)またはtap(レイヤー2)インターフェースは、アプリケーションのネットワークインターフェースエンドポイントであり、アプリケーションはこのネットワークインターフェースからパケットを読み書きできます。 ip tuntap add ...または古いtunctlで作成したものはそのようなエンドポイントの永続的な名前であり、通常は引き続きアプリケーションを実行し、アプリケーションを実行しない限り何も実行しません。

アプリケーションは設計の問題としてネットワークインターフェイスと相互作用するため、私が説明したこの通常の相互作用を「注入」することを意味しない限り、サードパーティアプリケーションでパケットを「注入」する必要はありません。

また、ネットワークをいじりたい場合は、ネットワーク名前空間およびvethペアの使用をお勧めします。基本的に、ネットワーク上の実際のコンピューター間の通信を模倣できる多数の仮想コンピューターをコンピューター上にセットアップできます。

したがって、それを実行したいが、パケットを作成および受信する独自​​のアプリケーションで遊んだくない場合は、tun/tapインターフェイスは必要ありません。

とはいえ、パケットを「注入」するために何を使用するかを言わなかったため、セットアップをテストしました。エンドポイントtap0atap1aをタップするために2つのsocatsを使用して、それらをブリッジしました。 、および2つの異なる名前空間で別の2つのsocatsを使用して、正しいパケットを作成しました。ローカルパケットは常にループバックloを介して配信されるため、これらは別の名前空間にある必要があります。

そして予想通り、ブリッジタップデバイスは問題なく機能します。

だから私はあなたが注入しているパケットに問題があると思います:間違ったイーサネットアドレス、またはブロードキャストがありません。 ARPパケットを挿入するときは、tcpdump -xx ...出力を使用して質問を編集してください。

または、ネットワーク名前空間を作成し、代わりに2つのvethペアの2つのエンドポイントをブリッジしたいですか?それはずっと簡単です。

編集

ARPパケットは良さそうです。 tap2に接続されているアプリケーションがないようです。 ip linkを実行した場合、LOWER_UPtap2フラグは表示されないはずです。推測:ブリッジは、デバイスが部分的にしか稼働していないことを検出し、このポートにパケットを送信しません。

tapに置き換えてみてくださいhas接続されているアプリケーションのように

Sudo socat TUN:10.0.2.2/24,tun-name=tapx,tun-type=tap,iff-up - | hexdump -C

10.0.2.2/24アドレスは何もしませんが、アドレスを指定しないとsocatは機能しません)、および別の端末

Sudo ip link set tapx master br0

(これはbrctl addifを置き換えます)次に、パケットを数回挿入し、最初のウィンドウでhexdumpを取得するかどうかを確認します。また、LOWER_UPip link show dev tapxを確認してください。

ところで、ifconfigbrctlは古くなっています。代わりにipbridgeを使用してください。

ブリッジポートにはIPアドレスがないため、ブリッジのポートにIPアドレスを割り当てなくても問題ありません(割り当てられている場合)彼らが橋に奴隷になる前に、彼らは無視されます)。たとえば、 ここ

2
dirkt

私はこれでたくさん苦労し、解決策に到達したと思います。または、少なくとも、何が起こっているのかをよりよく理解する。

受信側のタップインターフェイス(「RX」)にパケットを配信する唯一の方法は、そのパケットを、次のプロセスによって作成されたソケット記述子に書き込むことであることに注意してください。タップを開きましたopen("/dev/net/tun",...)およびioctlを介して)。このファイル記述子を一度に持つことができるプロセスは1つだけです。タップデバイスが開いていて、別のプロセスが同じ名前の別のタップデバイスを再度開こうとすると、そのシステムコールは失敗します。

したがって、wiresharkのような他のプロセスがあり、rawソケットを開いてから、thatを_tap0_にバインドする場合、トラフィックを書き込むことしかできません。 outシステムの(カーネルの観点から)。つまり、wiresharkは_tap0_のTXカウンターをバンプする必要があり、RXパケットのみがブリッジインターフェイスに転送されます。

あなたはそれぞれのようなカウンターをチェックすることができます:

_#!/bin/bash
for if in tap{0,1}; do
    stats=/sys/class/net/$if/statistics/
    rx=$(cat $stats/rx_packets)
    tx=$(cat $stats/tx_packets)
    echo "$if: rx=$rx, tx=$tx"
done
_

これは次のようなものを出力します:

_tap0: rx=0, tx=6
tap1: rx=0, tx=5
_

したがって、あなたの特定のケースでは、問題はここにあると思います:

Libpcapを使用してARPパケットを_tap1_に挿入するプログラムがあります。 Wiresharkは、_tap1_に入るパケットを正しく表示します。ただし、_tap2_にはパケットが表示されません。

Tap1にARPパケットをどのように注入していますか?私はwiresharkがfd = open("/dev/net/tun", ...)ioctl(fd, TUNSETIFF, ...)を呼び出していないので、送信されるパケットはTXであり、したがってブリッジされないと思います。

_tap0_にパケットを書き込んで_tap0_に転送し、_br0_に表示するには、_tap1_を開くプログラムが必要です。

1
Matt Rundle