2012-09-13

OpenBlocks AX3でasteriskのパフォーマンス測定


◆はじめに

Asteriskはご存知の方も多いと思いますがオープンソースのPBXです。今回はOpenBlocks AX3にAsteriskを導入しSIPサーバとして利用します。
内線通話やSIPプロバイダへの接続設定を行いiPhoneをSIPクライアントとして動作確認を行います。
さらにOpenBlocks AX3がSIPサーバとしてどの程度のパフォーマンスがでるかを簡単に測定してみます。


◆Hard Float対応のasterisk導入

OpenBlocks AX3の標準OSであるDebian 6.0では、バイナリパッケージとしてasteriskが用意されておりますが、今回は後述の通りソースパッケージからビルドして利用しています。

OpenBlocks AX3に搭載しているCPUは、Marvell社のARMADA XPというものでARMv7に対応しハードウェアFPUを搭載したCPUですが、現状のDebian 6.0では残念ながらARMv7やハードウェアFPUを活かしたAsteriskの利用が出来ません。
これは、ハードウェアFPUがなく、古くからあるARMアーキテクチャのハードウェアでも動作させるためであろうと推測しますが、バイナリがARMv4の命令セットを使用しハードウェアFPUを使用しない状態で構築されています。そのため、本記事では性能をフルに発揮できるようにソースパッケージからの利用方法をご紹介しています。
(なお2013年に公開予定となっているDebianの次期バージョン7.0では、armhfという新たなアーキテクチャが用意され、ARMv7及びハードウェアFPUを利用するバイナリが用意される見込みのようです。)

今回の利用環境としてOpenBlocks AX3のkernelイメージとして以下のものを利用しました。
ftp://ftp.plathome.co.jp/pub/OBSAX3/squeeze/3.0.6-4/uImage.initrd.obsax3
またストレージ併用モードを利用しました。
ストレージ併用モードではパッケージビルドの際に/tmpの容量が足りなくなってしまうためあらかじめSSDを利用するように対応しておきます。(/etc/fstabにあるtmpfsを使ったサンプル設定でも構いません)
 $ su
 # mkdir /.rw/tmp
 # mount -t unionfs -o dirs=/.rw/tmp=rw:/tmp=ro unionfs /tmp

 # df /tmp
 Filesystem           1K-blocks      Used Available Use% Mounted on
 unionfs               30771896  12702648  16506128  44% /tmp
早速asteriskの導入に入ります。
asteriskは2012年8月21日現在では10系や11系(beta)なども利用可能ですが1.8系が安定版のLTS(Long Term Support)となってますので今回は1.8系を利用します。

OpenBlocks AX3のdebian環境(squeeze)のaptでもインストール可能ですが標準でインストールasteriskは1.6系になってしまいます。
今回は1.8系を利用したいのでasterisk.orgで提供しているdebian用のパッケージを利用します。
残念ながらarmel用のバイナリパッケージは提供されていませんのでソースパッケージからビルドします。
この際OpenBlocks AX3で利用可能なHard Floatに対応するためにコンパイルフラグを少々変更してコンパイルを行います。

手順は https://wiki.asterisk.org/wiki/display/AST/Asterisk+Packages を参考に以下のように行いました。
 $ su
 # apt-key adv --keyserver pgp.mit.edu --recv-keys 175E41DF
 # echo "deb-src http://packages.asterisk.org/deb squeeze main" > /etc/apt/sources.list.d/asterisk.list
 # exit

 $ mkdir ~/asterisk-18
 $ cd ~/asterisk-18
 $ apt-get source asterisk
 $ cd asterisk-1.8.11.1
 $ vi debian/rules
 (Hard Float対応のため以下を追加)
  CFLAGS += -march=armv7-a -mhard-float -mfloat-abi=softfp -mfpu=vfpv3-d16
 $ su
 # apt-get build-dep asterisk
 # exit
 $ dpkg-buildpackage -us -uc
以下のようにdebパッケージが生成されます。
 $ ~/asterisk-18
 $ ls -1 *.deb
 asterisk-config_1.8.11.1-1digium1~squeeze_all.deb
 asterisk-dahdi_1.8.11.1-1digium1~squeeze_armel.deb
 asterisk-dbg_1.8.11.1-1digium1~squeeze_armel.deb
 asterisk-dev_1.8.11.1-1digium1~squeeze_all.deb
 asterisk-doc_1.8.11.1-1digium1~squeeze_all.deb
 asterisk-h323_1.8.11.1-1digium1~squeeze_armel.deb
 asterisk-mobile_1.8.11.1-1digium1~squeeze_armel.deb
 asterisk-mp3_1.8.11.1-1digium1~squeeze_armel.deb
 asterisk-mysql_1.8.11.1-1digium1~squeeze_armel.deb
 asterisk-ooh323_1.8.11.1-1digium1~squeeze_armel.deb
 asterisk-voicemail-imapstorage_1.8.11.1-1digium1~squeeze_armel.deb
 asterisk-voicemail-odbcstorage_1.8.11.1-1digium1~squeeze_armel.deb
 asterisk-voicemail_1.8.11.1-1digium1~squeeze_armel.deb
 asterisk_1.8.11.1-1digium1~squeeze_armel.deb
asterisk-voicemail*はconflictしてしまいますので上記のうちasterisk-voicemail-imapstorageとasterisk-odbcstorageを除いたdebパッケージをインストールします。
 $ su
 # dpkg -i asterisk-[c-o]*.deb asterisk-voicemail_1.8.11.1-1digium1~squeeze_armel.deb
ここまででasteriskパッケージの導入は完了です。


◆iPhoneとMacで内線通話を行う

まずはasteriskの基本動作の確認ということでSIP内線通話の設定を行います。
動作確認を行うための機材とSIPクライアントは以下のものを利用しました。
 - iPhone 4S / AGEphone 1.41
 - MacbookAir / Telephone 1.0.4
iPhone,MacbookAirともにローカルネットワークにWifiで接続されているものとします。
asteriskパッケージでは設定ファイルが山のようにインストールされますが、これらは使用せずに今回は必要最小限度の設定のみを行います。
設定ファイルは/etc/asteriskディレクトリ以下に置きます。
今回は以下のように設定しました。users.confでクライアントの設定、extensions.confで動作を設定します。
内線番号は6000番台として、それぞれ6000, 6001が各クライアントの内線番号としました。
users.conf:
 [general]
 hassip = yes

 ; iphone 4s(AGEphone)
 [6000]
 type=friend
 secret=test0
 canreinvite=no
 host=dynamic

 ; macbook air(Telephone)
 [6001]
 type=friend
 secret=test1
 canreinvite=no
 host=dynamic

