cactiで SSH認証失敗数をモニタする

 2014-09-10
iptablesとか、SSHguardとかあるけど、まずは攻撃されているかどうかの見える化を。
 

cactiって便利ね。

グラフ化すると見やすいし、cactiならちょいちょいするだけで勝手にログ取ってグラフになるのでこれ。ブルートフォースを受けた試行回数を数えてグラフにしてみようという感じ。
  snmpdに外部コマンドを追加してHDD温度を取得する
  cactiで任意の数値をグラフ化する

てきとうスクリプト

なにかイイカンジのソフトがあれば良かったんだけど思いつかないしいまいち検索にhitしないので、
スクリプトを書いちゃう。
#!/bin/zsh -f

# arg check
if [ $# -ne 1 ];
then
echo "arg error: $0 <MIN_AGO>\n"
exit 1
fi
if [[ "$1" =~ ^[0-9]+$ ]];
then
;
else
echo "arg error: $0 <MIN_AGO>\n"
exit 1
fi
MIN_AGO=$1
LC_ALL=C
LANG=C

LOGFILE="/var/log/secure"

for MIN in {${MIN_AGO}..0}
do
MONTH_OLD=`date +%h --date "${MIN} min ago"`
DAY_OLD=` date +%-d --date "${MIN} min ago"`
HOUR_OLD=` date +%H --date "${MIN} min ago"`
MIN_OLD=` date +%M --date "${MIN} min ago"`
LINE_BEGIN=`egrep -n "${MONTH_OLD} *${DAY_OLD} *${HOUR_OLD}:${MIN_OLD}:" ${LOGFILE} |\
grep 'Failed password for' | head -1 | cut -d":" -f1`

if [ ${LINE_BEGIN:-0} -ne 0 ];
then
break
fi
done
if [ ${LINE_BEGIN:-0} -eq 0 ];
then
echo "0"
exit
fi


sed -n -e "${LINE_BEGIN},\$p" ${LOGFILE} | grep 'Failed password for' | wc -l


/var/log/secureのログファイルから指定された時間だけ遡って、Failed password forという文字列が現れる回数を数えている。

LC_ALL=C とか LANG=C にして、dateで出力される月の表示を Sep とかの英語表示にしている。日本語ロケールのままだと 9月 とかが出力されるので非常にうっとおしい。

for文で引数の数だけループ。内部でdateコマンドでgrep用の文字列を生成。日付跨ぎとかを考えるとループ毎にdateで取得するのが楽だった。

一番古い Failed password for の行を発見できれば、その行数を記録してからforループをbreakする。
ループを抜けたら本当にちゃんと行数を見つけられたかどうかを確認し、行数が記録されてなければ、 Failed password forは無かったモノとしてそのまま終了。

行数が見つかっていれば、sedでその行以降の部分を取り出してきて、grepしてwcで行数カウント。これが出力になる。


使い方はこんな感じで。
root# ./getsshfailed.sh 5
0

引数で、何分遡るか指定する。cactiは5分毎にポーリングするので、基本的に5で使うつもりで書いた。けどほかの数字を指定しても一応動いてる。

SNMPでcactiへ

上記を適当なディレクトリに放り込んで、/etc/snmp/snmpd.conf に下記を追記する。
extend sshfailed5min   "/bar/boon/bin/getsshfailed.sh 5"

もちろんsnmpdを再起動させておく。
root# service snmpd restart

狙い通り動いているかsnmpwalkで確認してみる。
user% snmpwalk -v 2c -c public localhost .1.3.6.1.4.1.8072.1.3
<中略>
NET-SNMP-EXTEND-MIB::nsExtendOutput1Line."sshfailed5min" = STRING: 0


あとはSNMP Generic OID扱いで、cactiに登録してグラフ化させる。
graph_image_20140910192242281.png
結構来るもんです。 これ、プライベートIPのCATVのネットワークなんですけどねー。なしてこんなに届くのやら。
↑iptablesのコマンド調整中につきアタック受けすぎです ゲボォ


Redhat系以外だと?

ちなみに、上記がちゃんと動くのはRedhat系だと思います。CentOSとFedoraでは動いた。
なんか知らんけど、snmpdがrootで走っていたので、/var/log/secure にアクセスできたのだぁ。
いいのか?おいおい。

RaspberryPiではDebian系のRaspbianが走っておりますが、コヤツはsnmpというユーザでsnmpdが走っているので、このままでは/var/log/auth.log にアクセスできずに値がとれません。
# Redhat系では /var/log/secure でしたが、debian系では /var/log/auth.log みたいです。ふーん。。
ちょっと小細工をします。


view_authlog.cというファイルを用意する
#include <stdio.h>

main (int argc, char *argv[]){
FILE *fpr;
char buf[BUFSIZ];
if((fpr=fopen("/var/log/auth.log","r"))==NULL){
return (-1);
}
while(fgets(buf,sizeof(buf),fpr)!=NULL){
fprintf(stdout,"%s",buf);
}
}
C言語のプログラムで、 /var/log/auth.log というファイルをopenして標準出力にずらずらとはき出すだけのもの。
これをコンパイルして、chownして、SUIDをつけます。
user% gcc ./view_authlog.c -o ./view_authlog

user% sudo chown root:root ./view_authlog
user% sudo chmod 4775 ./view_authlog

SUIDとはなんぞや? 実行ファイルのオーナーの権限で、実行することができます。この場合、chownでrootに所有権を移しているので、どのユーザが実行しても、このプロセスはroot権限で動きます。こわい!

こわいですがこれでログの中身が見れるようになりました。SUIDはスクリプト系のファイルには付与できないらしいので、わざわざC言語で実行ファイルを作りました。メンド。

あとは例のてきとうスクリプトをちょい変。
#!/bin/zsh -f

# arg check
if [ $# -ne 1 ];
then
echo "arg error: $0 <MIN_AGO>\n"
exit 1
fi
if [[ "$1" =~ ^[0-9]+$ ]];
then
;
else
echo "arg error: $0 <MIN_AGO>\n"
exit 1
fi
MIN_AGO=$1
LC_ALL=C
LANG=C

LOGFILE="/tmp/sshfailed_$$"
/ras/berry/pi/view_authlog > ${LOGFILE}

for MIN in {${MIN_AGO}..0}
do
MONTH_OLD=`date +%h --date "${MIN} min ago"`
DAY_OLD=` date +%-d --date "${MIN} min ago"`
HOUR_OLD=` date +%H --date "${MIN} min ago"`
MIN_OLD=` date +%M --date "${MIN} min ago"`
LINE_BEGIN=`egrep -n "${MONTH_OLD} *${DAY_OLD} *${HOUR_OLD}:${MIN_OLD}:" ${LOGFILE} |\
grep 'Failed password for' | head -1 | cut -d":" -f1`

if [ ${LINE_BEGIN:-0} -ne 0 ];
then
break
fi
done
if [ ${LINE_BEGIN:-0} -eq 0 ];
then
\rm -f ${LOGFILE}
echo "0"
exit
fi



sed -n -e "${LINE_BEGIN},\$p" ${LOGFILE} | grep 'Failed password for' | wc -l
\rm -f ${LOGFILE}

変更してるのは一部分だけ。 /ras/berry/pi/view_authlog > ${LOGFILE} の部分で、例の view_authlog を呼び出して、 ${LOGFILE} にリダイレクト。つまり、 /var/log/auth.log をコピーしちゃう。これで、自由にアクセスできるね!やったね!
そして後始末のために \rm -f ${LOGFILE} を追記してるくらい。あとは同じように動きます。
RaspberryPiではちょっとレスポンスがおそいね。ちゃんとperlとか使えば良かったかな。でも(どうでも)いいや。


じゃあ適当に頑張ってください。
ほかにもっと良い方法があったらコッソリ教えてください。
 
コメント












管理者にだけ表示を許可する
トラックバック
トラックバックURL:
http://wbbwbb.blog83.fc2.com/tb.php/170-8f013fe9
≪ トップページへこのページの先頭へ  ≫