Snortは侵入検知システム、IDSと呼ばれるセキュリティ対策ソフトウェアに分類されます。
Snortの説明については豊富に文献が存在するのでそちらなどに譲ります。ここでは基礎はあまり語りません。
不正侵入の検知が得意なこのSnortですが、通常は不正侵入を検知するだけでその通信をブロックしてはくれません。 そこで、怪しいアクセスを行ったホストに対してそのアクセスを強制的に切断する、FlexResp機能を組込んでアクティブファイアウォール化を試みます。(当初、これら不正な通信をブロックするためにGuardianを仕込もうと考えていたのですが、開発の更新止まっているし、なんだか動かないし、そもそも外部プログラムなのでスループットにモロに影響でそうだったので、途中で諦めました。)
ここで予め断っておきますが、Snortの侵入検知も完璧ではありません。正常なアクセスを誤検知して不正とみなしてしまうこともあるかもしれません。FlexResp機能を使うとそういった類のアクセスも問答無用で切断してしまう諸刃の剣であるということを認識しておく必要があります。
FlexResp機能を利用する為にはSnortを--with flexrespオプション付きでRPMをビルドする必要があります。SnortのRPMパッケージはVineにもあることはありますが、バージョンが古すぎて使い物になりません。そこでSnort.orgから最新版のSRPMをダウンロードしてきます。
が、その前にSnortとの依存関係にあるパッケージをインストールしておきましょう。
まず、通常のSnort自体の依存関係を解決すべく、pcre-develとlibpcapをaptでインストールします。
次いで、FrexResp機能の実現に必要なlibnetをインストールする必要があります。しかし、困ったことにVineには標準でlibnetが用意されていません。
そこで、libnetのRPMを公開しているDag Wieers氏(?)のサイトからlibnet-1.0.2-2.rf.src.rpmを拾ってきてビルドします。
specファイルも公開されていますので、自分でソースファイル持ってきてRPMを作成することも出来ます。こんな至れり尽くせりなサイトを公開してくれているDag Wieers氏に感謝!
これでlibnetのインストール完了です。(出来たlibnetのRPMをテンポラリに置いています。)
次に、SnortのRPMを作成します。
Snort.orgにRPMバイナリパッケージと共にSRPMが置いてありますのでこれをダウンロードし、インストールします。
そして--with frexrespオプション付きでビルドします。
出来上がったSnortのパッケージをインストールします。
これでインストールが完了します。
OS起動時にSnortが起動するように設定します。ここではランレベル3と仮定しています。また、起動する順番も適当ですので構築する環境に合わせてください。
Snortの設定に入ります。ここで指定するネットワークは"はじめに"で示したネットワーク図に基きます。
/etc/snort/snort.conf を、適用するネットワークに合わせて修正します。 もし、DNSサーバやHTTPサーバなどを、Snortに個別に認識させたい場合は、"var DNS_SERVERS $HOME_NET"のようになっている箇所に修正を加えます。(だいたい50数行目から)
次に、/etc/sysconfig/snortを次のように編集して、監視インターフェースをbr0に指定します。(変更する箇所だけ抜粋)
Snortの、ユーザ独自ルールを作成する為、local.rulesファイルを作成します。
詳しくは後ほど触れますので、今はまだ何も記述する必要はありません。
さて、これでSnort本体の設定は終わりです。次はSnortのルールを更新するOinkmasterの導入を説明します。これはちょっと面倒です。
OinkmasterはSnortのルールを自動でアップデートしてくれるツールです。設定方法は次のとおり。
ここでは、それぞれ/usr/local/binと/usr/local/etcにコピーするようにします。
念の為、これらのファイルのアクセス権と所有権を適切に変更しておきます。
/usr/local/etc/oinkmaster.confを修正します。が、その前に別のことをしなければいけません。
Snortのルールセットは、なんだかごたごたがあったみたいで、以前とは配布形態が変わっているようです。
有償のルールセットを購入するか、一応登録すれば無償で使えるルールセットを利用するか、はたまたコミュニティーリリースのルールセットを使うかの三択を迫られます。(SnortのMLを参照)
私は当初、コミュニティーベースのルールセットを利用しようと画策したのですが、ルールの種類が少ない上に、Includeするルールファイル名がsnort.confに記述してあるものと違っていてSnortが起動できませんでした。
もちろんSnort.confのIncludeファイル名を変更すれば解決する問題なのですが、なんだかあからさまに邪険に扱われているようだったので、仕方なくユーザ登録する方を選ぶことにしました。
これでようやくoinkmaster.confを編集できる準備が整いました。 編集は次のようになります(変更箇所のみ抜粋)。ちなみにurlの値はダミーです。
ちなみに、今回のSnortルールのバージョンはCURRENTを指定しています。 この為、Snortのバージョンが上がった場合にルールの更新が出来なくなる可能性もありますので気を付ける必要があります。
さて、ちゃんと動くかテストしてみましょう。
操作に問題が無ければcrontabに記述して定期実行するようにします。ここでは毎週土曜日の1時にのみ更新するようにしています。
これでOinkmasterの設定は完了です。Snortを起動してみましょう。
/var/log/messages を見て、エラーなど出ていなければ無事に起動完了です。もし起動出来ていないならば、設定などに問題があるのかもしれませんので、再度設定ファイルなどの見直しが必要です。まぁ、言うまでも無い事ですが…。
正常に起動出来たなら、次はカスタムルールを作成して検知テストを行います。
ユーザ独自のルールを定義するファイルである/etc/snort/rules/local.rulesに、次のように記述してSnortを再起動しルールを適用します。
このルールが適用されると、$EXTERNAL_NETから$HOME_NETへの全TCPトラフィックを検知するようになります。
$HOME_NETのホストに対して、それ以外のホストからブリッジ経由でTCPアクセス、SSHやFTP、HTTPなどでアクセスしてみて下さい。
正常に稼動していれば、/var/log/snort/alertに検知内容が記録されるはずです。
次にSnortのFlexResp機能を活用する方法の説明に移ります。
さて、通常の検知テストがうまくいったならば、次はFlexResp機能を試します。
先ほど作成したlocal.rulesファイルの内容を下記のように少し変更します。
resp:rst_all;の記述を追加してSnortを再起動してください。
その後、HOME_NETに属していないネットワークから、先ほどと同じようにHOME_NET内のホストのTCPサービスポートにアクセスしてみてください。すぐに接続が切断されるはずです。もし切断されないようなら何か間違っています。/var/log/messagesや/var/log/snort/alertあたりをよく確認してみてください。
あ…、このテストが終わったらlocal.rulesの1行はコメントにしてSnort再起動しておくのが吉です。
このresp:rst_allの記述は両方向にTCP-RSTパケットを送信する、つまり通信を終了するという意味になります。このFlexRespの引数には、次のようなものがあります。
| 引数 | 説明 |
| rst_snd | 送信側ソケットにTCP-RSTパケットを送信する |
| rst_rcv | 受信側ソケットにTCP-RSTパケットを送信する |
| rst_all | 両方向にTCP-RSTパケットを送信する |
| icmp_net | 送信側にICMP_NET_UNREACHを送信する |
| icmp_host | 送信側にICMP_HOST_UNREACHを送信する |
| icmp_port | 送信側にICMP_PORT_UNREACHを送信する |
| icmp_all | 送信側に上記のICMPパケットをすべて送信する |
これらを利用して、遮断したいアクセスに対するルールを作成することが可能です。また、Oinkmasterで取得したルールファイル内のルールに resp:引数[,引数...];として追記すれば、容易に不正アクセスを遮断できるでしょう。ただし、この場合、再度Oinkmasterでルールファイルを更新すると、FlexRespの記述が消えてしまうことに気をつけてください。
さぁ、これでFlexResp機能付きのSnortが運用可能になりました。
それでは、快適なネットライフをどうぞ!!
…正直、FrexResp専用にルールを一つ一つ作成していくのはかったるくてやってられません。では、どうするか。
ここが難しいところですが、方法の一つとして、Oinkmasterが更新したルールファイルのTCPルールの全てに、FlexRespの設定を追記してしまうという手があります。ただし、Snortに誤検知がある以上、これは常に意図したとおりの動作をするとは限りません。もし今から書く内容をそのまま実行する場合は、そのことを十分認識しておいてください。何か問題が起こっても僕は責任は取れませんので、あしからず。
では、始めましょう。
まず、/etc/snortディレクトリに、addresp.shというファイルを作成し次のように記述します。
同じく/etc/snortディレクトリに、updaterules.shというファイルを作成します。内容は次のとおりです。
それらのファイルに実行権限を付与します。
Oinkmaster構築の時にcrontabに記述した一文を次のように変更します。
今crontabに登録したファイルでは、次のような処理を行っています。
Oinkmasterによるルールファイル更新の後、findコマンドでルールファイルを探し出し、ファイル名をaddresp.shファイルに渡します。addresp.shの方では、渡されたファイルの中にある、"alert tcp"で始まるルールの末尾にresp:rst_all;を追加します。ファイルの変更が完了したらSnortの再起動を実行します。
まぁ…、なんというか、自分でもかなり乱暴な気がします…。 でもこれで一応SnortのAlertにひっかかるTCP接続は遮断することが出来るでしょう。(あまり考えずに施した設定なので大きな見落としがある可能性は高いですけど)
| 参考書籍/参考サイト |
| 日本 Snort ユーザ会 |
| snortで変わりだねファイアウォール(flex_respを使う) |
| 正規表現メモ |