2012/02/20

[余談] MacOS X のVPN接続をコマンドラインから実行する

仮想化とは関係ないけど、余談で。

MacOS X では VPN接続機能が用意されており、システム環境設定の「ネットワーク」にて、左下の「+」ボタンを押すことで設定が可能になる。標準で用意されているのは、L2TP over IPsec, PPTP, Cisco IPSec の三つだ (Lion の場合)

それぞれを選択、アカウントなど適宜情報を記入することで L2で VPNを張ることができる。

ただ、その接続がシステム環境設定を開いて該当するネットワーク設定を選択、「接続」ボタンを押すか、メニューバーにVPN設定のアイコンをあらかじめ表示させておき、そこから選ぶか、になる。

そう頻繁にVPNを張らない人や、MacBookAir を利用しててメニューバーの横幅が足りないのであまりアイコンを表示させたくない人からすれば、一々システム環境を開くのは面倒だ。

そこで、ターミナルのコマンドラインから VPNを張れないかを調べてみた。
とりあえず、ざっと調べた限りではそれっぽいコマンドは見つけられなかった。のでスクリプトで対応させることとした。

#!/bin/sh
DoScript() {
/usr/bin/osascript << __EOF__
tell application "System Events"
   tell current location of network preferences
       set VPNservice to service "$2"
       if exists VPNservice then $1 VPNservice
   end tell
end tell
__EOF__
    return 0 ;
}
case $1 in
"connect")
    DoScript "connect" $2 ;;
"disconnect")
    DoScript "disconnect" $2 ;;
esac


DoScript 関数がこのシェルスクリプトの実体で、osascript にヒアドキュメントで AppleScript を流し込み、実行している。

tell application "System Events" により SystemEvents に対して指示を送り、さらにその中で「current location of network preferences」、つまり現在のネットワーク設定に指示を送っている。
OS X をあまり使われてない方には馴染みのないことだが、OS X では「場所」ないしは「ネットワーク環境」という名前で、使用するネットワークインターフェイスやインターフェイス冠の優先順位、IPアドレス、DNS、デフォルトルート、プロクシーなどの設定をまとめて切り替えることができる。ネットワーク管理をやってた頃はいく先々ごとにこのネットワーク環境を作り、ついたら切り替えることでたとえ固定IPアドレスや特別なプロクシの設定が必要でも一気に切り替えられたので便利なのだ。
ThinkPad など一部のベンダーのPCにも同様の機能はあるが、OS標準でないため細かいところで面倒だったのと、やはりUNIXコマンドが標準搭載なのもあり Macのノートは私の回りのネットワーク管理者にとっては必須のデバイスであった。

何を送ってるかというと $2 にはVPNサービス名が入り、$1 には connect か disconnect が入るため、set VPNservice to service "何らかのVPNサービス名" で、VPNService という変数にサービス名を突っ込む。

それから、if exist VPNservice でそのサービス名に該当する設定があるかを確認、あれば $2, つまり connect(接続)もしくは disconnect(切断)を行う。

case でくるんでるのは、コマンドラインからは connect でも start でもよくしようとして、途中で面倒になったからそうなっているだけだ。( "connect") を "connect"|"start") とかするだけなのだが)

さて、このスクリプトを vpnc という名前でパスの通るところに保存、実行フラグを立てる。システム環境設定のネットワークから「MyOffice」というVPN設定を作った後

$ vpnc connect MyOffice

とコマンドを叩けば、接続される訳だ。
なお、厳密には「接続を指示する」ところでこのスクリプトは終了してしまう。VPNの接続確立までに時間がかかる場合は、そのぶん待った方がいい。

私は接続先に既知のサーバがあるので、ちょっと待ってから ping を打って繋がってる確認した後に利用するようにしている。

もう少し頑張ればVPN明があるかをチェックしてなければエラーを返すとか、色々改善もできるだろうが私の用途ではこれで十分なのでそこから直していない。