extensions.conf:
 [default]
 exten=_6XXX,1,Dial(SIP/${EXTEN},30,tT)
 exten=_6XXX,n,HangUp

asterisk.conf:
(空)

sip.conf:
(空)

modules.conf:
 [modules]
 preload => codec_alaw.so
 preload => codec_ulaw.so
 preload => codec_gsm.so
 preload => codec_g722.so
 preload => pbx_config.so
 preload => pbx_realtime.so
 preload => chan_sip.so
 preload => app_dial.so
 preload => app_macro.so
 load => res_rtp_asterisk.so
asteriskが動作している場合は一度停止します。
 # /etc/init.d/asterisk stop
デバッグ用メッセージを確認するためasteriskをフォアグラウンドで起動します。
 # asterisk -ddddvvvvc
 *CLI>
各SIPクライアントを起動します。
SIPクライアントの設定の詳細は省略しますが、SIPサーバはasteriskを動作させているマシンのIPv4アドレス、ユーザ名は6000または6001、パスワードは上記users.confに記載したパスワードとします。
各クライアントがサーバに接続するとasteriskのCLIにはSIP REGISTERなどのデバッグ用メッセージ等がでてきます。
ここでasteriskがSIPクライアントを認識していることをCLIで確認します。
 *CLI> sip show peers
 Name/username              Host                                    Dyn Forcerport ACL Port     Status  
 6000/6000                  192.168.111.228                        D   N             15060    Unmonitored
 6001/6001                  192.168.111.29                           D   N             52374    Unmonitored
 2 sip peers [Monitored: 0 online, 0 offline Unmonitored: 2 online, 0 offline]
クライアント2台がonlineになっていることが確認できました。

実際にiPhoneのAGEphoneから6001番で発信し通話ができることを確認します。同様に逆方向も確認します。
上記設定でとくに問題なく通話できることを確認しました。


◆SIPプロバイダへの接続設定

次はasterisk確認その2としてSIPプロバイダへの接続を試します。
今回はFusionのIP-Phone SMARTというサービスを使って確認します。

今回はOpenBlocks AX3のeth1側にグローバルアドレスを付与してインターネットとつながるようにしました。
全体のネットワーク構成は以下のようになります。























IP-Phone SMARTの申込手続き等はすでに済んでいるとものとしてasteriskの設定をします。
6000番台は内線、0からはじまる番号は外線としてSIPプロバイダに接続するような設定を行います。
前項の設定のsip.confとextensions.confを以下のように修正します。
sip.conf:
 [general]
 port = 5060
 bindaddr = 0.0.0.0
 qualify = no
 disallow = all
 allow = alaw
 allow = ulaw
 dtmfmode = rfc2833
 srvlookup = yes

 register => <ユーザID>:<パスワード>@<SIPドメイン>

 [sipprovider]
 type = friend
 insecure = port,invite
 nat = no
 canreinvite = no
 authuser = <ユーザID>
 username = <ユーザID>
 fromuser = <ユーザID>
 fromdomain = <SIPドメイン>
 host = <SIPドメイン>
 secret = <パスワード>
 usereqphone=yes
 context = incoming
 allowsubscribe=no

extensions.conf:
 [globals]
 MYDIAL=<自番号>

 [default]
 exten => _6XXX,1,Dial(SIP/${EXTEN},30,tT)
 exten => _6XXX,n,HangUp
 exten => _0.,1,Dial(SIP/sipprovider/${EXTEN},180,tT)
 exten => _0.,n,Hangup

 [incoming]
 exten => ${MYDIAL},1,Dial(SIP/6000&SIP/6001,30,tT)
 exten => ${MYDIAL},n,HangUp
<ユーザID>、<パスワード>、<SIPドメイン>、<自番号>はそれぞれSIPプロバイダから提供されるものを利用します。
IP-Phone SMARTのサービスの場合、<ユーザID>,<自番号>はどちらも050に続く8桁の電話番号、<SIPドメイン>はsmart.0038.netとなります。
設定ができたらasteriskを起動します。
 # asterisk -ddddvvvvc
 *CLI>
SIPプロバイダに登録されたかを確認します。
 *CLI> sip show registry
 Host                                    dnsmgr Username       Refresh State                Reg.Time              
 smart.0038.net:5060                     N      5???????           105 Registered           Thu, 23 Aug 2012 00:00:00
 1 SIP registrations.
次にPEERの情報を確認します。
 *CLI> sip show peers
 Name/username              Host                                    Dyn Forcerport ACL Port     Status  
 6000/6000                  192.168.111.228                        D   N             15060    Unmonitored
 6001/6001                  192.168.111.29                           D   N             62240    Unmonitored
 sipprovider/5???????       ??.???.???.???                                          5060     Unmonitored
 3 sip peers [Monitored: 0 online, 0 offline Unmonitored: 3 online, 0 offline]
実際にiPhone/AGEphoneから外部の固定電話に対し発信し無事に通話できることを確認しました。
また外部の固定電話からSIPプロバイダから付与された番号に対し発信したところ、内線6000,6001の両方で着信音が鳴り、どちらかのSIPクライアントで通話できることを確認しました。

今回は単純化のためにセキュリティ対策についての記載は省略しましたが、実運用時にはセキュリティ対策について十分な考慮が必要となりますのでご注意ください。


◆sippを使用したasteriskのパフォーマンス測定

asteriskのパフォーマンスを測定してみます。
今回はsippというツールを用いて同時接続数がどの程度まで耐えられるかを測定します。
OpenBlockSのasterisk一台に対してsippをインストールしたLinux PCからテストを行います。
ネットワーク構成は以下のようにします。



sippを使用するマシンはCore2Duo 2.13GHzにUbuntu Linuxをインストールしています。
http://sourceforge.net/projects/sipp/
からsipp.svn.tar.gzをダウンロードしbuildします。
 pc$ tar zxvf sipp.svn.tar.gz
 pc$ cd sipp.svn
 pc$ make pcapplay
