Powershell скрипт создания L2TP/IPsec VPN подключения на Windows

📅
⏱️ 3 min read
#windows-server #windows #powershell #vpn

PowerShell скрипт для автоматического подключения к L2TP/IPsec VPN между Windows и MikroTik.

Если VPN-подключения еще нет - создаст, подключится, настроит маршруты и проверит, что всё реально работает, а не просто горит зеленым.

Поддерживает L2TP и IKEv2, логирует всё подряд и умеет диагностировать косяки. Все пароли, IP-адреса и Pre-Shared Key вынесены в переменные в начале скрипта - меняй на свои и запускай.

Идеально заходит для автоматического коннекта при загрузке сервера или в связке с мониторингом, чтобы VPN сам поднимался когда отвалится.

# ============================================
# КОНФИГУРАЦИЯ - измените под свои параметры
# ============================================
$VPN_NAME = "MikroTik-Domain"
$VPN_SERVER = "vpn.example.com"
$PSK = "YourPreSharedKey123!"
$VPN_USERNAME = "vpnuser"
$VPN_PASSWORD = "VpnPassword2025!"
$TARGET_NETWORK = "192.168.10.0"
$NETWORK_MASK = "255.255.255.0"
$VPN_GATEWAY = "172.16.67.1"
$TEST_IP = "192.168.10.1"
$LOG_FILE = "C:\Scripts\IPsec_VPN_Connection.log"
$NETWORK_LOAD_DELAY = 15
$CONNECTION_DELAY = 10
$PING_DELAY = 3
$VPN_CONNECTION_TYPE = "L2TP"  # L2TP или IKEv2

# ============================================
# ОСНОВНОЙ КОД
# ============================================

# Логирование
$timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
Write-Output "[$timestamp] Запуск скрипта автоподключения IPsec VPN" | Out-File $LOG_FILE -Append

# Ждём загрузки сетевых служб
Start-Sleep -Seconds $NETWORK_LOAD_DELAY
Write-Output "[$timestamp] Ожидание завершено" | Out-File $LOG_FILE -Append

# Проверяем существование VPN подключения
$vpnConnection = Get-VpnConnection -Name $VPN_NAME -ErrorAction SilentlyContinue

