VPN接続・切断時に自動でルーティング追加・削除 (Windows)


Windowsから会社やら自宅鯖やらにVPN接続してるとインターネット回線が遅いよー! と思う人は多いかと思います。デフォルトゲートウェイがVPN接続に向くため、全てのパケットがVPNを通るようになるからです。できれば、必要なパケットだけをVPNに振り分けたいですね。VPN接続のIP詳細設定で「リモートネットワークでデフォルトゲートウェイを使用する」を切ればデフォルトゲートウェイは変更されませんが、VPNの向こうに別のネットワークセグメントがあったりするとそこにはアクセスできなくなります。そのセグメントへのルーティングがないからです。

ルーティングは route コマンドで書き換えることができますが、VPN接続していないときもVPNへのルーティングを有効にしていると、VPNとIPアドレスがかぶっているネットワークに入ったりすると不具合が出そう(ホテルLANや公衆無線LANがどんなIPアドレスを出してくるか分かったものではありません!)なので、できればVPN用ルーティングはVPN接続しているときだけ有効にしておきたいものです。

VPNに接続したときに自動でルーティングを書き換えたいというのはよくある要求だと思うのですが、日本語文献はなかなかない、もしくは環境ややり方が古いのですよね… 今回は、http://simpleverse.wordpress.com/2010/10/06/add-routes-on-vpn-connect-with-powershell-and-task-scheduler/ をもとに設定します。

この文書では、正しく接続できるVPN接続がすでに存在していることを前提に書かれてており、VPN接続の作り方そのものについては説明していません。また、Vista以降のWindows(タスクスケジューラのイベント時タスク実行機能を使います)とPowerShellを用意してください。PowerShellはWindows7には最初から入っていますが、Vistaには入っていませんので、http://tobysoft.net/wiki/index.php?PowerShell%2FWindows%20Vista%A4%CBPowerShell%20v2%A4%F2%A5%A4%A5%F3%A5%B9%A5%C8%A1%BC%A5%EB%A4%B9%A4%EB%CA%FD%CB%A1 を参考にして入れてください。あと、管理者権限で起動したPowerShellウィンドウで

Set-ExecutionPolicy RemoteSigned

するのも忘れずに。これをしておかないとPowerShellスクリプトファイルを実行できません。

まず、PowerShellスクリプトを作りましょう。最初の方にあるIPアドレスは貴方の環境に合わせて変更してください。下のスクリプトでは、

  • VPNに接続すると192.168.1.170~192.168.1.189のうち一つのIPアドレスをもらえる
  • VPN先ネットワーク(192.168.1.0/24)のさらに先に10.10.10.0/24,192.168.2.0/24,10.11.12.0/24という3つのネットワークセグメントがあるので、そこにもアクセスしたい

という設定になっています。

# ---------------------------------------------------------------------------------------
# Initial version: http://www.webboise.com/windows-powershell-script-for-adding-ip-routes-across-a-vpn/
# by Chris @ 30.9.2008
# ---------------------------------------------------------------------------------------
# Modified version: http://simpleverse.wordpress.com/2010/10/06/add-routes-on-vpn-connect-with-powershell-and-task-scheduler
# by Luka Ferle? @ 6.10.2010
# ---------------------------------------------------------------------------------------
# modified by kabbalah (http://erirun.net/), 2012-01-07
$OutputEncoding = [console]::OutputEncoding
# Configuration
# Route IP address
$ips = @("10.10.10.0", "192.168.2.0", "10.11.12.0")
# VPN connection IP
$vpnIP = "192.168.1.1[78][0-9]"
# delete route
foreach($ip in $ips) {
 $hasRoute = route print | findstr $ip
 if($hasRoute) {
 "Deleting route " + $ip
 route delete $ip
 }
}
$vpnip = ipconfig | findstr $vpnIP
if (!$vpnip) {
 "You do not have an IP address on the VPN"
 exit
}
$vpnip = $vpnip.Trim().Split(" ")
$bit = $vpnip.Length - 1
$vpnip = $vpnip[$bit]
foreach($ip in $ips) {
 "Adding route " + $ip
 route add $ip MASK 255.255.255.0 $vpnip
}

これに適当な名前をつけてどこかに保存します。ここでは D:\BIN\vpnroute.ps1 とします。

次に、このスクリプトをイベントと関連づけたタスクに設定します。イベントビューアのアプリケーションログを見てください。VPN接続をしたことがあるなら、RasClientの20225番で接続のイベントが、20226番で切断のイベントが記録されているはずです。この2種のイベントに対してタスクを設定します。今回は、接続・切断両方のイベントに対して先ほど作成したvpnroute.ps1を実行させるようにします。このスクリプトは「ルーティングを消す→VPN接続があったらルーティングを追加」という動きをするので、接続時と切断時の両方に使用できるのです。

該当イベントのどれか一つで右クリックして「このイベントにタスクを設定…」を選択します(20225番と20226番の2回行う必要があります)。作成ウィザードが出ますので、[操作]-[プログラムの開始]まで進めます。するとプログラムを指定する画面になりますので、プログラムに「powershell」、引数に「-NonInteractive -Command D:\BIN\vpnroute.ps1」と指定します。そして最後の完了画面で「[完了]をクリックしたときに、このタスクの[プロパティ]ダイアログを開く」をチェックしてウィザードを完了しましょう。

そうすると、タスクのプロパティが開きます。そのままではスクリプトが正しく動かないので、少々プロパティの変更が必要です。

  • 実行アカウントが管理者権限を使えるアカウントであることを確認し、「最上位の特権で実行する」にチェック。ルーティングの変更には管理者権限が必要です。
  • [条件]タブの[電源]セクションのチェックを全て外す。これをしておかないと、バッテリ運用時にスクリプトが動いてくれません。

これだけ変更したらOKで終了します。あとはVPN接続のIP詳細設定で「リモートネットワークでデフォルトゲートウェイを使用する」を切った状態で実際にVPN接続をしてみて、

  • 接続時に実際にルーティングが設定されているか
  • VPNホストにアクセスできるか
  • インターネットサイトにVPNを経由せずにアクセスできるか
  • 切断時に正しくルーティングが消えるか

を確認してください。

接続時・切断時にPowerShellのウインドウが出ますが、動作確認のためわざと残してあります。タスクのプロパティでPowerShellの起動引数に「-WindowStyle Hidden」を追加するとウィンドウは出なくなると思いますが、試していません。

また、もう一つの問題点として、スクリプトはRAS接続・切断に対して起動しますが、実はVPN接続でなくてもどのRAS接続(3G回線へのダイヤルアップなど)に対しても起動します。スクリプトが起動すると一瞬だけVPN接続へのルーティングが消えますが、実際にVPN接続があるかどうかをスクリプト側でipconfigを使用して判断してVPN接続があればまたルーティングを設定するので大きな問題は起きないのではないかと思います。

カテゴリーTips

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

*