これでsippが生成されます。

次にsippでの測定のためにasteriskの設定を行います。
200番は直ちに応答し音声をそのままエコーする設定にしました。
users.conf:
 ; 以下を追加
 [sipp]
 type=friend
 canreinvite=no
 host=dynamic

extensions.conf:
 [default]
 exten => 200,1,Answer()
 exten => 200,n,Echo()
 exten => 200,n,Hangup()

modules.conf:
 ; 以下を追加
 preload => app_echo.so
asteriskを起動します。性能測定なのでできるだけ余分なメッセージがでないようにします。
 # asterisk -c
 *CLI>
今回の測定にはsippに標準で用意されている二つのシナリオで行います。

シナリオ1は1通話は10秒無音待機後に接続を切るという動作とします。MAX接続数を増やしながら、再送数(Retrans)が0より大きくなる地点を探します。
実際のコマンドは以下になります。<MAX接続数>は100から100ずつ増やして確認を行います。
 pc# ./sipp -sn uac -d 10000 -s 200 -r 100 -l <MAX接続数> -m 5000  192.168.111.217
測定の結果、500までは再送数が0でしたが600以上では再送が出現しました。
よってOpenBlocks AX3上でのシナリオ1の同時最大接続数は500程度のようです。

シナリオ2は1通話8+1=9秒で音声を流し接続を切るという動作とします。シナリオ1と同様にMAX接続数を増やしながら、再送数(Retrans)が0より大きくなる地点を探します。
 pc# ./sipp -sn uac_pcap -s 200 -r 100 -l <MAX接続数> -m 5000  192.168.111.217
測定の結果、400までは再送数が0でしたが500以上では再送が出現しました。
よってOpenBlocks AX3上でのシナリオ2の同時最大接続数は400程度のようです。

上記のシナリオ実行中に、内線通話でiPhone/AGEphoneとMac/Telephone間(音声もasteriskを経由)で通話を行いましたが、音飛びや遅延などは感じられませんでした。


◆まとめ

今回はOpenBlocks AX3にasteriskを用いてSIPサーバの設定を行いました。
内線通話およびSIPプロバイダへの接続設定を行い問題なく使用できることを確認しました
SIPサーバのパフォーマンス測定を行い、同時接続数400〜500程度まで行けそうなことを確認しました。

2012-09-12

[.tested] テクノブロード PoE-ZR2512T/PoE-ZR1005T PoE受電アダプタ [AX3][A6]



テクノブロード PoE-ZR2512Tは12V/2.1A出力、PoE-ZR1005Tは5V/2A出力のPoEの受電アダプタです。
今回、上記2製品をテクノブロード様よりお借りし、OpenBlocks AX3およびA6における動作検証を行いました。





OBDN技術ブログによる動作検証は、該当するデバイスの動作を保証およびサポートを行うものではありません。
内容に関するご指摘などありましたら、ブログ記事の担当までご連絡下さい。

<検証環境>
OpenBlocks AX3/4 Debian 6.0 kernel: 3.0.6
OpenBlocks A6 Debian 6.0 kernel: 2.6.31.8

1. 対応するDC出力ケーブルについて
本受電モジュールを使用する場合、DCケーブルのプラグ形状は接続する機器に合わせる必要があります。
今回は、ACアダプタの仕様に基づき、テクノブロード様にて、対応するケーブルを用意していただきました。

2. 給電アダプタについて
今回は、PoE-ZS251T(1ポート)をお借りしました。


本製品は受電の規格として、IEEE802.3afに対応していますが(本規格の受電側の最大電力は12.95 W)、25Wの電力供給を行える独自規格による拡張がされており、仕様上は、ZSシリーズ以外の給電アダプタには対応していません。
AX3の場合、最大13Wを必要としますので、IEEE802.3afの受電側規格、12.95 Wを上回り、上記の独自拡張による電力供給が必要となるため、ZSシリーズの給電アダプタをご使用下さい。

また、A6で使用したPoE-ZR1005Tについては、IEEE802.3afの規格内となりますが、他社との接続検証を別途行う必要がありますので、ZSシリーズとの組み合わせでのご使用を推奨します。

なお、ユニバーサルな使用が可能な単体の受電のみのアダプタで、25.5Wの受電が可能なIEEE802.3atに対応したものは、当社では扱いがありません。

3. 対応するLAN規格について
10BASE-T/100BASE-TXに対応しています。

4. 製品の詳細について
以下のリンクを参照願います。

PoE受電アダプタ詳細

PoE給電アダプタ詳細

5. 動作検証について
PoE受電モジュールにより、AX3、A6、それぞれ1日程連続稼動させましたが、特に異常なく動作しています。
ただし、あくまでも短期的な検証であり、当社の公式サポート対象外となりますことをご理解願います。

2012-09-11

OSC 2012 Tokyo/Fall セミナー内容について (PDFファイル)

OSC 2012 Tokyo/Fall 来場ありがとうございました。
また関係者の方、お疲れ様でした。

Kansai/Kyotoに続き、A Familyに関して、以下のタイトルにて、45分のセミナー枠にて発表させて頂きました。Kyotoでは公開していない、apache benchやarmel/armhfパッケージの比較なども追加しています。
以下に発表時のPDFを公開します。
なお、OSC 2012 沖縄のJus発表枠や大分でのセミナー枠では、若干違うアプローチでの発表を考えています。

開発担当者が語る最新マイクロサーバーの作り方 -ソフトウェア実装秘話と実運用に迫る

--
2012/10/2 PDFファイルpreviewにより以降の記事に影響があることがわかりましたので、リンクのみとします。

2012-09-04

OpenBlocks AX3 で PacketFence を動かしてみる

はじめに


PacketFence は、ネットワークアクセスコントロール(Network Access Control, NAC)システムのオープンソース実装です。2004年頃から開発が行われ、現在に至るまでアクティブに開発が行われています。2012年8月現在の最新バージョンは 3.5.0 です。

大変多機能な PacketFence の主な特徴は以下の通りです。

  • in-band, out-of-band (VLAN) に対応
  • FreeRadius を使った 802.1X 認証、VoIPに対応
  • ワイヤレス接続も透過的に対応(有線でも無線でも共通のユーザDB、Web認証を使用可能)
  • snort/suricata を使った不正なネットワークアクティビティの検知が可能
  • Nessus / OpenVAS と連携させて脆弱製検出機能追加も可能
  • 問題のある端末をネットワークアクセスから隔離し、対象端末のステータスに応じて指定した URL へと誘導させる機能
  • コマンドラインからでも web ペースでも可能なシステム管理
  • ゲストアクセス機能

