自宅サーバのSSHにログインしたらIPアドレスと位置情報をLINE通知する
こんにちは(๑╹ω╹๑ )
久しぶりに自宅サーバに関連する記事を書きます!
(前回:入門自宅サーバ
序盤は前回以降に新しく構築した環境を紹介します!
成果物
日本ならregionに都道府県、cityに市区町村情報が入っています。
きっかけ
- fail2banの環境構築をしているがsshにログインしたIPアドレス情報は念の為通知させておきたい
- ログインするのは自分だけ(のはず?)なので通知で埋もれることは無い(はず?)
新しく構築した環境
弐号機とスイッチングハブを調達
手元のEthernetポートが足りなくなってきたため近いうちにもう一つ調達予定。
Proxmox VEで宅内クラスタ構築
物理ノード2台構成でクラスタ構築をしました
(スナップショット取得するのが案外楽しい
環境構築用のスクリプト群を実装
今日紹介するスクリプトはこちらにあります。
init-root_user.shをコピペで実行するとgit等のパッケージを諸々インストールしながら、
同リポジトリをその場でcloneして実行権限付与しながら一通りの環境構築をします。
SSHにログインしたらLINE通知する
本題に入っていきます!
事前準備物
- 自宅サーバ
- LINE NotifyのAPIキー
- jqコマンド
環境
# rootへの直ログインが無効になっている
cat /etc/ssh/sshd_config | grep "^PermitRootLogin"
# => PermitRootLogin no
# ログインshellはbash
echo ${SHELL};
# => /bin/bash
ローカルネットワークの設定
ホスト部は末尾8ビット。
(ローカルネットワーク内のクライアントからSSHログインされたことを判定するために利用
名称 | 設定 |
---|---|
IPアドレス | 192.168.0.1 |
サブネット | 255.255.255.0 |
グローバルIPを記録しておく
ローカルネットワーク内のサーバへインターネットゲートウェイ経由でアクセスした場合の通知を除外するために利用します。
curl -s ifconfig.io > /tmp/global_ipaddress;
フックとなるスクリプト
下記のスクリプトを ~
に notify_to_line_on_login_shell.sh
という名称で設置。
#!/bin/sh
line_notify(){
referrer_ipaddress=${!1};
country=${!2};
region=${!3};
city=${!4};
message="shellにログインしました
ip_address:${referrer_ipaddress}
country:${country}
region:${region}
city:${city}";
curl "https://notify-api.line.me/api/notify" \
-s \
-XPOST \
--header "Authorization: Bearer ${LINE_ACCESS_TOKEN}" \
--form "message=${message}" \
> /dev/null;
};
isLocalNetworkReffered(){
referrer_ipaddress=${!1};
if [ "`echo "${referrer_ipaddress}" | grep "192.168.0"`" ]; then
return 1;
else
return 0;
fi
}
isSameGlobalIpAddress(){
referrer_ipaddress=${!1};
global_ipaddress=`cat /tmp/global_ipaddress`;
if [ ${referrer_ipaddress} == ${global_ipaddress} ]; then
return 1;
else
return 0;
fi
}
record_last_referrer_ipaddress(){
last_referrer_ipaddress=${!1};
echo ${last_referrer_ipaddress} > /tmp/referrer_ipaddress;
};
referrer_ipaddress=`echo ${SSH_CLIENT} | cut -f1 -d' '`;
last_referrer_ipaddress=`cat /tmp/referrer_ipaddress`;
# 最後にアクセスしたリファラIPアドレスの場合
if [ ${referrer_ipaddress} == ${last_referrer_ipaddress} ]; then
exit;
fi
isLocalNetworkReffered referrer_ipaddress;
# ローカルネットワーク経由のログインの場合
if [ ${?} -eq 1 ]; then
exit;
fi
isSameGlobalIpAddress referrer_ipaddress;
# ローカルネットワーク内のサーバにインターネットゲートウェイ経由でアクセスしている場合
if [ ${?} -eq 1 ]; then
exit;
fi
# アクセス元のIPアドレス情報記録
curl -s http://ip-api.com/json/${referrer_ipaddress}?lang=ja > /tmp/referrer_ipaddress_info.json
country=`cat /tmp/referrer_ipaddress_info.json | jq .country | sed -e 's/"//g'`
regionName=`cat /tmp/referrer_ipaddress_info.json | jq .regionName | sed -e 's/"//g'`
city=`cat /tmp/referrer_ipaddress_info.json | jq .city | sed -e 's/"//g'`
# shellにログインしたIPアドレス情報をLINEに通知する
line_notify referrer_ipaddress country regionName city;
# リファラIPアドレスを記録する
record_last_referrer_ipaddress referrer_ipaddress;
exit;
通知を除外するルール
- ローカルネットワーク内からのSSHログイン
- 最後にSSHへログインした時と同一のIPアドレス
- ローカルネットワーク内のクライアントだがインターネットゲートウェイ経由でのSSHログイン
リファラIPのgeo location情報の取得について
ip-apiを利用しています。
(無料プランの場合はAPIキーは不要ですが、1分間に最大45回のリクエスト、SSL通信が利用できない等の制限があります。
curl -s http://ip-api.com/json/${referrer_ipaddress}?lang=ja
以下がAPIドキュメント
SSHログイン時に発火させる
SSHログイン時に発火させるために /etc/ssh/sshrc
に上記までのスクリプトを実行する記述をします。
.bashrc
ファイルに記述してもフック可能ですが、
下記の事象でもフックされてしまうため /etc/ssh/sshrc
に記述します。
sshログイン => rootユーザにログイン => rootユーザからログアウト
環境変数の LINE_ACCESS_TOKEN
はスクリプト実行前に読み込まれている必要があります。
echo "export LINE_ACCESS_TOKEN=アクセストークン
~/notify_to_line_on_login_shell.sh" >> /etc/ssh/sshrc
さいごに
沼の底が見えない。。。
Discussion