OpenSSHでVPN

これは便利すぎる。しかもタダ。
http://www.unixuser.org/~euske/doc/openssh/openssh-vpn.html

OpenSSHはバージョン4以降ほとんどコンパイルをせず、パッケージに含まれているものをそのまま使うことが多かった。OpenSSLが安定してきて、セキュリティインシデントが発生しなくなってきた事も一因だが、単純に面倒になっただけでもある。

そんな理由もあって、OpenSSHは4.3からtun/tapデバイスを使ったトンネリングをサポートしていた事を今日まで知らなかったし、長らくの懸案だったChrootにも最近対応している事も同じく今日まで知らなかった。

OpenSSHでChrootだよ!これは本当に念願だったんだよ。
変なシェルを自作したり、おかげで妙な事もやった。

sftpとChrootDirectory
http://d.hatena.ne.jp/rougeref/20080414

実際にやろうと思ったらハマりどころがあるようだが、おそらく↑の情報でカバーされているだろうと思われる。


さて、本題のOpenSSHでVPNなんだけど、実は最初に提示したURLに全て書いてあるので、俺から補足することはほとんどなかったりする。ほぼ自動化出来ているわけだし。

PermitTunnel yes

これはデフォルトで no のようだから、変更した。

こんだけでは何なので、トラブル発生時の自動再接続スクリプトを書いてみた。
再接続なんて勝手にやってくんねーかな、って思って。

#!/bin/sh

PING_INTERVAL=1
PING_COUNT=3
PING_TARGET=192.168.0.1
PROC='ssh -w 0:0 warumono.jp.'

ping -c ${PING_COUNT} -i ${PING_INTERVAL} ${PING_TARGET} >/dev/null
RET=$?
if [ $RET -eq 0 ]; then
  D=`date "+%Y-%m-%d %H:%M:%S"`
  echo "${D} not bad"
  exit 0;
fi

while ps -ef  | grep "${PROC}" | grep -v grep >/dev/null
do
  D=`date +%Y-%m-%d %H:%M:%S`
  echo "$D killing ssh tunnel proc"
  ps -ef | grep "${PROC}" | grep -v grep | awk '{print $2}' | xargs kill -TERM >/dev/null
  sleep 1
done

$PROC 2>&1 >/dev/null &

D=`date +%Y-%m-%d %H:%M:%S`
echo "$D ssh tunnel proc restarted"

トンネル先の192.168.0.1に対して、1秒間隔で3回pingを打つ。失敗すると、pingはexitコード0以外で終了するので、次のwhileループに入る。ping成功なら"not bad"と言うことでそのまま終了。
whileループは、ssh -w コマンドが起動している限り真。一度これを落とすため、トンネル用のsshプロセスを探して kill -TERM で落とす。1秒まってまだ起動しているなら何度でも試す(という仕様は無限ループを生む可能性があり素人にはオススメしない)。無事プロセスが終了すれば、whileループからは抜ける。そして改めてトンネル用のsshプロセスを起動して終了する。

この監視/自動対応ツールは以下の状況を前提にしている。

  • VPNクライアント側のrootでcronにて起動(タイミングは任意)
  • VPNクライアント側rootユーザのid_rsa.pubはVPNサーバ側のauthorized_keysに登録済み、しかもforced-commandでVPNサーバ側のインタフェース設定やルーティング追加までを済ませてくれるようにしてある。
  • 必要に応じてiptablesを使ってフィルタしてみたりマスカレードしてみたり。

など?その他状況は最初のURLのとおりだ。

ちなみにこのVPN接続は、普通の会社で自宅と会社を繋ぐ目的等で勝手にやるとセキュリティポリシー違反になる事が容易に予想されるため、実施にあたってはネットワーク管理者の許可を得るなど、適切に利用すること。間違っても俺のせいにしないでね。