なお、オフィシャルの推奨環境としては以下のように挙げられています。

  • Intel / AMD CPU 3GHz (もしくはそれ以上)
  • 2GB (もしくはそれ以上) の RAM
  • 20GB (もしくはそれ以上) のディスクスペース (RAID 1 を推奨)
  • 1 ネットワークカード (高可用性向け設定には +1, 侵入検知向け設定には +1)

ドキュメント・マニュアル類は公式 web サイトにてPDFが公開されており、大変充実した内容となっています。

今回は、この PacketFence を OpenBlocks AX3 にインストール、使用を試みてみました。


PacketFence の AX3 へのパッケージインストール


PacketFence 自体はアーキテクチャ非依存の(主に)perl スクリプトで構成されていますが、PacketFence が使用する各種 perl モジュールの中には一部、アーキテクチャ依存のものがあったり、Debian 公式のリポジトリには存在しないパッケージも多数必要となります。

PacketFence 自体は6月リリースのバージョン 3.4.0 から deb パッケージが公開されていますが、i386 と amd64 のみのリポジトリのみとなっており、armel 用のパッケージ群はオフィシャルには用意されていません。

そこで今回、アーキテクチャ依存の perl モジュールを含め、PacketFence 3.5.0 をインストールするのに必要なパッケージ群をリポジトリとして用意しました。

/etc/apt/sources.list.d/pf.list などのファイルを作成し、そこに
deb     http://ftp.plathome.co.jp/pub/OBSAX3/obdnmag/packetfence35 squeeze main
deb-src http://ftp.plathome.co.jp/pub/OBSAX3/obdnmag/packetfence35 squeeze main
と書いてやり、
# apt-get update
# apt-get install packetfence
とすれば、AX3 用に PacketFence を導入できるようにしました(パッケージには署名を施していませんので、"WARNING: The following packages cannot be authenticated!" と表示されますが、Y を押下して進めてください)。

VLAN 設定可能な L2 スイッチを併用するのであれば、ネットワークアダプタが1つあればよく、メインのネットワーク(eth0)の他に登録用ネットワーク(eth0:2)と隔離用ネットワーク(eth0:3)といった風に /etc/network/interfaces に登録しておきます。Snort などを使った不正検出を行う場合は、パケット監視用に別途他のアダプタ(例えば eth3)を用意しておきます。
そうでないのであれば、複数のアダプタに対して、メイン(eth0)、登録用(eth1, eth2, ...)といった風に登録しておきます。


installer.pl によるインストール作業


ここまで済んだら、以下のコマンドを実行して、PacketFence のインストールを完了させます。
# /usr/local/pf/installer.pl

(1) 最初に DISCLAIMER が表示され、許諾するかどうか聞かれます

(2) 続いて PacketFence の使用する MySQL データベースの情報を聞かれます
MySQL Host [localhost]:
MySQL Port [3306]:
Database Name [pf]:
Current Admin User [root]:
Current Admin Password:

(3) 更に PacketFence 用にデータベース pf を作成する旨確認を促されます

(4) PacketFence が DB アクセス時に使うアカウント作成を促されます
Username [pf]:
Password:
Confirm:

(5) PacketFence の管理者ユーザアカウント作成を促されます
Username [admin]:
New password:
Re-type new password:

(6) Snort 用のルールファイルを emergingthreats.net からダウンロードするか尋ねられます
Do you want me to download the latest Emergingthreats rule files?
This is only necessary if you intent to use Snort. [y|n]
「y」を選ぶと、以下のファイル群がダウンロードされます
/usr/local/pf/conf/snort/emerging-botcc.rules
/usr/local/pf/conf/snort/emerging-attack_response.rules
/usr/local/pf/conf/snort/emerging-exploit.rules
/usr/local/pf/conf/snort/emerging-malware.rules
/usr/local/pf/conf/snort/emerging-p2p.rules
/usr/local/pf/conf/snort/emerging-scan.rules
/usr/local/pf/conf/snort/emerging-shellcode.rules
/usr/local/pf/conf/snort/emerging-trojan.rules
/usr/local/pf/conf/snort/emerging-virus.rules
/usr/local/pf/conf/snort/emerging-worm.rules

(7) DHCP フィンガープリントファイルのダウンロード・更新を行うか尋ねられます
Do you want me to update the DHCP fingerprints to the latest available version? [y|n]
「y」を選ぶと、以下のファイルがダウンロードされます
/usr/local/pf/conf/dhcp_fingerprints.conf

(8) OUI (Organization Unit Identifier) ファイルのダウンロード・更新を行うか訪ねられます
Do you want me to update the OUI prefixes to the latest available version? [y|n]
「y」を選ぶと、以下のファイルがダウンロードされます
/usr/local/pf/conf/oui.txt

(9) その他、後処理(必要なディレクトリの生成、一部ファイル・ディレクトリのオーナーシップ変更など)が行われて終了です
Installation is complete
** Please run /usr/local/pf/configurator.pl before starting PacketFence **



configurator.pl による PacketFence の初期設定



PacketFence の設定は主に以下の2ファイルで行われます。
/usr/local/pf/conf/pf.conf
/usr/local/pf/conf/networks.conf

前者(pf.conf)に書かれていないパラメータ(デフォルト値)は、
/usr/local/pf/conf/pf.conf.defaults
から補完されますので参照して下さい。

これらの設定を(テンプレートを元に)インタラクティブに行うコマンドラインツールが、 上述の installer.pl 終了直後に実行を促される configurator.pl となります。
# /usr/local/pf/configurator.pl

ここでは、以下の様な使用形態を前提として設定を行うこととします。
  • インラインネットワーク(PacketFence ホストをルータとして使用)
  • eth0 が外部と繋がっているネットワーク(マネージメントネットワーク)
    192.168.0.0/24
    
web 管理画面へのアクセスもこちらから行う
  • eth1eth2 が登録用ネットワーク
    192.168.1.0/24, 192.168.2.0/24

