OpenVPN の接続・切断時に Slack に通知する

この記事では, OpenVPN サーバーの設定を行うことで, OpenVPN のクライアントがサーバーに接続・切断した際に, Slack に通知を送る方法を紹介します. 接続・切断時に任意のスクリプトを実行することができるので, Slack 通知以外にも活用できるはずです.

環境

今回の記事で利用した環境は以下の通りです.

  • Debian 8 amd64
  • OpenVPN 2.3.4
  • curl 7.38.0

接続・切断時に処理を実行する

OpenVPN のサーバーの設定項目に --client-connect--client-disconnected があり, それぞれクライアントがサーバーに接続・切断した際に実行するコマンドを指定することが出来ます. 詳細な説明は man page に書かれています:

–client-connect cmd
Run command cmd on client connection.
cmd consists of a path to script (or executable program), optionally followed by arguments. The path and arguments may be single- or double-quoted and/or escaped using a backslash, and should be separated by one or more spaces.

–client-disconnect cmd
Like –client-connect but called on client instance shutdown. Will not be called unless the –client-connect script and plugins (if defined) were previously called on this instance with successful (0) status returns.

また, OpenVPN には実行可能な外部のプログラムやスクリプトを指定する --script-security という設定項目があるため, これも適切に設定する必要があります. curl などのプログラムを実行するには, デフォルトの 1 から 2 に変更する必要があります. 以下も man page からの引用です:

–script-security level
This directive offers policy-level control over OpenVPN’s usage of external programs and scripts. Lower level values are more restrictive, higher values are more permissive. Settings for level:
0 — Strictly no calling of external programs.
1 — (Default) Only call built-in executables such as ifconfig, ip, route, or netsh.
2 — Allow calling of built-in executables and user-defined scripts.
3 — Allow passwords to be passed to scripts via environmental variables (potentially unsafe).

Slack に通知する

Slack への通知は Slack の incoming webhook を curl で叩くことで実現できます. まずこちらから Integration を作成して Webhook URL を取得しておきます.

次に, 接続時に実行するスクリプトと, 切断時に実行するスクリプトをそれぞれ connected.shdisconnected.sh として作成しておきます. (Webhook URL は適宜設定して下さい.)

connected.sh:

#!/bin/bash
curl -X POST --silent --data-urlencode "payload={\"channel\": \"#openvpn\", \"username\": \"OpenVPN (Connected)\", \"text\": \"Connected\nName: $common_name\nGlobal IP: $untrusted_ip\nLocal IP: $ifconfig_pool_remote_ip\", \"icon_emoji\": \":airplane_departure:\"}" https://hooks.slack.com/services/......

disconnected.sh:

#!/bin/bash
curl -X POST --silent --data-urlencode "payload={\"channel\": \"#openvpn\", \"username\": \"OpenVPN (Disconnected)\", \"text\": \"Disconnected\nName: $common_name\nGlobal IP: $untrusted_ip\nLocal IP: $ifconfig_pool_remote_ip\", \"icon_emoji\": \":airplane_arriving:\"}" https://hooks.slack.com/services/......

これらのスクリプトに $ sudo chmod +x connected.sh disconnected.sh などとして実行権限を与えておきます.

スクリプトの中では環境変数から情報を取得することが出来ます. 例えば $common_name でクライアントの証明書の Common Name, $untrusted_ip でクライアントの IP アドレス, $ifconfig_pool_remote_ip でクライアントの VPN での IP アドレスが取得できます. その他の環境変数については man page を参照して下さい.

次に OpenVPN のサーバーの設定に以下を追記し, クライアントの接続・切断時に先ほど作成したスクリプトを実行するようにします.

script-security 2
client-connect connected.sh
client-disconnect disconnected.sh

OpenVPN サーバーを再起動して, 正しく動作するかテストします. 正しく動作すると以下のようになります.

OpenVPN Slack

正しく動作していない場合は OpenVPN サーバーのログを確認して下さい.