Automated VPN Reconnection Script for Windows Servers (2008/2012+) – Persistent Connection Solutions


1 views

Maintaining uninterrupted VPN connections on Windows servers is critical for remote administration and secure communications. When connections drop due to server reboots, network issues, or manual disconnects, automated reconnection becomes essential.

Windows includes some basic persistence features:

rasdial "VPN Connection Name" username password /phonebook:%userprofile%\AppData\Roaming\Microsoft\Network\Connections\Pbk\rasphone.pbk

However, this only works for initial connection and doesn't handle drops.

This PowerShell script monitors and reconnects automatically:

# VPN Auto-Reconnect Script
$VPNName = "YourVPNConnectionName"
$username = "vpnuser"
$password = "securepassword"

while ($true) {
    $connection = Get-VpnConnection -Name $VPNName
    if ($connection.ConnectionStatus -ne "Connected") {
        rasdial $VPNName $username $password
        Start-Sleep -Seconds 10
    }
    Start-Sleep -Seconds 30
}

Create a scheduled task that runs at system startup:

# Create scheduled task
$action = New-ScheduledTaskAction -Execute "PowerShell.exe" -Argument "-File C:\Scripts\VPNReconnect.ps1"
$trigger = New-ScheduledTaskTrigger -AtStartup
Register-ScheduledTask -TaskName "VPN Auto-Reconnect" -Action $action -Trigger $trigger -RunLevel Highest

Enhanced version with logging and retry logic:

function Write-Log {
    param([string]$message)
    Add-Content -Path "C:\VPNLog.txt" -Value "$(Get-Date -Format 'yyyy-MM-dd HH:mm:ss') - $message"
}

$maxRetries = 5
$retryCount = 0

while ($true) {
    try {
        $connection = Get-VpnConnection -Name $VPNName -ErrorAction Stop
        if ($connection.ConnectionStatus -ne "Connected") {
            Write-Log "Attempting VPN connection..."
            rasdial $VPNName $username $password | Out-Null
            if ($LASTEXITCODE -eq 0) {
                Write-Log "VPN connected successfully"
                $retryCount = 0
            } else {
                $retryCount++
                Write-Log "Connection failed (Attempt $retryCount)"
                if ($retryCount -ge $maxRetries) {
                    Write-Log "Max retries reached, waiting before next attempt"
                    Start-Sleep -Seconds 300
                    $retryCount = 0
                }
            }
        }
    } catch {
        Write-Log "Error: $_"
    }
    Start-Sleep -Seconds 30
}

For enterprise environments, consider tools like:

  • AlwaysUp (commercial service manager)
  • NSSM (Non-Sucking Service Manager)
  • DameWare Remote Everywhere (enterprise solution)

Maintaining persistent VPN connections on Windows Server environments (2008 R2, 2012 R2, and newer) requires robust handling of various disconnection scenarios. The primary pain points include:

  • Unexpected network interruptions
  • Server reboots during maintenance windows
  • Temporary credential expirations
  • Manual disconnections by administrators

The built-in VPN client offers some persistence features through connection properties:

# Configure persistent connection in PowerShell
Add-VpnConnection -Name "CorporateVPN" -ServerAddress "vpn.example.com" \
-AllUserConnection -RememberCredential -IdleDisconnectSeconds 0 \
-CustomConfiguration "@{DnsSuffix=corp.example.com; UseRasCredentials=1}"

However, this doesn't cover all scenarios, particularly manual disconnections or credential rotations.

Create a scheduled task that runs this script every 5 minutes:

# VPN-Watchdog.ps1
$connectionName = "CorporateVPN"
$vpn = Get-VpnConnection -Name $connectionName -ErrorAction SilentlyContinue

if ($vpn.ConnectionStatus -ne "Connected") {
    Write-Output "$(Get-Date) - VPN disconnected. Reconnecting..."
    rasdial $connectionName /disconnect
    Start-Sleep -Seconds 2
    rasdial $connectionName
    # For credential-based connections:
    # rasdial $connectionName [username] [password]
} else {
    Write-Output "$(Get-Date) - VPN connection healthy"
}

# Log results to event viewer
if ($vpn.ConnectionStatus -ne "Connected") {
    Write-EventLog -LogName "Application" -Source "VPN Watchdog" -EntryType Information -EventId 1001 -Message "Reconnected VPN $connectionName"
}

For real-time monitoring without polling, use Windows Event Log triggers:

# Create event filter for VPN disconnections
$query = @'
<QueryList>
  <Query Id="0" Path="Application">
    <Select Path="Application">
      *[System[Provider[@Name='RasClient'] and (EventID=20267)]]
    </Select>
  </Query>
</QueryList>
'@

# Create the event subscription
$action = New-ScheduledTaskAction -Execute "PowerShell.exe" -Argument "-File C:\Scripts\VPN-Reconnect.ps1"
$trigger = New-ScheduledTaskTrigger -AtLogon -RandomDelay "00:00:30"
Register-ScheduledTask -TaskName "VPN Auto-Reconnect" -Action $action -Trigger $trigger -Description "Automatically reconnects VPN on disconnection" -User "SYSTEM"

For critical environments, consider these enhancements:

# Multi-interface failover script
$primaryVPN = "Primary-VPN"
$backupVPN = "Backup-VPN"
$testHost = "internal-server.corp.example.com"

if (-not (Test-Connection -ComputerName $testHost -Count 1 -Quiet)) {
    Write-Output "Primary VPN failed, testing backup..."
    rasdial $primaryVPN /disconnect
    
    if (Test-Connection -ComputerName $testHost -Count 1 -Quiet) {
        Write-Output "Backup VPN already active"
    } else {
        rasdial $backupVPN
        Start-Sleep -Seconds 5
        if (-not (Test-Connection -ComputerName $testHost -Count 1 -Quiet)) {
            # Alert operations team
            Send-MailMessage -To "noc@example.com" -From "vpnmonitor@example.com" -Subject "VPN Connection Failure" -Body "Both primary and backup VPN connections failed" -SmtpServer "smtp.corp.example.com"
        }
    }
}

When implementing automated VPN reconnections:

  • Store credentials securely using Windows Credential Manager
  • Implement appropriate certificate-based authentication where possible
  • Set script execution policies to RemoteSigned or AllSigned
  • Log all reconnection attempts for audit purposes
# Example of secure credential handling
$credential = Get-StoredCredential -Target "CorporateVPN"
rasdial "CorporateVPN" $credential.UserName $credential.GetNetworkCredential().Password

Enhance your solution with proper monitoring:

# Prometheus exporter for VPN status
$vpnStatus = (Get-VpnConnection -Name "CorporateVPN").ConnectionStatus
$metrics = @"
# HELP vpn_connection_status Current VPN connection state (0=disconnected, 1=connected)
# TYPE vpn_connection_status gauge
vpn_connection_status{name="CorporateVPN"} $(if ($vpnStatus -eq "Connected") {1} else {0})
"@

$metrics | Out-File "C:\metrics\vpn_metrics.prom" -Encoding utf8