やったこと
以前公開した記事の構成では、自宅サーバが落ちたときに、VPNに繋いでる端末がインターネットに接続できなくなります。
そうなると困るので、緊急用のVPNが自動で起動するようにしました。
忙しい人向け
やったことは、wgE(OCIから直接インターネットへ抜けるVPN)のconfファイルを用意し、以下のスクリプトをcronで定期実行するよう設定しただけです。
#!/bin/bash
TARGET="10.50.0.254"
PING_COUNT=3
TIMEOUT=2
WG_PRIMARY="wg-quick@wg0"
WG_EMERGENCY="wg-quick@wgE"
# wgE起動判定
if ! ping -I wg0 -c ${PING_COUNT} -W ${TIMEOUT} ${TARGET} > /dev/null 2>&1; then
if ! systemctl is-active --quiet ${WG_EMERGENCY}; then
# wg0経由でping通らない & wgE未起動なら wgE起動
logger "[wg-failover] ping failed. switching wg0 -> wgE"
systemctl stop ${WG_PRIMARY}
sleep 2
systemctl restart ${WG_EMERGENCY}
fi
fi
解説
後から修正したので、少しスクリプトの内容が違っています。
wgEの準備
基本的に、wg0の時と変わりません。
まずは、秘密鍵と公開鍵を作成します。
sudo wg genkey | tee private.key #秘密鍵を作成
#(秘密鍵がここに表示される)
sudo cat private.key | sudo wg pubkey | tee public.pub #秘密鍵に対応する公開鍵を作成
#(公開鍵がここに表示される)
次に、wgE.confを準備します。
sudo vi /etc/wireguard/wgE.conf
[Interface]
PrivateKey = [OCIのPrivateKey]
Address = 10.60.0.1/32
ListenPort = 51821
Table = 51821
PostUp = ip -4 rule add from 10.60.0.2/32 table 51821
PostUp = ip -4 route add 10.60.0.0/24 dev wgE
PostUp = iptables -t nat -A POSTROUTING -s 10.60.0.0/24 -o ens3 -j MASQUERADE
PostUp = iptables -A FORWARD -i wgE -o ens3 -j ACCEPT
PostUp = iptables -A FORWARD -i ens3 -o wgE -m state --state ESTABLISHED,RELATED -j ACCEPT
PostDown = ip -4 rule del from 10.60.0.2/32 table 51821
PostDown = ip -4 route del 10.60.0.0/24 dev wgE
PostDown = iptables -t nat -D POSTROUTING -s 10.60.0.0/24 -o ens3 -j MASQUERADE
PostDown = iptables -D FORWARD -i wgE -o ens3 -j ACCEPT
PostDown = iptables -D FORWARD -i ens3 -o wgE -m state --state ESTABLISHED,RELATED -j ACCEPT
[Peer]
PublicKey = [クライアントのPublicKey]
AllowedIPs = 10.60.0.2/32
起動スクリプトの作成
前述したスクリプトを作成します。
一応、スクリプト内に簡単なコメントは残していますが、もう少し詳しく一つ一つの処理を解説していきます。
TARGET="10.50.0.254"
PING_COUNT=3
TIMEOUT=2
WG_PRIMARY="wg-quick@wg0"
WG_EMERGENCY="wg-quick@wgE"
ここでは、各変数と変数に格納する値を指定しています。
# wgE起動判定
if ! ping -I wg0 -c ${PING_COUNT} -W ${TIMEOUT} ${TARGET} > /dev/null 2>&1; then
# ping通らなかったらwgE起動
logger "[wg-failover] ping failed. switching wg0 -> wgE"
systemctl stop ${WG_PRIMARY}
sleep 2
systemctl restart ${WG_EMERGENCY}
fi
ここについては、もう少し分解して解説します。
if ! ping -I wg0 -c ${PING_COUNT} -W ${TIMEOUT} ${TARGET} > /dev/null 2>&1; then
まず、wg0もしくは自宅サーバが落ちていないか確認します。
確認方法は、wg0経由で自宅サーバにpingを打って応答があるかを見るというシンプルな方法を取ってます。
もし、ここでpingが通らなければ条件を満たすため、次の処理に移っていきます。
logger "[wg-failover] ping failed. switching wg0 -> wgE"
wg0からwgEに移行することをログに記録します。
systemctl stop ${WG_PRIMARY}
sleep 2
systemctl restart ${WG_EMERGENCY}
先にwg0を止める処理を開始し、少し待った後、wgEを起動します。
自動起動の設定
作成したスクリプトを/usr/local/binに保存しておきます。
スクリプトのファイル名は任意ですが、本記事では例としてwg_failover.shとしておきます。
その後、ログインユーザーをrootに切り替え、以下コマンドでcronに設定します。
crontab -e
* * * * * sh /usr/local/bin/wg_failover.sh
上記の通り、実行時間の指定なしの場合、指定したコマンドは毎分実行されます。
そこまで頻繁に実行したくない場合は、適宜cronに登録する実行時間を変更してください。
テスト
以下コマンドでwg0を止めて、しばらくした後、wgEが起動していれば問題なく動作しています。
wg-quick down wg0
まとめ
今回、wg0でインターネットに繋げなくなった時の対策としてwgEを作成し、以下をシェルスクリプトとcronで自動化しました。
- wg0が繋がらなくなった判定
- wgEの起動
これで、仮に自宅のサーバが万が一落ちてしまっても、ある程度安心して自前のVPN回線を使い続けることができるようになったと思います。
追記
上記までのスクリプトだと、wgEを立ち上げた後も再起動コマンドを連打することになるので、wgEが立ち上がっていないかも条件に追加しました。
if ! systemctl is-active --quiet ${WG_EMERGENCY}; thenの部分を追加したので、wgEが起動していない状態であれば、次の処理に進みます。
忙しい人向けには、修正版のスクリプトを記載しています。