ラズパイVPNのログ監視:VPN接続毎にLINEへ通知して不審なアクセスを検知する

Raspberry Pi(ラズパイ)
Photo by Markus Spiske on Unsplash
スポンサーリンク

以前構築したRaspberryPi VPNなんですが、やっぱり外部に公開する以上、多少の監視はしておかないとなと思っていまして、今回は導入編として“検知”機能を組み込んでみたいと思います。

またこちらでRaspberryPiに公開鍵認証をかけるやり方も記載していますので、こちらもどうぞ。

全体構成

大まかな構成としてはこんな感じにする予定です。SoftetherVPNのサーバログを監視して、接続ログ(接続成功、切断および認証エラー)を検知したら、LINEで通知するみたいな構成です。正直メールでも良かったんですが、LINEとの連携の方が今後面白そうだし、Apple Watchに通知が来るのも面白そうかなと思ってます。

構築手順

今回の構築手順は大きく二段階で構成されます。IFTTT側での設定作業と、RaspberryPi側でのプログラミング作業。コード自体は単なる通知なので、そんなに長くないですが、そのうち”検知”の次の段階である、”プロテクション”になるともう少しコードを考えないとダメかもしれませんね。

因みにRaspberryPiでの既にSoftEtherVPNがインストールされていることが前提になりますので、未インストールの場合は以下の記事を参考にしてください。

IFTTTでLINE通知が出来るようにする

IFTTTの登録

先ずはIFTTT自体の登録が必要ですね。既にIFTTTに登録済みの方は読み飛ばしてください。https://ifttt.comにアクセスして、右上のサインアップボタンから登録します。

IFTTTでWebhooksアプレットの作成

IFTTTアカウントが作成し終わったら、次にWebhooksというアプレットを使用します。今回の構築で初めて知ったのですが、これはWeb APIを提供してくれるAPI Gatewayのようなもので、こいつを使用することでトリガー用のURLを作成してくれます。SlacksとかMicrosoft Teamsとかとシステム連携する時なども使うこともあるそうで、既に割とメジャーなサービスだったようです。このアプレットの作成はhttps://ifttt.com/maker_webhooksから作成できます。

ここで通知先のURLを確認します。上で説明したようにこのURLが自分用のトリガーWeb APIになるようなイメージです。~~~use/以下のものをどこかにコピーしておいてください。このキーを後のステップでシェルに組み込みますので。

因みに上の画像ではマスクしてしまっていますが、実際にはdXXXXxxq-QQQQ_ZZZZZVVVVのような文字列になっています。

IFTTT~LINE連携登録

次はIFTTTと自分のLINEアカウントを連携してあげる必要があります。https://ifttt.com/lineをクリックすると以下のような画面が出てきますので、同意して連携するをクリック。

IFTTTでLINEアプレットの作成

ここまで出来たら、あとは上で作成したWebhooksとLINEアプレット作って、IFTTTのレシピを作って上げます。以下の URLでアプレットを作成します。

Get Started - IFTTT
Sign up for a free IFTTT account to connect Google, Alexa, Twitter, Instagram, Fitbit, Slack, and hundreds more of your favorite apps and devices.

先ずはトリガーを決めて上げます。”this”部分をクリックして

Webhooksを検索して、選択します。自分で探してもいいですが、検索した方が早かったですね。

Webhooksで選択できるトリガーはこれしかないので、”Receive a web request”をクリックして適当なEvent Nameを付けておきます。シェルに組み込む時にこ“Event Name”を使いますので、アルファベットかつ空白なしにしておいてください。

次は、”that”の部分です。トリガーが発生した場合に、今度はLINEを通知するというレシピを作って上げます。

同じようにLINEを検索して、選択します。

LINEアプレットも、選択できる動作は”Send message”しかありませんので、これを選択して以下のような感じにしていきます。Message部分でどういうフォーマットでメッセージを受け取りたいかを編集することが出来ます。この場合、引数として受け取るあたいは3つまで(Value 1, Value 2, Value 3)として、各メッセージは改行して表示するようにしてあげます。

因みにRecipent部分をプルダウンすると、既存LINEグループや個人を指定することも出来ます

これでIFTTTのレシピは完成となります。次の画面でFinishをクリックしてIFTTT側の操作はおしまいとなります。