eth1eth2 の登録ネットワークセグメントに接続された端末は、PacketFence が dhcp によって供与する IP アドレスを与えられ、web アクセスを行うと、そのアクセスはリダイレクトされ Captive Portal へと導かれます。

(1) Snort を使った不正検出の有効・無効を選ぶ
[trapping]detection={disabled,enabled} に対応
有効にする場合は、VLANで使わないインタフェースを別途指定します(eth3など)
What kind of configuration would you like to put in place?
    1) PacketFence standalone (Basic configuration)
    2) PacketFence with detection (SNORT)
Configuration choice:
 [1|2]

(2) VLAN 使用の有無を選ぶ。VLAN のみ、インラインのみ、VLAN インライン混在から選びます。
What kind of enforcement would you like to use for isolation?
    1) VLANs
    2) Inline
    3) VLANs and Inline
Enforcement choice:
 [1|2|3]

(3) PacketFence 全般の設定

(3.1) ホストネームの設定
[general]hostname= に対応
What's my host name (without the domain name)?
    (default: packetfence | current: platax3 | ?)

(3.2) ドメイン名の設定
[general]domain= に対応
What's my domain name?  (default: packetfence.org | current: localdomain | ?)

(3.3) DHCP サーバの設定
[general]dhcpservers= に対応
DHCP servers, including me (comma delimited):
    (default: 127.0.0.1 | current: 127.0.0.1 | ?)

(3.4) 管理用 Web UI のポート番号の設定
[ports]admin= に対応
What will be my webGUI admin port? (default: 1443 | current: 1443 | ?)

(3.5) 通知用メールアドレスの設定
[alerting]emailaddr= に対応
Which email address should receive my notifications and other sundry goods sent?
    (default: pf@localhost | current: pf@localhost | ?)

(3.6) PacketFence 管轄下のサービスが停止していた場合、メールを送るかどうかの設定
[servicewatch]email={enabled,disabled} に対応
Should I send notification emails when services managed by PacketFence
    are not running? (default: enabled | current: enabled | [ enabled|disabled ] | ?)

