無線LAN搭載PCでKVMを実行し、仮想OSをブリッジ接続するには

無線LAN搭載PCでKVMを実行し、仮想OSをブリッジ接続するには
2014年2月11日 無線LAN搭載PCでKVMを実行し、仮想OSをブリッジ接続するには へのコメントはまだありませんちょっとマニアックな情報なので、興味のない方は読み飛ばしてください。
最近はノートPCもマルチコアが当たり前で、メモリもふんだんにあるので、ノートPC内に仮想化環境を構築することも容易にできます。マニアックな使い方ではありますが・・、必要な人には必要なわけで・・
そこで、ノートPC内にKVMで仮想環境を構築し、ゲストOSをブリッジ接続して、LAN内のPCと直接通信するような環境を作りたいというのが今回の目標です。
ゲストOSをブリッジ接続するぐらい、VirtualPCやVMWareでも簡単にできるんだからKVMでも簡単にできるだろうと思っていたのですが、落とし穴がありました。LANに接続するインターフェイスが有線NICである場合問題なくブリッジを構成できるのですが、無線LANでLANにつながっている場合は、ブリッジ接続を作ること自体難しいようです。これはKVMに限った話ではなく、VirtualPCやVMWareでも同様です。
何がダメかって言いますと、無線LANは背後にある有線LANネットワークにあるMACアドレスなんかは感知しない模様。なんだか難しい話ですね。私もよくわからなかったので、ネットワークの基礎についてあれこれ調査しました。そこで、間違いもあると思いますが、理解した範囲で、あれこれと書いてみます。基本LAN内の通信はMACアドレスベースで行われるようですね。通信の起点は相手のPCのIPアドレスをベースにするみたいなのですが、arpという機能を使って 目的のIPアドレスのMACアドレスを解決したら、以降の通信はMACアドレスベースに通信すると・・。ちょっと図を交えてご説明します。 今回のネットワーク構成はざっと以下のようになります。
PCTest(IP 192.168.1.99)から、無線LANでつながっているPCKVM(IP 192.168.1.26)へ通信を行う場合
1.arpで 192.168.1.26のMACアドレスを知る。
2.知ったMACアドレスをもとに通信する。
ブリッジとは L2レイヤーでイーサネットフレーム(パケット)を転送するものらしく、無線LANはL2レイヤーレベルでの転送をサポートしていないというのが 無線LANでブリッジ接続ができないということの根本的な理由みたいです。
今回は、この問題を回避するために brctl/parprouted/bcrelayを用います。
無線LAN PCKVMで以下のようなコマンドを実行します。
[diff]
$ sudo /sbin/sysctl net.ipv4.ip_forward=1
$ sudo /sbin/brctl addbr br0
$ sudo /usr/sbin/tunctl -t tap0
$ sudo /sbin/brctl addif br0 tap0
$ sudo /sbin/ip addr add 192.168.1.2 dev br0
$ sudo /sbin/ip link set br0 up
$ sudo /usr/sbin/parprouted wlan0 br0
$ sudo /usr/sbin/bcrelay -d -i br0 -o wlan0
[/diff]
上記コマンドが、具体的に何をやっているかというと
・まず、PCKVM内で パケットフォワードを有効にする。
・ブリッジデバイス br0を作る。
・tunデバイス tap0 を作る。
・br0とtap0をブリッジする。
・br0 に IPアドレスを付与し、起動する。
・parproutedで wlan0に飛んできたarpをbr0にも転送する。
・bcrelayで、br0(仮想環境)から飛んできたブロードキャストをwlan0に転送する。
後は、KVMの仮想OS側のNIC設定で、下図のようにbr0を指定してやれば、PCTestから、KVMRails1やKVMRails2と通信できるようになります。
と、めでたく接続できたは良いのですが、いったい内部で何が起こっているか、理解できなかったので、ちょっと調べてみました。
PCTest側で arpコマンドを実行した結果は、図中のPCTestの右側にあるものになります。
ここで注目して欲しいのが
[bash]
192.168.1.26 00:24:a5:6b:80:2a PCKVM
192.168.1.30 00:24:a5:6b:80:2a PCRails1
192.168.1.33 00:24:a5:6b:80:2a PCRails2
[/bash]
PCKVM,PCRails1,PCRails2 の MACアドレスが全部同じものになっているのですね。
このMACアドレスが何者かというと、 PCKVMの無線LAN (wlan0)のMACアドレスなんです。
今度はPCKVM側でarpコマンドを実行した結果は図中のPCKVMの左斜め下にあるものとなります。
ここで注目して欲しいのが
[bash]
192.168.1.30 52:54:00:f1:16:be PCRails1
192.168.1.33 52:54:00:1d:bd:a5 PCRails2
[/bash]
PCRails1,PCRails2 は別々のMACアドレスが振られており、PCKVMの無線LANのMACアドレスとも異なるものとなっています。
PCTest(192.168.1.99)から
PCKVM (192.168.1.26)、KVMRails1 (192.168.1.30)の 80版ポートへwgetした際の動作をなんとなく想像しています。
■PCTest >>>> PCKVM
PCTestは 192.168.1.26のMACアドレスを知るために arpコマンドを発行する。
PCKVMは自分宛のarpコマンドなので、自分のNICつまり、wlan0のMACアドレスを返す。
PCTestはPCKVMから戻ってきたMACアドレスに向け、メッセージを送信する。
PCKVMは自分のIP向けにメッセージが届いたので、返答をする。
■PCTest >>>> PCRails1
PCTestは 192.168.1.30のMACアドレスを知るために arpコマンドを発行する。
PCKVMは自分宛のarpコマンドではないが、parproutedが機能して、arpコマンドを br0 に転送する。
arpコマンドはブロードキャストなので、仮想PC全てに転送され、192.168.1.30のIPでアドレスを持つPCRails1が私だよー!とMACアドレスを返答する。arpアドレスの返答は PCKVMのparproutedでキャッチされ、PCKVMのarpテーブルに192.168.1.30のMACアドレスを登録し、PCTestにはPCRails1からの返答に含まれるMACアドレスではなく、PCKVMのwlan0のMACアドレスを返す。
PCTestはPCKVMから戻ってきたMACアドレス(PCKVMのwlan0)に向け、メッセージを送信する。
PCKVMはメッセージを受信するが、自分のIP(192.168.1.26)宛のメッセージではないため、自身のarpテーブルをチェックし、仮想PCであるKVMRail1にメッセージを転送する。
KVMRails1は自分のIP向けにメッセージが届いたので、返答をする。
多分こんなかんじで、やりとりが行われているんだと思います。
Leave a comment