VineLinuxパフォーマンスアッププロジェクト:0088

■Snortをインストールしてみよう!■

 Snortはtcpdumpコマンドと同じような機能がありますが、侵入検知システム(IDS)として会社等でも広く使用されているソフトです。VineLinuxにこれをインストールして実際に動かすことができますので今回はその方法について紹介したいと思います。



 Snortは大きく分けて2つのモードがあります。

●パケットスニファモード(パケットロガーモード)

 このモードはtcpdumpコマンドと同じようなはたらきをするものです。ネットワーク上を流れるデータ(パケット)を傍受し、その傍受したデータをディスクに記録したりすることができます。

●NIDSモード(ネットワーク型侵入検知システムモード)

 こちらのモードのほうが多く使われています。ネットワーク型侵入検知システムとして作動し、あらかじめ設定されたファイルとルールに基づいて怪しいパケットがあればアラート(警告)として通知する役割を担っています。


 通常Linuxを個人で利用する方はこのようなソフトはまず使わないと思いますが、私自身現在大学の卒業研究でこのような分野を研究しており、今回使用する機会がありましたので記録として紹介するに損はないと思ったわけです。

★Snortの入手・ルールファイルの入手

 Snortは以下のページよりダウンロードできます。
https://www.snort.org/#get-started


 ページ中央部にある"Binaries"部分にリンクされているソースrpmパッケージをダウンロードしてください。Fパッケージ(FedoraCore用)はVineLinuxにうまくインストールできない場合があるためです。

downloadsnort.png(20158 byte)

Snortのrpmパッケージダウンロード画面


 次にルールファイルを入手します。ルールファイルはSnortを実行する上で必要不可欠なもので、Snort本体のパッケージとは別に入手しなければなりません。
 こちらへいき、インストールするSnortにあったバージョンをダウンロードしてください。別途Snortにユーザ登録すれば、比較的新しめのルールファイルをダウンロードすることも可能です。


★Snortのインストール・ルールファイルのインストール

 Snortのインストールはrootユーザで普通にrpmコマンドを実行するだけです。

  rpm -ivh snort-XXXXX.rpm(←XXXXXはバージョン名等)

 ソースrpmパッケージはリビルドが必要です。"rpm --rebuild パッケージ名"でリビルド完了後上のコマンドでインストールしてください。ただしインストールするにあたり、pcre-develパッケージやlibpcapパッケージ・tcpdumpパッケージ等が必要になってきますのでインストールされていなければそちらを先にapt-getコマンドなどを使用してインストールしてください。

 次にルールファイルのインストールを行います。先ほど入手したルールファイルパッケージをtarコマンドを使い適当な場所で展開します。展開が終わるとrulesというディレクトリがあるのでその中身をまるごと/etc/snort/rules内へ移動させます。これで完了です。


★設定ファイルの編集

 設定ファイルは/etc/snort/snort.confです。全文英語ですがあきらめずにがんばりましょうね。以下にその設定ファイルの例をリンクしておきます。

/etc/snort/snort.confの例

 ここでいくつか設定すべき項目があります。

▼HOME_NET記述

 HOME_NET記述には監視したいネットワークIPアドレスとサブネットマスクを記述します。もちろん監視対象をSnortがインストールされているコンピュータ1台のみにすることも可能です。その場合はそのコンピュータのIPアドレスを記述してください。

 例: var HOME_NET 222.111.177.189/24


▼EXTERNAL_NET記述

 EXTERNAL_NET記述には外部と見なすネットワークを設定します。通常はHOME_NET記述で指定したネットワーク以外すべてが外部ネットワークなので下のように設定します。

 例: var EXTERNAL_NET !$HOME_NET

 ここで"!"は「否定」を意味します。よって、"HOME_NET以外"となるわけです。


▼DNS/SMTP/HTTP/SQL/TELNET/SNMP記述

 これらは該当するサーバが構築されている場合のみ記述してください。直接IPアドレス指定で可能です。

 例: var HTTP_SERVERS [222.111.177.190/24]

 もしこれらのサーバがなければ先頭に"#"をつけてコメントアウトするか、あるいはデフォルトのままでもよいでしょう。


▼ルールファイルの有効化

 設定ファイル終わり付近にあるルールファイルの設定をすべて有効化します。先頭に"#"がついている場合はそれを取り除いてください。

 例: #include $RULE_PATH/web-cgi.rules → include $RULE_PATH/web-cgi.rules

 これで最低限の設定は完了です。


★さあ動かしてみましょう!

 では実際に動かしてみましょう。Snortは非常にオプションがたくさんありますが、ネットワーク型IDSモードで動作させるには

  /usr/sbin/snort -i 監視したいインタフェース名(eth0など) -c /etc/snort/snort.conf -l アラートの出力したいディレクトリ(/var/log/snortなど)

 とします。また、オプション"-D"をつけるとデーモンとして作動します。さらにオプション"-v"をつけると端末上で流れているパケットを監視することもできます。

 もし何らかのエラーでsnortがうまく起動しない場合は/var/log/messagesのSnort起動ログにエラー原因が格納されていますのでそこを参考にしてください。