RaspberryPiでSwatchを用いてログを監視し、LINE通知シェルを呼び出す

ここからはRaspberryPi側での処理になりますので、RaspberryPiにSSH接続して以下の作業を実施してください。勿論コンソールからのターミナルでもいいですが。

Swatchのインストール

先ずはSwatchのインスールになります。”スウォッチ”と聞くと、時計のブランドのように聞こえてしまうんですが、こちらは”Simple Log Watcher”の意味らしいですね。”L”はどこに行ったんだとかいうツッコミは置いておいて。インストール自体は、debian系ですので、いつものapt-getコマンド実施します。インストールフォルダは特に指定しなくても勝手にどこかにインストールしておいてくれます。

またここで構成ファイル用のフォルダは別で作成してます。

$ sudo apt-get install swatch

#swatch用の構成フォルダを作成しておく
$ sudo mkdir /usr/local/vpnswatch

Swatchがインストール完了したあとは、制御コマンドシェルを作成します。ここでVPNサーバログ、つまりSoftEtherVPNのserver_logを監視するように記述します。こいつを後ほどデーモンサービス化します。

因みにSwatchの基本的なコマンドレファレンスは、”swatch -c ‘コンフィグファイル’ -t ‘ログファイル'”になります。

$ sudo vim /usr/local/vpnswatch/vpnswatch

#!/bin/bash

VPNDIR=/usr/local/vpnserver
SWATCHDIR=/usr/local/vpnswatch
SWATCHRC=${SWATCHDIR}/vpnswatchrc
PIDFILE=${SWATCHDIR}/.vpnswatch.pid

LOGDIR=${VPNDIR}/server_log
LOG=${LOGDIR}/vpn_`date '+%Y%m%d'`.log

# ログファイルが存在しなければ監視しない
if [ ! -e ${LOG} ]
then
  echo "vpnswatch not found logfile : ${LOG}"
  exit 0
fi

start() {
  # Start daemons.
  ls ${PIDFILE} > /dev/null 2>&1
  if [ $? -ne 0 ]
  then
    echo "Starting vpnswatch"
    /usr/bin/swatch  
      --config-file ${SWATCHRC}  
      --script-dir  ${SWATCHDIR} 
      --pid-file    ${PIDFILE}   
      --tail-file   ${LOG}       
      --daemon
    RETVAL=$?
    return $RETVAL
  else
    echo "vpnswatch is already started"
  fi
}

stop() {
  # Stop daemons.
  ls ${PIDFILE} > /dev/null 2>&1
  if [ $? -eq 0 ]
  then
    echo "Shutting down vpnswatch"
    kill $(cat ${PIDFILE})
    rm -f ${PIDFILE}
    return 0
  else
    echo "vpnswatch is not running"
  fi
}

case "$1" in
  start)
    start
    ;;
  stop)
    stop
    ;;
  restart)
    stop
    start
    ;;
  *)
    echo "Usage: vpnswatch {start|stop|restart}"
    exit 1
esac

exit 0


Swatchのコンフィグファイルの作成

次にSwatchが何をログから読み取るのかを設定します。ここでは”watchfor”コマンドを使っています。watchforコマンドの使い方は、

watchfor /正規表現/
アクション1
アクション2
・・・・

の書き方になります。シェルなどを実行させたい場合はexecコマンド書いた上で記述します。因みにpipeコマンドでログ自体をシェルに渡すことでもう少しスマートな感じに通知することも出来そうなんですが、今回はとりあえずシンプルに作っています。

$ sudo vim /usr/local/vpnswatch/vpnswatchrc

# swatch で vpnserver のログを監視する

