クラウドサーバを利用していたり、自宅サーバに外部から接続できるようにしていると、不正アクセスによる乗っ取りの可能性を考える必要があります。
(少なくともパスワード認証を禁止して鍵認証によるログインは絶対にしておきましょう)
それでも、本当にサーバが乗っ取られていないか心配ですよね。
そこで、SSH接続時に出力されるログを監視してログイン成否を通知してみます。
swatchを使用します。
環境
・動作環境:IDCFクラウド
・OS:CentOS 6.9
インストール
epelリポジトリを追加する必要があります。
rpm -ihv http://ftp.riken.jp/Linux/fedora/epel/6/i386/epel-release-6-8.noarch.rpm
yum -y install swatch
設定ファイル作成
/etc
配下に設定ファイルを作成して監視条件を指定します。
mkdir /etc/swatch
mkdir /etc/swatch/conf
touch /etc/swatch/conf/secure.conf
### 成功時通知
watchfor /Accepted/
exec "\/root\/slack\/bin\/authAlert.sh $_ > /dev/null 2>&1"
### 失敗時通知
watchfor /Invalid user/
exec "\/root\/slack\/bin\/authAlert.sh $_ > /dev/null 2>&1"
\ * + . ? { } ( ) [ ] ^ $ - | /
がメタ文字となるため、バックスラッシュでエスケープしています。
ここではwatchfor
の後で指定する監視文字列をそれぞれ"Accepted"
と"Invalid user"
にしています。
これは/var/log/secure
に出力されるSSHログイン成功時、失敗時の文字列です。他の出力例はこちらを参考にしてください。
そして、条件にマッチした際にexec
でシェルスクリプトを実行してslackに通知します。引数の$_
は検知行全体という意味です。
Slackへの通知はSlack APIでやります。参考
今回用いる通知シェルスクリプトの中身はこんな感じです。
# !/bin/bash
USERNAME="SSH-alert"
CHANNEL="#test"
ICON=":ghost:"
TEXT=$*
WEBHOOK_URL="https://hooks.slack.com/services/T2PBMxxxx/B2Q5xxxxx/JuG08e37bczxxxxxxxxxxx"
author="author name"
data=`cat << EOF
payload={
"channel": "$CHANNEL",
"username": "$USERNAME",
"icon_emoji": "$ICON",
"link_names": 1 ,
"attachments": [{
"text": "$TEXT"
}]
}
EOF`
curl -X POST --data-urlencode "$data" $WEBHOOK_URL
パーミッション変更も忘れずに。chmod 700 /root/slack/bin/authAlert.sh
swatchではその他にも様々な挙動をさせることができます:参考
動作確認
swatchを起動して動作確認してみます。書式はこんな感じです。
swatch -c [設定ファイル] -t [監視対象ログファイル]
監視ログファイルは/var/log/secure
ですので、以下の通り実行します。
swatch -c /etc/swatch/conf/secure.conf -t /var/log/secure &
"Accepted"
および"Invalid user"
を含む行が通知されていることが分かります。
※上のほうにたくさん"Invalid user"
が通知されていますが、辞書式アタックというのは本当に頻繁に来ていることが分かります。
サービス登録
あとはサービス登録して自動起動するようにしておきます。
# /bin/sh
#
# swatch
#
# chkconfig: 2345 90 35
# description: swatch start/stop script
#
. /etc/rc.d/init.d/functions
[ ! -d /var/log/swatch ] && mkdir -p /var/log/swatch
PATH=/bin:/sbin:/usr/bin:/usr/sbin
start() {
ls /var/run/swatch_*.pid 1> /dev/null 2>&1
if [ $? -ne 0 ]; then
echo -n "Starting swatch"
pno=0
RET=0
for conf in /etc/swatch/conf/*.conf
do
log=`basename $conf | cut -d\. -f1`
if [ -f /var/log/$log ]; then
pno=`expr $pno + 1`
swatch -c $conf -t /var/log/$log --daemon \
--pid-file /var/run/swatch_$pno.pid 1>> /var/log/swatch.log 2>& 1
RET=$?
[ $RET != 0 ] && return $RET
fi
done
if [ $pno -gt 0 ]; then
echo
[ $RET = 0 ] && touch /var/lock/subsys/swatch
fi
return $RET
else
echo "swatch already started"
fi
}
stop() {
ls /var/run/swatch_*.pid 1> /dev/null 2>&1
if [ $? -eq 0 ]; then
echo -n "Stopping swatch"
for pid in /var/run/swatch_*.pid
do
kill $(cat $pid)
rm -f $pid
done
echo
rm -f /var/lock/subsys/swatch /tmp/.swatch_script.*
else
echo "swatch is not starting"
fi
}
status() {
ls /var/run/swatch_*.pid 1> /dev/null 2>&1
if [ $? -eq 0 ]; then
echo -n "swatch (pid"
for pid in /var/run/swatch_*.pid
do
echo -n " `cat $pid`"
done
echo ") is running"
else
echo "swatch is stopped"
fi
}
case "$1" in
start) start;;
stop) stop;;
restart)stop && start;;
status) status;;
*) echo "Usage: swatch {start|stop|restart|status}" && exit 1;;
esac
exit $RET
service swatch start
chkconfig swatch on
以上です。