if (-not $vpnConnection) {
    Write-Output "[$timestamp] VPN подключение '$VPN_NAME' не найдено. Создаём..." | Out-File $LOG_FILE -Append
    
    try {
        if ($VPN_CONNECTION_TYPE -eq "L2TP") {
            # Создаём L2TP/IPsec подключение
            Add-VpnConnection -Name $VPN_NAME `
                -ServerAddress $VPN_SERVER `
                -TunnelType L2tp `
                -EncryptionLevel Required `
                -AuthenticationMethod Pap `
                -L2tpPsk $PSK `
                -Force `
                -RememberCredential `
                -PassThru
            
            Write-Output "[$timestamp] L2TP/IPsec VPN подключение создано" | Out-File $LOG_FILE -Append
        } 
        elseif ($VPN_CONNECTION_TYPE -eq "IKEv2") {
            # Создаём IKEv2 подключение
            Add-VpnConnection -Name $VPN_NAME `
                -ServerAddress $VPN_SERVER `
                -TunnelType Ikev2 `
                -EncryptionLevel Required `
                -AuthenticationMethod EAP `
                -Force `
                -RememberCredential `
                -PassThru
            
            Write-Output "[$timestamp] IKEv2 VPN подключение создано" | Out-File $LOG_FILE -Append
        }
    } catch {
        Write-Output "[$timestamp] Ошибка создания VPN подключения: $_" | Out-File $LOG_FILE -Append
        exit 1
    }
}

# Подключаемся к VPN
try {
    Write-Output "[$timestamp] Попытка подключения к VPN..." | Out-File $LOG_FILE -Append
    
    # Используем rasdial для подключения
    $output = rasdial $VPN_NAME $VPN_USERNAME $VPN_PASSWORD 2>&1 | Out-String
    Write-Output "[$timestamp] Результат подключения: $output" | Out-File $LOG_FILE -Append
    
    # Альтернативный метод через PowerShell (если rasdial не работает)
    # rasdial $VPN_NAME /disconnect 2>&1 | Out-Null
    # Start-Sleep -Seconds 2
    # rasdial $VPN_NAME $VPN_USERNAME $VPN_PASSWORD 2>&1 | Out-String
    
    Write-Output "[$timestamp] IPsec VPN подключен успешно" | Out-File $LOG_FILE -Append
} catch {
    Write-Output "[$timestamp] Исключение при подключении: $_" | Out-File $LOG_FILE -Append
}

# Ждём установки соединения (для IPsec может потребоваться больше времени)
Start-Sleep -Seconds $CONNECTION_DELAY

# Проверяем статус подключения
$connectionStatus = Get-VpnConnection -Name $VPN_NAME | Select-Object -ExpandProperty ConnectionStatus
Write-Output "[$timestamp] Статус VPN подключения: $connectionStatus" | Out-File $LOG_FILE -Append

# Удаляем старый маршрут если есть (игнорируем ошибки)
try {
    cmd /c "route DELETE $TARGET_NETWORK" 2>$null | Out-Null
    Write-Output "[$timestamp] Старый маршрут удалён" | Out-File $LOG_FILE -Append
} catch {
    Write-Output "[$timestamp] Старого маршрута не было" | Out-File $LOG_FILE -Append
}

# Добавляем маршрут
try {
    $routeOutput = cmd /c "route ADD $TARGET_NETWORK MASK $NETWORK_MASK $VPN_GATEWAY -p" 2>&1 | Out-String
    Write-Output "[$timestamp] Результат добавления маршрута: $routeOutput" | Out-File $LOG_FILE -Append
    Write-Output "[$timestamp] Маршрут добавлен успешно" | Out-File $LOG_FILE -Append
} catch {
    Write-Output "[$timestamp] Исключение при добавлении маршрута: $_" | Out-File $LOG_FILE -Append
}

# Проверяем маршрут
$routes = route PRINT | Select-String $TARGET_NETWORK
Write-Output "[$timestamp] Текущие маршруты к ${TARGET_NETWORK}:" | Out-File $LOG_FILE -Append
Write-Output "$routes" | Out-File $LOG_FILE -Append

# Получаем информацию об адаптере VPN
$vpnAdapter = Get-NetAdapter | Where-Object {$_.InterfaceDescription -like "*$VPN_NAME*" -or $_.Name -like "*$VPN_NAME*"}
if ($vpnAdapter) {
    Write-Output "[$timestamp] VPN адаптер: $($vpnAdapter.Name), Status: $($vpnAdapter.Status)" | Out-File $LOG_FILE -Append
} else {
    Write-Output "[$timestamp] VPN адаптер не найден" | Out-File $LOG_FILE -Append
}

# Проверяем связь
Start-Sleep -Seconds $PING_DELAY
if (Test-Connection -ComputerName $TEST_IP -Count 2 -Quiet) {
    Write-Output "[$timestamp] Проверка связи: SUCCESS (ping $TEST_IP)" | Out-File $LOG_FILE -Append
} else {
    Write-Output "[$timestamp] Проверка связи: FAILED (ping $TEST_IP)" | Out-File $LOG_FILE -Append
    
    # Дополнительная диагностика при неудаче
    $tracert = Test-NetConnection -ComputerName $TEST_IP -TraceRoute -WarningAction SilentlyContinue
    Write-Output "[$timestamp] Трассировка маршрута: $($tracert.TraceRoute -join ' -> ')" | Out-File $LOG_FILE -Append
}

Write-Output "[$timestamp] Скрипт завершён" | Out-File $LOG_FILE -Append