# 通信を開始したら通知
watchfor /[HUB.* セッション .*: VPN Client の詳細:/
    exec /usr/local/vpnswatch/LINE.sh HomeVPN_Connected 

watchfor /[HUB.* Session .*: VPN Client details:/
    exec /usr/local/vpnswatch/LINE.sh HomeVPN_Connected

# 通信を終了したら通知
watchfor /[HUB.* セッション .*: セッションが終了しました/
    exec /usr/local/vpnswatch/LINE.sh HomeVPN_Disconnected

watchfor /[HUB.* Session .*: The session has been terminated/
    exec /usr/local/vpnswatch/LINE.sh HomeVPN_Disconnected

# ユーザ認証失敗したら(60秒間に3回間違えたら)通知
watchfor /[HUB.* コネクション .*: ユーザー認証に失敗/
    exec /usr/local/vpnswatch/LINE.sh HomeVPN_Auth_Failed
    threshold track_by=/[HUB.* コネクション .*: ユーザー認証に失敗/,type=both,count=3,seconds=60

watchfor /[HUB.* Connection .*: User authentication failed/
    exec /usr/local/vpnswatch/LINE.sh HomeVPN_Auth_Failed
    threshold track_by=/[HUB.* Connection .*: User authentication failed/,type=both,count=3,seconds=60

セッションが開始・終了・認証失敗した場合に、それぞれHomeVPN_Connected/HomeVPN_Disconnected/HomeVPN_Auth_Failedの通知が行くように設定しています。個人的にはここに接続IPアドレスとかを書きたいところ何ですが、pipeコマンドの使い方がまだよくわかっておらず、またいつかここは改修したいですね。

LINE通知シェルを作成する

ここでLINE通知シェルを作成します。前述のコンフィグファイルでは既に指定しちゃいましたが、内容としては以下のような感じに作成しました。気をつけなければならないのは、“EVENTNAME”“YOUR_KEY”ですね。

“EVENTNAME”部分は、Webhooksアプレットで指定したEvent Nameを使用します。今回の場合は、”raspberry_pi”を記入。そして”YOUR_KEY”部分は、WebhooksのAPIキーであるdXXXXxxq-QQQQ_ZZZZZVVVVのような文字列ですね。

Json形式でPostする形になっており、Value 1/Value 2/Value 3に、3つの引数を割り当てています。ただし今回は引数を実質的には1つしか使用していません。

$ sudo vim /usr/local/vpnswatch/LINE.sh

#!/bin/bash

URL="https://maker.ifttt.com/trigger"
EVENTNAME="raspberry_pi"
YOUR_KEY="自分のWebhooksのKey"

WEBHOOKSURL="${URL}/${EVENTNAME}/with/key/${YOUR_KEY}"

curl -X POST -H "Content-Type: application/json" -d 
     '{"value1":"'$1'","value2":"'$2'","value3":"'$3'"}' 
         ${WEBHOOKSURL}

echo
exit 0

このシェルが作成できたら、試しに上記コマンドだけ実行してあげると自分のスマホにLINE Notifyが行っているはずです。もし行っていないようであれば、”EVENTNAME”、”YOUR_KEY”の記載が間違えている可能性があるので、確認してみてください。

incronのインストール

次にincronのインストールを実施します。こいつは何かというと、ファイルが作成、更新、削除したタイミングをトリガーとして、コマンドを実行してくれるもの何ですが、こいつが何故必要かというと、今回作成しているvpnswatch自体は、実行された日付のログファイルを監視するように起動されています。なので、そのままの状態であると、毎回手動でvpnswatchを再起動をかけて上げないとなりません。

正直crontabでもいいのかなとも思ったんですが、incronの方がスマートかつ、今後他にも使えそうな気がしたので、こちらを使うようにしています。インストール自体は、apt-getコマンドでおしまいです。

$ sudo apt-get install incron

そしてincronの起動ルールを設定します。コマンドの使い方はcrontabと同じような感じで使えますが、ちょっと困るのがnanoベースの編集なんですよね。正直nanoの使い方はあまり知らないので、少し苦手です。ともかく以下のルールを作成します。「server_logのフォルダに新しいファイルが作成されたら、vpnswatchを再起動する」と。

$ sudo incrontab -e
/usr/local/vpnserver/server_log IN_CREATE /usr/local/vpnswatch/vpnswatch restart

因みにこのコマンドが私の環境では、”root”で認証拒否されてしまいました。その場合は、以下のコマンドでincronをrootで使えるように指定して上げましょう。

$ sudo vim /etc/incron.allow
root

これでできるようになっているはずです。

その後、incronに今回記載したルールを読み込みさせて上げてからサービスの自動起動化を設定しておしまいです。

# ルールの読み込み
$ sudo incrontab -d

# 起動ルールの確認
$ sudo incrontab -l

# サービスの自動起動
$ sudo service incron start
$ sudo update-rc.d incron enable


ログ監視のサービス化

最後にvpnswatchのサービスデーモン化を作成します。

$ sudo vim /usr/lib/systemd/system/vpnswatch.service

[Unit]
Description=SoftEther VPN Server Log Simple Watch
After=vpnserver.service

[Service]
Type=forking
ExecStart=/usr/local/vpnswatch/vpnswatch start
ExecStop=/usr/local/vpnswatch/vpnswatch stop

[Install]
WantedBy=multi-user.target

因みにサービスのデーモン化で使用している今回のinitの設定は、/usr/lib/systemd/system/と/etc/systemd/system/のディレクトリ下に存在しているのですが、基本的に同名の設定ファイルがある場合には、/etc/systemd/system/のファイルが優先となります。使い方としては/usr/lib/systemd/system/には、システム標準の設定を配置しておき、システム管理者が設定変更する場合は、/etc/systemd/systemにファイルをコピーした上で修正をするのが、正しいやり方のようです。

今回は参照した手順では、/usr/lib/systemd/system/を使用していたのでそのままにしています。

$ sudo systemctl daemon-reload
$ sudo systemctl enable vpnswatch
$ sudo systemctl start  vpnswatch

これで全ての手順は完了となります。

起動確認

PCもしくは、スマホからRaspberryPiのVPNを接続して、数秒後にLINEに以下のような通知が来ていれば成功です。

因みにApple watchではこんな感じで通知が来るようになりますので、これでVPN接続されたらすぐに自分の腕がブルっとするので、怪しい接続を直後に検知することができます。

これで全ての作業が完了になります。途中watchforの記述を変えてあげることで、監視ログを変えたり、動作を変更することができるので、色々と試してみると面白いかもしれません。また個人的にはpipeを使って、IPアドレスまでの検知や、不審なIPをブロックするなどと行ったこともいつかしたいなと思います。

ではこの辺で。

Raspberry Pi(ラズパイ)
スポンサーリンク
スポンサーリンク
スポンサーリンク
\この記事が役に立ったらシェアしよう/
DIGILINE (デジライン)

Comments

  1. […] RaspberryPi VPNのログ監視:VPN接続毎にLINEへ通知して不審なアクセスを検知する […]

  2. shin より:

    TKさん

    早速のご教示、ありがとうございました。
    無事LINEにメッセージが飛んできました。
    お礼かたがたご報告まで。

  3. shin より:

    初めまして、shin と申します。
    ひかり電話を外で受けるため、RaspberryPiにSoftEtherVPNを導入し運用しております。
    ログ監視の必要性を感じこのサイトにたどり着きました。
    記事中、ログ監視のサービス化の件で[最後にvpnswatchのサービスデーモン化を作成します。]とあり
    /usr/lib/systemd/system/にvpnswatch.serviceを作成していますが、ディレクトリ /usr/lib/systemd/system/ はありませんとはじかれます。 /usr/lib/systemd/の下に /system ディレクトリを作成しなければいけないのですか。/lib/systemd/の下には /systemディレクトリは存在します。/etc/systemd の下にも /systemディレクトリが存在します。これらの間違えじゃないですよね。Linuxは始めたばかりで分からに事だらけです。
    どうかご教示いただければ幸いです。よろしくお願いいたします。

    • TK より:

      shinさん

      コメントありがとうございます。
      ワタシもあまり意識してなかったのですが、今回少し調べて見たところ、結論としては/usr/lib/systemd/system/と/etc/systemd/systemのどちらのディレクトリでサービスファイルを作って問題ありません。
      記事内でも追記していますが、/usr/lib/systemdがシステム標準で使用するinitファイル、/etc/systemdで使うものが管理者が個別に作成するもののようです。
      今回はワタシも参照していたものは/usr/lib/systemdだったのでそうしていますが、/etc/systemdでも問題なく動くと思います。

      Linuxが少しでもいじれるようになると楽しいですよね。ワタシもまだまだ勉強中ですが、一緒に頑張りましょう^^

スポンサーリンク
こちらの記事も読まれています
スポンサーリンク

この記事を書いた人

シニアモバイルシステムコンサルタント。エンジニア兼ガジェットブロガーをやっています。自宅をスマートホーム化させたり、デスク周りのガジェット、生活家電を中心にレビューしており、またお得で便利なサービスなども紹介しています。
レビュー依頼などはお問合せからお願いします。

\フォローする/
タイトルとURLをコピーしました