1 октября 2011 г. 17:23
Написал soar

VPN и маршрутизация под Windows

Безусловно, чаще всего VPN-подключения используются как туннель с маршрутом по-умолчанию, однако что делать, когда VPN служебный, и подключаться через него нужно только к определенному списку ресурсов? Хоть Windows и далеко до *nix-систем, с их возможностью настойки if-up/if-down скриптов, однако и здесь есть красивые варианты решения этой задачи. Один из них базируется на использовании встроеного планировщика заданий, который в 7-ой версии операционки, на мой взгляд, близок к идеалу.

Плохое решение - bat'ники

Заходя издалека, можно рассказать о простом и не очень красивом решении проблемы: всегда можно создать bat-файлы примерно следующего содержания для подключения и отключения VPN.

rem Подключение
rasdial "My VPN Connection" username *
route add bla-bla-bla
rem Отключение
rasdial "My VPN Connection" /disconnect
route add bla-bla-bla

Работать вполне будет, но мы ведь ходим подключать VPN красивой кнопочкой в трей-туле?

Хорошее решение - планировщик

Настройка планировщика

Признаюсь, я не помню каким был планировщик заданий в Windows XP, но судя по всему он был не очень хорош, т.к. для своих нужд я использовал выдернутый из дистрибутива Dr.Web тех времен Dr.Web Scheduler. От того еще большим было моё удивление, когда я увидел функционал и возможности шедуллера из Win-7. Любая задача здесь представляется в виде связки триггеров и действий, и, надо отдать должное Microsoft, настроек для этих триггеров, действий и условий по-настоящему много.

В нашем случае нам нужно поставить триггеры на подключение и отключение VPN (если при отключении не нужно восстанавливать специфические системные маршруты, то можно обойтись и одной задачей), и, в ответ на эти срабатывания, запускать bat-скрипт. Выглядеть это будет примерно так.


Всё то же самое (за исключением пары не очень значительных галочек) можно добавить всего одной командой в cmd:

schtasks /create /F /RL HIGHEST /TN "Маршруты для VPN" /TR "C:\vpnroutes.bat /connect" /SC ONEVENT /EC System /MO "*[System[Provider[@Name='Rasman'] and (Level=4 or Level=0) and (EventID=20267)]] and *[EventData[Data='My VPN Connection']]"

Для события на отключение (опять же, если оно необходимо), всё так же, за исключением идентификатора события и ключа для bat-скрипта:

schtasks /create /F /RL HIGHEST /TN "Маршруты для VPN (удаление)" /TR "C:\vpnroutes.bat /disconnect" /SC ONEVENT /EC System /MO "*[System[Provider[@Name='Rasman'] and (Level=4 or Level=0) and (EventID=20268)]] and *[EventData[Data='My VPN Connection']]"

Скрипт

Ну и наконец сам скрипт C:\vpnroutes.bat:

@echo off
rem ===========================================================================

rem Маршруты, которые будут добавлены при отключении VPN.
rem Если установлен маршрут по-умолчанию - обычно не нужны.
rem Формат: IP маска шлюз
rem route novpn: 10.0.0.0 255.0.0.0 172.16.0.1

rem Маршруты, которые будут добавлены при подключении VPN.
rem VPNIP заменяется на текущий адрес интерфейса.
rem формат: IP маска шлюз
rem route vpn: 10.0.0.0 255.0.0.0 VPNIP
rem route vpn: 192.168.0.0 255.255.0.0 VPNIP

rem Имя VPN-подключения
set vpnname=My VPN Connection

rem ===========================================================================

setlocal EnableDelayedExpansion
@set gw=

for /F "tokens=2" %%i in ('netsh interface ipv4 show addresses "%vpnname%" ^| findstr IP') do @set vpnip=%%i

if [%1]==[/connect] goto connect
if [%1]==[/disconnect] goto disconnect

echo Please select /connect or /disconnect option key!
rem pause
goto end

:connect
if "%vpnip%"=="" goto noip

for /F "tokens=4,5,6" %%i in ('type %0 ^| findstr "^rem.*route"') do route delete %%i mask %%j
for /F "tokens=4,5,6" %%i in ('type %0 ^| findstr "^rem.*route.*vpn"') do (
set gw=%gw%%%k
set gw=!gw:VPNIP=%vpnip%!
route add %%i mask %%j !gw!
)
goto end

:disconnect
for /F "tokens=4,5,6" %%i in ('type %0 ^| findstr "^rem.*route"') do route delete %%i mask %%j
for /F "tokens=4,5,6" %%i in ('type %0 ^| findstr "^rem.*route.*novpn"') do route add %%i mask %%j %%k
goto end

:noip
echo Can't set gateway IP, check your settings
goto end

:end
endlocal

rem end of file

Комментарии