★自動起動スクリプトの設定

 Snortをrpmパッケージでインストールすると自動的に起動スクリプトが作成され、自動起動設定をしておけば次回コンピュータの電源を入れるだけで自動的にSnortを立ち上げてデーモンとして実行してくれます。
 しかし自分の起動オプションに比べてよけいなものがあったり、足りないものがあったりする場合があるので起動スクリプトを自分流にカスタマイズしましょう。

 起動スクリプトは/etc/rc.d/init.d/snortdです。これをテキストエディタ等で開くと大体下のようになっているはずです。
#!/bin/sh
# $Id$
#
# snortd         Start/Stop the snort IDS daemon.
#
# chkconfig: 2345 40 60
# description:  snort is a lightweight network intrusion detection tool that \
#                currently detects more than 1100 host and network \
#                vulnerabilities, portscans, backdoors, and more.
#

# Source function library.
. /etc/rc.d/init.d/functions

# Source the local configuration file
. /etc/sysconfig/snort

# Convert the /etc/sysconfig/snort settings to something snort can
# use on the startup line.
if [ "$ALERTMODE"X = "X" ]; then
   ALERTMODE=""
else
   ALERTMODE="-A $ALERTMODE"
fi

if [ "$USER"X = "X" ]; then
   USER="snort"
fi

if [ "$GROUP"X = "X" ]; then
   GROUP="snort"
fi

if [ "$BINARY_LOG"X = "1X" ]; then
   BINARY_LOG="-b"
else
   BINARY_LOG=""
fi

if [ "$CONF"X = "X" ]; then
   CONF="-c /etc/snort/snort.conf"
else
   CONF="-c $CONF"
fi

if [ "$INTERFACE"X = "X" ]; then
   INTERFACE="-i eth0"
else 
   INTERFACE="-i $INTERFACE"
fi

if [ "$DUMP_APP"X = "1X" ]; then
   DUMP_APP="-d"
else
   DUMP_APP=""
fi 

if [ "$NO_PACKET_LOG"X = "1X" ]; then
   NO_PACKET_LOG="-N"
else
   NO_PACKET_LOG=""
fi        

if [ "$PRINT_INTERFACE"X = "1X" ]; then
   PRINT_INTERFACE="-I"
else
   PRINT_INTERFACE=""
fi

if [ "$PASS_FIRST"X = "1X" ]; then
   PASS_FIRST="-o"
else
   PASS_FIRST=""
fi

if [ "$LOGDIR"X = "X" ]; then
   LOGDIR=/var/log/snort
fi

# These are used by the 'stats' option
if [ "$SYSLOG"X = "X" ]; then
   SYSLOG=/var/log/messages
fi

if [ "$SECS"X = "X" ]; then
   SECS=5
fi

if [ ! "$BPFFILE"X = "X" ]; then
   BPFFILE="-F $BPFFILE"
fi

######################################
# Now to the real heart of the matter:

# See how we were called.
case "$1" in
  start)
        echo -n "Starting snort: "
        cd $LOGDIR
        if [ "$INTERFACE" = "-i ALL" ]; then
           for i in `cat /proc/net/dev|grep eth|awk -F ":" '{ print $1; }'`
           do
                mkdir -p "$LOGDIR/$i"
                chown -R $USER:$GROUP $LOGDIR
                daemon /usr/sbin/snort $ALERTMODE $BINARY_LOG $NO_PACKET_LOG $DUMP_APP -D $PRINT_INTERFACE -i $i -u $USER -g $GROUP $CONF -l $LOGDIR/$i $PASS_FIRST $BPFFILE $BPF
           done
        else
           # check if more than one interface is given
           if [ `echo $INTERFACE|wc -w` -gt 2 ]; then
              for i in `echo $INTERFACE | sed s/"-i "//`
                do
                  mkdir -p "$LOGDIR/$i"
                  chown -R $USER:$GROUP $LOGDIR
                  daemon /usr/sbin/snort $ALERTMODE $BINARY_LOG $NO_PACKET_LOG $DUMP_APP -D $PRINT_INTERFACE -i $i -u $USER -g $GROUP $CONF -l $LOGDIR/$i $PASS_FIRST $BPFFILE $BPF
             done
           else
              # Run with a single interface (default)
              daemon /usr/sbin/snort $ALERTMODE $BINARY_LOG $NO_PACKET_LOG $DUMP_APP -D $PRINT_INTERFACE $INTERFACE -u $USER -g $GROUP $CONF -l $LOGDIR $PASS_FIRST $BPFFILE $BPF
           fi
        fi
        touch /var/lock/subsys/snort
        echo
        ;;
  stop)
        echo -n "Stopping snort: "
        killproc snort
        rm -f /var/lock/subsys/snort
        echo 
        ;;
  reload)
        echo "Sorry, not implemented yet"
        ;;
  restart)
        $0 stop
        $0 start
        ;;
  condrestart)
        [ -e /var/lock/subsys/snort ] && $0 restart
        ;;
  status)
        status snort
        ;;
  stats)
        TC=125                          # Trailing context to grep
        SNORTNAME='snort'               # Process name to look for

        if [ ! -x "/sbin/pidof" ]; then
           echo "/sbin/pidof not present, sorry, I cannot go on like this!"
           exit 1
        fi

        #Grab Snort's PID
        PID=`pidof -o $$ -o $PPID -o %PPID -x ${SNORTNAME}`

        if [ ! -n "$PID" ]; then        # if we got no PID then:
           echo "No PID found: ${SNORTNAME} must not running."
           exit 2
        fi

        echo ""
        echo "*******"
        echo "WARNING:  This feature is EXPERIMENTAL - please report errors!"
        echo "*******"
        echo ""
        echo "You can also run: $0 stats [long | opt]"
        echo ""
        echo "Dumping ${SNORTNAME}'s ($PID) statistics"
        echo "please wait..."

        # Get the date and tell Snort to dump stats as close together in
        # time as possible--not 100%, but it seems to work.
        startdate=`date '+%b %e %H:%M:%S'`

        # This causes the stats to be dumped to syslog
        kill -USR1 $PID

        # Sleep for $SECS secs to give syslog a chance to catch up
        # May need to be adjusted for slow/busy systems
        sleep $SECS

        if [ "$2" = "long" ]; then              # Long format
            egrep -B 3 -A $TC "^$startdate .* snort.*: ={79}" $SYSLOG | \
                grep snort.*:
        elif [ "$2" = "opt" ]; then             # OPTimize format
           # Just show stuff useful for optimizing Snort
            egrep -B 3 -A $TC "^$startdate .* snort.*: ={79}" $SYSLOG | \
                egrep "snort.*: Snort analyzed |snort.*: dropping|emory .aults:"
        else                                    # Default format
            egrep -B 3 -A $TC "^$startdate .* snort.*: ={79}" $SYSLOG | \
                grep snort.*: | cut -d: -f4-
        fi
        ;;
  *)
        echo "Usage: $0 {start|stop|reload|restart|condrestart|status|stats (long|opt)}"
        exit 2
esac

exit 0
 これを修正するわけですが、具体的な修正箇所を説明するのが非常に面倒なので修正したsnortdを以下にリンクしておきます。このsnortdは自動起動で

  /usr/sbin/snort -D -i eth0 -c /etc/snort/snort.conf -l /var/log/snort

 となるように設定してあります。もし改良したい場合は掲示板などで連絡いただければ対処しますのでぜひご利用ください。

改良版snortdスクリプトはこちら ←(利用する場合はsnortdという名前で保存してください。)


★Snortログのお助けツール

 最後にSnortと一緒に使用すると役立ちそうなツールを紹介しておきます。

▼SnortSnarf

 これはSnortが吐き出すアラートやポートスキャンログをhtml形式に変換してくれる視覚化ツールです。日本語化もできますのでおすすめのツールです。
*SnortSnarfはこちらから

▼Oinkmaster

 これはSnortのルールファイルを自動的に更新してくれるものです。Snortのルールファイルは常にアップデートが行われているので毎回毎回手動でダウンロードして差し替えるのは面倒です。そんな時はこの出番。これを使えば必要なルールファイルのみアップデートしたりすることもできるようです。
*Oinkmasterはこちらから

▼Swatch

 これはSnortのアラートなどを随時監視して設定した文字列とマッチするようなアラートがあれば何らかの行動を起こすといったリアルタイムログ監視ツールです。うまく使いこなせば警告メールを自動配信することもできます。VineLinuxでインストールするのがかなり複雑ですが、これもおすすめのツールです。
*Swatchはこちらから


★Snortのアラートをデータベース出力にする

 Snortのアラートをテキストファイル形式ではなく、データベース出力にすることもできます。また、Snortとデータベースサーバとを別々に稼働させておいてネットワーク経由でSnortのアラートを遠く離れたデータベースサーバに格納させることも可能です。

 私自身VineLinuxでデータベースを扱う際にはPostgresqlを使用するのがほとんどなのでPostgresql形式でアラート格納にチャレンジしてみました。詳しくは以下のページで説明しています。

SnortとPostgresqlを連携させる方法


★acidでログを視覚化する

 Snortのアラートは蓄積されると分析するのが面倒になってしまいます。そこでログ視覚化ツールacidをインストールしてみましょう。ちょっとインストールが大変ですが、これをインストールするだけでぐんと解析作業の負担が軽減されること間違いなしですよ。詳しくは以下のページで説明しています。

acidをインストールしてみよう!(1)





プロジェクト ホームへ戻る