(3.7) そのサービスが停止していた際に PacketFence がそれらを再起動するかどうかの設定
[servicewatch]restart={enabled,disabled} に対応
Should I restart services I manage and that seems halted?
    (Remember that you'll need to install a cron entry. See conf/pf.conf.defaults)
    (default: disabled | current: disabled | [ enabled|disabled ] | ?)

(3.8) 強制的デバイス登録を有効にするかの設定
[trapping]registration={enabled,disabled} に対応
Do you want to force registration of devices?
    (default: disabled | current: disabled | [ enabled|disabled ] | ?)

(3.9) 高可用性 (HA) セッティングにするかどうかの設定
Do you want to use a high-availability setup? (default:  | [ enabled|disabled ] | ?)

(4) Snort で監視するポートを選ぶ
What is my monitor interface?
    (default:  | [ eth0|eth1|eth2|eth3|sit0 ] | ?)

(5) データベース設定

(5.1) データベースサーバのホスト名
[database]host= に対応
Where is my database server? (default: localhost | current: localhost | ?)

(5.2) データベースサーバのポート
[database]port= に対応
Which port is it listening on? (default: 3306 | current: 3306 | ?)

(5.3) 使用するデータベース名
[database]db= に対応
Which database should I use? (default: pf | current: pf | ?)

(5.4) データベースアクセス時に使用するアカウント
[database]user=pass= に対応
Which account should I use? (default: pf | current: pf | ?)
What is the password associated with this account?:
Confirm:

(6) ネットワークインタフェースの設定
pf.conf[network eth0] などの設定と、networks.conf 内の設定に対応
*** PacketFence configuration rely on your network interfaces attributes. Prior to
continue, make sure that those are correctly configured using ifconfig (You should
open a new term window to avoid closing this configuration process) ***

Is eth0 ( 192.168.0.196 ) to be used by PacketFence? [y|n]
What kind of interface is it? (default:  | [ internal|management ] | ?)

Is eth1 ( 192.168.1.254 ) to be used by PacketFence? [y|n]
Is eth2 ( 192.168.2.254 ) to be used by PacketFence? [y|n]

(7) PacketFence ネットワークの設定
networks.conf 内の設定に対応
*** PacketFence will now be configured to act as a DHCP / DNS server on the
enforcement enabled interfaces ***

Interface eth1 (192.168.1.254 mask 255.255.255.0)
What's the network prefix? (ex: 192.168.1.0) (default:  | ?)
What is the DHCP scope first address? (default:  | ?)
What is the DHCP scope last address? (default:  | ?)

Interface eth2 (192.168.2.254 mask 255.255.255.0)
What's the network prefix? (ex: 192.168.1.0) (default:  | ?)
What is the DHCP scope first address? (default:  | ?)
What is the DHCP scope last address? (default:  | ?)

(8) 終了
Writing PacketFence and networks configurations

ここまでで、/usr/local/pf/conf/{pf,networks}.conf が設定され、出力されます。

実際の動作時(/etc/init.d/packetfence start など)には、/usr/local/pf/conf/ 以下の各種設定ファイルをもとに、/usr/local/pf/var/conf/ 以下に設定ファイルが生成され、それらが各サービス・デーモンの設定ファイルとして使用されます。


その他、必要に応じて行う設定



(9.1) web admin 用アカウントのパスワードを設定
# htpasswd -d /usr/local/pf/conf/admin.conf admin
# htpasswd -d /usr/local/pf/conf/admin.conf webservice
これらは installer.pl 実行時に聞かれて設定する場合もあります。

(9.2) ip_forward を有効にする
インライン利用の場合、この設定が必要となる場合があります。
# vi /etc/sysctl.conf
net.ipv4.ip_forward=1

(9.3) webservice パスワードの設定
FreeRadius を認証に使用する場合に必要となります。
/etc/freeradius/packetfence.pm
FreeRadius 側から PacketFence にアクセスする為のアカウント設定
WS_PASS を (9.1) で設定した webservice アカウントのパスワードに設定します
/etc/freeradius/sql.conf
FreeRadius 側から SQL データベースにアクセスする為のアカウント設定
password を installer.pl 実行時に設定した pf アカウントのパスワードに設定します

(9.4) networks.conf の編集
インライン使用の場合、/usr/local/pf/conf/networks.conf 内の各インタフェース用設定パラメータにおいて、以下を確認し、必要であれば編集します。
  • named=enabled に修正(デフォルトでは disabled になっている)
  • dns= の値を、PacketFence 内部 DNS ではなくグローバルに引ける DNS に設定
後者は、例えばインラインネットワーク 192.168.1.0/24eth1 (192.168.1.254) では、dns=192.168.1.254 にするのではなく、外部ネットワークのグローバル DNS (例えば 8.8.8.8 など) にしておくことが、正しく動作するために必要です。

(9.4) Oinkmaster のインストールと設定
Snort を使う場合、不正検出ルールファイルの定期的な更新が必要になるので、この定義ファイルの自動更新の設定を行うツールを入れ、設定しておくとよいでしょう。

Oinkmaster は、Debian squeeze にパッケージが存在しているので、それをインストールして PacketFence 用に設定してもよいですが、PacketFence は全体的に /usr/local/pf/ 内で全完結することをよしとするようですので、その際は
  • oinkmaster 一式を /usr/local/pf/oinkmaster にコピーする
  • PacketFence が提供するサンプルの oinkmaster 設定ファイル 
/usr/local/pf/addons/snort/oinkmaster.conf
 で、oinkmaster 付属のデフォルト設定ファイルを置き換える
  • oinkmaster.conf 内の
 url = http://rules.emergingthreats.net/open/snort-2.9.0/emerging.rules.tar.gz
 を、インストールされている snort のバージョンに近いもの
 url = http://rules.emergingthreats.net/open/snort-2.8.4/emerging.rules.tar.gz
 に書き換える
などといった手順を踏むことになります。

その後、oinkmaster が定期的に実行されるように
0 23 * * * (cd /usr/local/pf; perl oinkmaster/oinkmaster.pl \
            -C conf/oinkmaster.conf -o conf/snort/)
などと cron に登録しておきます。


管理 web UI へのアクセス


マネージメントネットワーク (ここでは eth0) 側のセグメントから、以下の URL にアクセスすることで可能です。
https://(packetfence eth0 側のホスト名またはIPアドレス):1443/

この画面からユーザ名 admin、パスワードは (9.1) で設定したものを使ってログインすると、管理画面のダッシュボードが表示されます。

この画面で閲覧・設定可能な内容は全て、管理コマンド /usr/local/pf/bin/pfcmd を使って閲覧・設定が可能です。



利用パターンの概要


PacketFence では、主に以下の VLAN に分割してネットワークセグメントを管理します。
  • 通常のネットワーク (Regular VLAN)
  • 登録用ネットワーク (Registration VLAN)
  • 隔離用ネットワーク (Isolation VLAN)
登録されていないホストやユーザは、登録用ネットワークへと導かれます。登録が済んだホスト・ユーザは通常のネットワークへと導かれます。Snort 使用時は、ネットワークアクティビティの不正を検出した際、隔離用ネットワークへと導かれます。

VLAN を使わず PacketFence をルーター的に使う場合(今回はこちらで動作検証を行いました)は、以下のように管理されます。
  • 通常のネットワーク
  • インラインネットワーク
登録されていないホストやユーザは、インラインネットワークからアクセスし、登録を促されます。登録が済んだホスト・ユーザは、外部ネットワークへのアクセスが許可され、PacketFence マシンがルータとして機能します。

PacketFence 上に登録されていないホストは登録用ネットワークへと導き、登録が済んだホストは通常のネットワークへと導かれます。この際、ユーザが自らゲスト登録を行うようにする設定も可能です。
/usr/local/pf/conf/pf.conf:
guests_self_registration={enabled|disabled}
ユーザ自身によるゲスト登録は、SMS を使ったアクティベーション、電子メールでのアクティベーションなどがありますが、日本の SMS 環境は今のところ考慮されていないコーディングになっているようですので、修正を行うか、電子メールでのアクティベーションを使うことになるでしょう。

Snort を使った検出の結果違反があった場合(例えば Limewire を使っているホストを検出した場合、など)、隔離用ネットワークへと移されたり(VLAN)、アクセスがブロックされたり(インライン)します。以下は、デフォルトで設定ファイルに書かれている、Limewire を使ったパケット検出を有効にする設定です。
/usr/local/pf/conf/violations.conf:
[2001808]
desc=P2P (Limewire)
priority=8
url=/remediation.php?template=p2p
enabled=Y
max_enable=1
trigger=Detect::2001808
VLAN 設定可能な L2 スイッチを PacketFence と連携して使う場合、1ホストアダプタ (eth0) 上で複数 VLAN を動かせばよいので、必ずしも 2ホストアダプタ以上は必要としません(Snort を使う場合は、パケット監視用に1アダプタを使用します)。

VLAN ではない通常のインラインネットワークを使う場合は、PacketFence 稼働ホスト(ここでは AX3 マシン)がルータとして働き、iptables NAT が使われることになるので、登録済みホストのネットワークアクセスパケットは全て PacketFence ルータを通過することになり、それだけ負荷もあがることになります。また、ネットワーク的にも SPOF (Single Point of Failure) になりやすいので注意が必要でしょう。


インライン運用による使用例


以下、PacketFence が稼働する AX3 マシンをルータ・ファイヤーウォール的に使用し、このマシンのインラインネットワークに接続するホストを制御する際のおおまかな流れを、スクリーンショットを交えて概説します。

ここで AX3 は、eth0 を介して外部ネットワークに接続されており、eth1eth2 をインラインネットワークとして使用します。全ての端末はこのインラインネットワーク下に接続されるものとします。
/usr/local/pf/conf/pf.conf{,.defaults}:

[trapping]
registration=enabled

[registration]
guests_self_registration=enabled
のように設定しており、未認証端末はユーザ自身によるゲスト登録画面へと誘導されます。

また、ここでは AX3 マシン上でのローカルの認証を行い、LDAP や FreeRADIUS などは使用していません。
/usr/local/pf/conf/pf.conf{,.defaults}:

[registration]
# Method by which registering nodes will be authenticated.
# Templates for LDAP, RADIUS, Kerberos, local and guests are
# available at /authentication.  If you wish to use
# a different authentication mechanism, simply create a file
# called /authentication/.pm,
# fill it with the necessary data, and set auth=.
# The default value, local, relies on a local access file in
# /user.conf.
auth=local

インラインネットワーク下の未認証端末が web アクセスをしようとすると、ブラウザには以下のような画面(Captive Portal)が表示されます。


ここで「Sign up」をクリックすると、ユーザ自身によるゲスト登録を行う画面へと遷移します。

ここでは
/usr/local/pf/conf/pf.conf{,.defaults}:

[guests_self_registration]
modes=sms,email,sponsor
という設定になっており、SMS による認証、電子メールによる認証、スポンサー経由の認証が有効になっています。通常の使用では modes=email だけで充分と思われます。


必須入力フィールドも設定ファイルで指定可能です。デフォルトは以下の通りです。
/usr/local/pf/conf/pf.conf{,.defaults}:

[guests_self_registration]
mandatory_fields=firstname,lastname,phone,email

デフォルトでは無意味な文字列である「Acceptable Use Policy」内の文面は、以下で定義されています。
/usr/local/pf/html/captive-portal/templates/aup_text.html

その他、認証時に表示される各遷移ページは、以下に HTML 形式で置かれているので、必要に応じてカスタマイズ可能です。
/usr/local/pf/html/captive-portal/templates/

この段階で、Web 管理画面の「NODE」⇒「view」を覗くと、以下の様に表示され、インラインネットワークへのアクセスがあった全ホストの状態が閲覧できます。最も上に表示されたホストが現在ゲスト登録をしようとしているホストであり、「Status」が「unreg」つまり未登録であることが分かります。

同一の内容は、以下のコマンドでも閲覧可能です。
# /usr/local/pf/bin/pfcmd node view all


認証用のメールを受け取りたいメールアドレスを入力し「I accept the terms」にチェックを入れ、「Register by Email」をクリックすると、次のスクリーンショットの様な画面が表示されたのち、ネットワークアクセスが一時的に有効になります。


メールによる認証を行うまでの間、一時的に外部ネットワークへのアクセスが有効になりますが、この時間は設定により変更可能です。デフォルト設定では10分となっています。
/usr/local/pf/conf/pf.conf{,.defaults}:

[guests_self_registration]
email_activation_timeout=10m

PacketFence は、ゲスト登録画面で入力された電子メールアドレス宛に、認証用のメールを送ります。メール用に接続する SMTP サーバは設定ファイル内で変更可能です([alerting]smtpserver)。

インラインネットワーク上のゲスト端末自体から認証を行うためには、gmail などの web メールを使うことになると思われます。

送られたメールのサンプルは以下の通りです。


このリンクをクリックすると、正式にゲスト登録され、認証済の端末としてネットワークアクセスが可能になります。


デフォルトでは、認証完了後7日間のアクセスが可能となります。この日数は設定により変更可能です。
/usr/local/pf/conf/pf.conf{,.defaults}:

[guests_self_registration]
# The length of network access a confirmed guest will have. On successful
# confirmation a guest node's unregdate is set to now + access_duration.
access_duration=7D


その他


上のケースでは、ユーザ自身によるゲスト登録という流れでしたが、
  • ユーザ自身によるゲスト登録申請、それを受けて管理者が許可・拒否を行う
  • ユーザ自身の登録は行えず、管理者があらかじめ許可登録したホストのみ使用可能
といった運用も可能です。


現時点での問題点


全体的にパフォーマンスが遅い
インラインでの運用(AX3 をルータ・ファイヤーウォール的に使用)では、iptables NAT によるオーバーヘッドもあり、スループット的にはあまり期待できないようです。

実際、サーバ機(Core2Duo E8400)とクライアント機(Atom 330)を用意し、ab (Apache Bench) で静的コンテンツに対する簡単なベンチマーク(ab -c 100 -n 100000 http://test.localdomain/sample.html など)をとってみたところ、AX3 を経由しない場合に平均 55,000Kbytes/sec のパフォーマンスがでたところ、AX3 を経由した場合 (PacketFence をルータ的に使用) には、平均 35,000Kbytes/sec にまで低下してしまいました。この時 PacketFence によって自動設定された iptables の内容を巻末に引用しておきます。

また、Perl モジュールを組み合わせて作られている PacketFence そのものや web 管理インタフェース表示のレスポンス、サービス再起動時などに要する時間なども比較的長めで、これは公式サイトで推奨ハードウェアとして挙げられているスペックより低いため、致し方ないと思われます。

snort が動作しないことがある
snort を使った不正パケット監視を packetfence 側から管理する際、pfdetectsnort が特に異常なエラーログを出力することなく落ちることがありました。これは現在、パッケージング(PacketFence が必要とする各種 perl モジュールなども含めて)の為なのか、Debian wheezy からより新しい snort をバックポートする必要があるのか、それとも設定内容の不備の為なのか、を含め調査中です。なにか気付かれた方がいらっしゃいましたら、ご一報頂ければ幸いです。


付録


eth0 (192.168.0.0/24) が外部ネットワーク、eth1 (192.168.1.0/24), eth2 (192.168.2.0/24) がインラインネットワーク、という、インライン設定で PacketFence を運用する際に、自動設定される iptables 内容(例):
# Generated by iptables-save v1.4.8 on Mon Jul  2 22:11:15 2012
*filter
:INPUT DROP [83450:12805732]
:FORWARD DROP [5:380]
:OUTPUT ACCEPT [899415:51053741]
:forward-internal-inline-if - [0:0]
:input-highavailability-if - [0:0]
:input-internal-inline-if - [0:0]
:input-internal-vlan-if - [0:0]
:input-management-if - [0:0]
-A INPUT -i lo -j ACCEPT
-A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
-A INPUT -p icmp -m icmp --icmp-type 8 -j ACCEPT
-A INPUT -d 192.168.1.254/32 -i eth1 -j input-internal-inline-if
-A INPUT -d 255.255.255.255/32 -i eth1 -j input-internal-inline-if
-A INPUT -d 192.168.0.196/32 -i eth1 -p tcp -m tcp --dport 443 -j ACCEPT
-A INPUT -d 192.168.2.254/32 -i eth2 -j input-internal-inline-if
-A INPUT -d 255.255.255.255/32 -i eth2 -j input-internal-inline-if
-A INPUT -d 192.168.0.196/32 -i eth2 -p tcp -m tcp --dport 443 -j ACCEPT
-A INPUT -i eth0 -j input-management-if
-A FORWARD -i eth1 -j forward-internal-inline-if
-A FORWARD -i eth2 -j forward-internal-inline-if
-A FORWARD -i eth0 -m state --state RELATED,ESTABLISHED -j ACCEPT
-A forward-internal-inline-if -m mark --mark 0x1 -j ACCEPT
-A input-highavailability-if -p tcp -m state --state NEW -m tcp --dport 22 -j ACCEPT
-A input-highavailability-if -p udp -m udp --dport 5405 -j ACCEPT
-A input-highavailability-if -p udp -m udp --dport 5407 -j ACCEPT
-A input-highavailability-if -p tcp -m tcp --dport 7788 -j ACCEPT
-A input-internal-inline-if -p udp -m udp --dport 67 -j ACCEPT
-A input-internal-inline-if -p tcp -m tcp --dport 67 -j ACCEPT
-A input-internal-inline-if -p tcp -m tcp --dport 53 -m mark --mark 0x3 -j ACCEPT
-A input-internal-inline-if -p udp -m udp --dport 53 -m mark --mark 0x3 -j ACCEPT
-A input-internal-inline-if -p tcp -m tcp --dport 53 -m mark --mark 0x2 -j ACCEPT
-A input-internal-inline-if -p udp -m udp --dport 53 -m mark --mark 0x2 -j ACCEPT
-A input-internal-inline-if -p tcp -m tcp --dport 53 -m mark --mark 0x1 -j DROP
-A input-internal-inline-if -p udp -m udp --dport 53 -m mark --mark 0x1 -j DROP
-A input-internal-inline-if -p tcp -m tcp --dport 80 -m mark --mark 0x1 -j DROP
-A input-internal-inline-if -p tcp -m tcp --dport 443 -m mark --mark 0x1 -j DROP
-A input-internal-inline-if -p tcp -m tcp --dport 80 -j ACCEPT
-A input-internal-inline-if -p tcp -m tcp --dport 443 -j ACCEPT
-A input-internal-vlan-if -p udp -m udp --dport 53 -j ACCEPT
-A input-internal-vlan-if -p udp -m udp --dport 67 -j ACCEPT
-A input-internal-vlan-if -p tcp -m tcp --dport 67 -j ACCEPT
-A input-internal-vlan-if -p tcp -m tcp --dport 80 -j ACCEPT
-A input-internal-vlan-if -p tcp -m tcp --dport 443 -j ACCEPT
-A input-management-if -p tcp -m state --state NEW -m tcp --dport 22 -j ACCEPT
-A input-management-if -p tcp -m tcp --dport 1443 -j ACCEPT
-A input-management-if -p tcp -m tcp --dport 1812 -j ACCEPT
-A input-management-if -p udp -m udp --dport 1812 -j ACCEPT
-A input-management-if -p tcp -m tcp --dport 1813 -j ACCEPT
-A input-management-if -p udp -m udp --dport 1813 -j ACCEPT
-A input-management-if -p udp -m udp --dport 162 -j ACCEPT
-A input-management-if -p udp -m udp --dport 67 -j ACCEPT
-A input-management-if -p tcp -m tcp --dport 67 -j ACCEPT
-A input-management-if -p tcp -m tcp --dport 9392 -j ACCEPT
-A input-management-if -p tcp -m tcp --dport 443 -j ACCEPT
COMMIT
# Completed on Mon Jul  2 22:11:15 2012
# Generated by iptables-save v1.4.8 on Mon Jul  2 22:11:15 2012
*mangle
:PREROUTING ACCEPT [1656139:1620626399]
:INPUT ACCEPT [280:41132]
:FORWARD ACCEPT [1655790:1620570673]
:OUTPUT ACCEPT [90:8961]
:POSTROUTING ACCEPT [1655880:1620579634]
:prerouting-int-inline-if - [0:0]
-A PREROUTING -i eth1 -j prerouting-int-inline-if
-A PREROUTING -i eth2 -j prerouting-int-inline-if
-A prerouting-int-inline-if -j MARK --set-xmark 0x3/0xffffffff
-A prerouting-int-inline-if -m mac --mac-source 00:1B:FC:XX:XX:XX -j MARK \
        --set-xmark 0x1/0xffffffff
-A prerouting-int-inline-if -m mac --mac-source 00:1C:C0:YY:YY:YY -j MARK \
        --set-xmark 0x1/0xffffffff
COMMIT
# Completed on Mon Jul  2 22:11:15 2012
# Generated by iptables-save v1.4.8 on Mon Jul  2 22:11:15 2012
*nat
:PREROUTING ACCEPT [136694:21222584]
:INPUT ACCEPT [170:44855]
:OUTPUT ACCEPT [42437:2575166]
:POSTROUTING ACCEPT [42437:2575166]
:postrouting-int-inline-if - [0:0]
:prerouting-int-inline-if - [0:0]
-A PREROUTING -i eth1 -j prerouting-int-inline-if
-A PREROUTING -i eth2 -j prerouting-int-inline-if
-A POSTROUTING -o eth0 -m mark --mark 0x3 -j postrouting-int-inline-if
-A POSTROUTING -o eth0 -m mark --mark 0x1 -j postrouting-int-inline-if
-A POSTROUTING -o eth0 -m mark --mark 0x2 -j postrouting-int-inline-if
-A postrouting-int-inline-if -j MASQUERADE
-A prerouting-int-inline-if -p udp -m udp --dport 53 -m mark --mark 0x3 -j REDIRECT
-A prerouting-int-inline-if -p udp -m udp --dport 53 -m mark --mark 0x2 -j REDIRECT
-A prerouting-int-inline-if -p udp -m udp --dport 53 -m mark --mark 0x3 -j REDIRECT
-A prerouting-int-inline-if -p udp -m udp --dport 53 -m mark --mark 0x2 -j REDIRECT
-A prerouting-int-inline-if -p tcp -m tcp --dport 80 -m mark --mark 0x3 -j REDIRECT
-A prerouting-int-inline-if -p tcp -m tcp --dport 80 -m mark --mark 0x2 -j REDIRECT
-A prerouting-int-inline-if -p tcp -m tcp --dport 443 -m mark --mark 0x3 -j REDIRECT
-A prerouting-int-inline-if -p tcp -m tcp --dport 443 -m mark --mark 0x2 -j REDIRECT
COMMIT
# Completed on Mon Jul  2 22:11:15 2012