私はまったくの初心者です。これは、カーネルネットワーキングを使った初めての実験です。 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
を作成し、tap1
とtap2
の両方を追加しました。 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
tap1
とtap2
に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
大変申し訳ございませんが、問題を理解するのに十分な情報があることを願っています。
念のため、あなたが完全な初心者だと言ったので:tun(レイヤー3)またはtap(レイヤー2)インターフェースは、アプリケーションのネットワークインターフェースエンドポイントであり、アプリケーションはこのネットワークインターフェースからパケットを読み書きできます。 ip tuntap add ...
または古いtunctl
で作成したものはそのようなエンドポイントの永続的な名前であり、通常は引き続きアプリケーションを実行し、アプリケーションを実行しない限り何も実行しません。
アプリケーションは設計の問題としてネットワークインターフェイスと相互作用するため、私が説明したこの通常の相互作用を「注入」することを意味しない限り、サードパーティアプリケーションでパケットを「注入」する必要はありません。
また、ネットワークをいじりたい場合は、ネットワーク名前空間およびvethペアの使用をお勧めします。基本的に、ネットワーク上の実際のコンピューター間の通信を模倣できる多数の仮想コンピューターをコンピューター上にセットアップできます。
したがって、それを実行したいが、パケットを作成および受信する独自のアプリケーションで遊んだくない場合は、tun/tapインターフェイスは必要ありません。
とはいえ、パケットを「注入」するために何を使用するかを言わなかったため、セットアップをテストしました。エンドポイントtap0a
とtap1a
をタップするために2つのsocat
sを使用して、それらをブリッジしました。 、および2つの異なる名前空間で別の2つのsocat
sを使用して、正しいパケットを作成しました。ローカルパケットは常にループバックlo
を介して配信されるため、これらは別の名前空間にある必要があります。
そして予想通り、ブリッジタップデバイスは問題なく機能します。
だから私はあなたが注入しているパケットに問題があると思います:間違ったイーサネットアドレス、またはブロードキャストがありません。 ARPパケットを挿入するときは、tcpdump -xx ...
出力を使用して質問を編集してください。
または、ネットワーク名前空間を作成し、代わりに2つのvethペアの2つのエンドポイントをブリッジしたいですか?それはずっと簡単です。
編集
ARPパケットは良さそうです。 tap2
に接続されているアプリケーションがないようです。 ip link
を実行した場合、LOWER_UP
のtap2
フラグは表示されないはずです。推測:ブリッジは、デバイスが部分的にしか稼働していないことを検出し、このポートにパケットを送信しません。
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_UP
でip link show dev tapx
を確認してください。
ところで、ifconfig
とbrctl
は古くなっています。代わりにip
とbridge
を使用してください。
ブリッジポートにはIPアドレスがないため、ブリッジのポートにIPアドレスを割り当てなくても問題ありません(割り当てられている場合)彼らが橋に奴隷になる前に、彼らは無視されます)。たとえば、 ここ 。
私はこれでたくさん苦労し、解決策に到達したと思います。または、少なくとも、何が起こっているのかをよりよく理解する。
受信側のタップインターフェイス(「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
_を開くプログラムが必要です。