監視が役立つか害になるかは、調査が何を区別できるか、何回連続で失敗したら行動を正当化できるか、その行動が再接続なのか切り替えなのか、という三つの条件で決まる。公開アドレスに ping を打つ cron の一行は、そのどれにもうまく答えない。正常なトンネルを再接続し、壊れたトンネルはそのままにし、しかもどちらも記録を残さない。残す価値のある設計は、この三つの選択を明示する。

調査こそが他のすべてを決める部分だ。

インターネットへの ping が実際に証明すること

公開リゾルバへの ping は、ローカルのインターネット経路が生きていることを示す。トンネルが通信を運んでいることは証明しないし、全トンネルのプロファイルでは ping 自体がトンネルを通るので、クライアントが今もパケットを転送していても、正常な応答と壊れたトンネルが同時に存在しうる。プロファイルが名前解決をトンネル経由で送るなら、DNS の失敗は切れた回線として読まれ、何も直せない再接続を始めてしまう。

誤りのどちらの向きも終了コードには現れない。 その信号の上に作られた監視は、cron の予定表を伴うコイン投げでしかない。

トンネルの向こう側に住むものを調べる

ip -brief addr show tun0
ip route get 10.100.20.10
nc -z -w3 10.100.20.10 443

内側から調べ、いちばん安い確認を先に行う。インターフェースがあればトンネルは上がっており、既知の内部アドレスへの経路を引けば通信はそこへ入り、向こう側のホストへの TCP 検査で何かが実際に応答していると分かる。echo 要求だけでは誤り、多くの内部ホストは TCP には気軽に応答するが ICMP は捨てるので、ping 頼みの監視は、止まったことのないトンネルを再接続し続ける。

調査には時間の上限を設け、終了状態を分けて持たせる。三十秒もぶら下がる調査は、遅れを内蔵した障害検知器に監視を変えてしまう。

一行とループのどちらかを選ぶ

* * * * * nc -z -w5 10.100.20.10 443 || myvpn reconnect

cron の項目は記憶を持たない一行で、余分な再接続に何のコストもないノート pc に向く。監視下のループはカウンタを保ち、何度か外した後にだけ動くので、不安定な回線が再接続の嵐を起こすのを防ぐ。いずれにせよ、クラッシュを生き延びてジャーナルに書くよう、スーパーバイザの下で動かす。どちらの版が短いかではなく、無駄な再接続が問題になるかで選ぶ。

failures=0
while sleep 30; do
  if nc -z -w5 10.100.20.10 443; then failures=0
  else failures=$((failures+1)); fi
  if [ $failures -ge 3 ]; then myvpn reconnect; failures=0; fi
done

そのループは窓あたりの割合ではなく、連続した失敗を数える。窓には時計と標本の記憶が要るし、手作りの監視の不具合はたいていその算術に住んでいる。

切り替えは別の判断だ

サーバーの切り替えは再接続とは違う。まず古い回線を切るのは、先がアドレスを握ったまま二つ目のクライアントが始まれば衝突するからだ。切り替える前に連続失敗を数え、試行に上限を置き、新しい回線が上がってから調べ直し、connect コマンドの終了状態は信じない。誤った設定がループで全サーバーを回るべきではない。

全トンネルの内側から VPN サーバー自身の公開アドレスを調べてはいけない。その確認は自分が試しているものに依存しており、検証すべき経路が消えていても成功を報告する。

どの調査が走り、何を返し、どんな行動が続いたかを記録する。その記録が、謎の再接続を診断できる事象に変える。

関連記事