前回 は非常にザックリとした OpenFlow の基本的な話に終始しました。
OpenFlow を知るために、スタンフォードの人が書いた WihtePaper [1] を読んだり、スイッチの仕様 [2] を読んだりでもいいんですが。まずは動作環境を作って、使ってみるのが一番よく理解できますし、動かしてみると先の文献に書いてある内容もスイスイ頭に入ってきます。
なのでまず、OpenFlow についての文書を読んでみる前に OpenFlow について実際に動かして、使ってみることをお勧めします。
ではまず、VMware を用いて以下の仮想ネットワークを構築します。
最終的にやりたいことは、Switch 部分で Firewall を動作させることです。
各 VM に GNU/Linux を入れて、仮想敵に以下のネットワークトポロジーをつくります。
ここでは VM を5台書いていますが、今回使うのは Host1 と switch と controller の3台の VM を使います。
まずは OpenFlow switch (以下、スイッチ) 用の VM インスタンスです。VMWare Server には OpenFlow スイッチの機能を提供する仮想デバイスみたいなモノは無いので、OpenFlow スイッチをエミュレーションするソフトウェアスイッチ [3] を GNU/Linux に入れて、スイッチの代替にします。
ネットワーク 1,2,3,4 は、それぞれ別々の HostOnly ネットワークで、ネットワーク 5 は NAT ネットワークに設定してます。VMWare Server のデフォルトの設定では、一つの HostOnly ネットワークしかありませんが、vmware-config.pl で増やせます。
ネットワークが分離し、各ホスト間は物理的(?)に繋がっていないので、このまま何も設定しないと、各ホストはインターネットに出れません。スイッチにどのパケットフロー(もしくは、各パケット)を通したり、転送したり、破棄したりするのかを決定するのが OpenFlow controller (以下、コントローラ) です。
コントローラとスイッチの間は、セキュアな通信路でなければなりません(スイッチが乗っ取られるとこのネットワーク環境を好き放題いじれてしまうので)。なので、他のネットワークとは独立させています。
Host1 はただの GNU/Linux の VM です。
次に Firewall の定義と実装について見ていきます。
この辺りの話は OpenFlow と全然関係なく、「Firewall 定義ファイルを Python で解析するプログラムを作ったぜ」という話なので、OpenFlow についてのみ知りたい人は、軽くスルーしてください。
Firewall の定義ファイルは、以下に示すフォーマットで記述します。
[ Firewall 定義ファイルのフォーマット ]
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
${operation} ${src_condition} ${dst_condition} ${operation} is "pass" "drop" "change" ${src_condition} is ${condition} ${dst_condition} is ${condition} ${condition} is (${ip_addr},${mac_addr},${port}) ${ip_addr} is string of ip-address ${mac_addr} is string of mac-address ${port} is number of tcp/udp port |
なにやらぐちゃぐちゃしてますが。以下の記述例は以下のような感じになります。
[ Firewall 定義ファイルの記述例 ]
1 2 |
pass (192.168.0.1, *, *) (74.125.31.104, *, 80) pass (*, 00:16:d3:3e:2d:25) (*, 00:19:7e:4b:03:50) |
1行目は、192.168.0.1 から 74.125.31.104 (www.google.co.jp) への http アクセスを許可しています。
2行目は、MACアドレス 00:16:d3:3e:2d:25 から 00:19:7e:4b:03:50 へのあらゆるアクセスを許可しています。
IPv6 への対応はしてないです(まぁ NOX コンポーネントの実装の練習プログラムみたいなものなので、細かい仕様の不備は許しください)。
ではいよいよ実装 [4] を見ていきます。
ソフトウェア構造は以下の用になっています。
1 2 3 4 5 6 7 |
my_firewall/ |-- Rule/ | # Firewall 定義ファイルを解析するプログラム群 |-- my_firewall.py | # Firewall を実現する NOX component |-- firewall.conf # Firewall 定義ファイル(my_firewall.py は /etc/firewall.conf を参照) |
Rule ディレクトリ以下のファイルで定義してあるクラス群で、上述の Firewall 定義ファイルを解析し、内部オブジェクト (Rule オブジェクト) に変換してます。そして、パケットがコントローラに到着する度に、これらのルールを参照し、転送/破棄を決定しています。
ではいよいよ動かしてみましょう。
実効する VM (Host1) の Firewall 定義ファイル (/etc/firewall.conf) には以下を記載します。
1 2 3 |
pass (172.16.110.110) (219.94.131.163, *, 80) pass (172.16.110.110) (10.100.254.191) pass (10.100.254.191) (*) |
各 IP が何を表すかは以下のとおりです。
1 2 3 |
172.16.110.110 :Host1 のローカル IP アドレス 219.94.131.163 :アリエルの web サーバのグローバル IP アドレス 10.100.254.191 :DNS サーバのローカル IP アドレス |
ここでは Host1 からアリエルの web サーバへの http アクセスと、DNS サーバへのアクセス、そして DNS サーバからのアクセスを許可しています。その他の内から外及び、外から内へのすべての通信はコントローラによって破棄されます。フローテーブルに定義が無いパケットがくると、パケットはコントローラに流れます、フローテーブルにその他全部を破棄するような行を入れとくと、スイッチ側で破棄してくれます(面倒くさかったので実装てません)。
では Host 1 から www.google.co.jp とアリエルの公式サイト www.ariel-networks.com へ wget してみます。
最初に firewall.conf で許可した www.ariel-networks.com (219.94.131.163) へ wget しています。次に、何の記述も無い www.google.com に対して wget を試みますが、繋がりません。
ちゃんと Firewall の内-外の設定が機能していますね。
[1] http://www.openflow.org/documents/openflow-wp-latest.pdf
[2] http://www.openflow.org/documents/openflow-spec-v1.1.0.pdf
[3] http://yuba.stanford.edu/foswiki/bin/view/OpenFlow/Deployment/HOWTO/LabSetup#3_1_1_Stanford_Software_Referenc
[4] http://dev.ariel-networks.com/wp/wp-content/uploads/2011/09/my_firewall.tar.gz
最近のコメント