VPN Always On Script
If anyone is interested, I wrote an always-on script that will connect if not on the local network and disconnect when you connect. This script requires a split tunnel. If you don't want to use split tunnel, you can potentially change the IP it looks for to something not accessible when connected to the vpn to figure out if you're on the local network or not.
I made this a GPO that sets a scheduled task and copies the files. I put all the wireguard files and script in netlogon
#v1.3 Added silent install
#v1.2 Added Connection successful check and notification - only use for troubleshooting and running manually
#v1.1 Wireguard install and config check.
#v1.0 20250805
#Create Scheduled Task in Task Scheduler
#1. Create a New Task
#2. General Tab
# Name: WireGuard Always-On VPN
# Select "Run whether user is logged on or not"
# Check "Run with highest privileges"
# Choose "SYSTEM" as the user account
#3. Triggers Tab
# On Logon
# On Event
# Log: Microsoft-Windows-NetworkProfile/Operational
# Source: NetworkProfile
# Event ID: 10000 (for connected) 10001 (for disconnected)
#4. Actions Tab
# Program/script: powershell.exe
# arguments: -NoProfile -ExecutionPolicy Bypass -File "C:\scripts\Wireguard\WireGuard-AlwaysOnVPN.ps1"
#5. Conditions Tab
# Uncheck "Start the task only if the computer is on AC power"
#6. Settings Tab
# Check "Allow task to be run on demand"
# Set "Stop the task if it runs longer than..." 1 hour
#7. Save the Task
#CLI CMD powershell -ExecutionPolicy Bypass -File "C:\scripts\Wireguard\WireGuard-AlwaysOnVPN.ps1"
# Suppress all output and errors unless critical
#Add-Type -AssemblyName System.Windows.Forms
# SET VARIABLES
$tunnelName = $env:COMPUTERNAME + "<TUNNEL NAME>" # WireGuard tunnel name
$configPath = "C:\Scripts\Wireguard\" + $tunnelName + ".conf" # Path to WireGuard config file
$MYpublicIP = "<PUBLIC IP>"
$wgExe = "C:\Program Files\WireGuard\wireguard.exe"
$isAtHome = $false
$hasNetwork = $false
$hasInternet = $false
$wgvpnon = $false
function TesthasNetwork {
########### TEST NO NETWORK AT ALL
# Get all network adapters that are up and not loopback
# Check if any adapter has a valid IPv4 address
$adapters = Get-NetAdapter | Where-Object { $_.Status -eq 'Up' -and $_.InterfaceDescription -notmatch 'Loopback' }
foreach ($adapter in $adapters) {
$ipConfig = Get-NetIPAddress -InterfaceIndex $adapter.InterfaceIndex -AddressFamily IPv4 -ErrorAction SilentlyContinue
if ($ipConfig.IPAddress -and $ipConfig.IPAddress -ne '169.254.0.0') {
return $true
}
}
return $false
}
function TesthasInternet {
############ TEST IF THERE IS INTERNET ACCESS
# Target to test internet connectivity
# Try pinging the target
$testTarget = "8.8.8.8" # You can also use google dns server
$internetAccessible = Test-Connection -ComputerName $testTarget -Count 1 -Quiet
if ($internetAccessible) {
return $true
}
else {
return $false
}
}
function TestisAtHome {
# Create a new web session to avoid cached connections
$publicIP = Invoke-RestMethod -Uri "https://api.ipify.org?format=json"
if ($publicIP.ip -eq $MYpublicIP) {
return $true
}
else {
return $false
}
}
function TestWG {
$wgInterfaces = Get-NetAdapter | Where-Object { $_.InterfaceDescription -like "*WireGuard*" -and $_.Status -eq "Up" }
if ($wgInterfaces) {
return $true
}
else {
return $false
}
}
$hasNetwork = TesthasNetwork
$hasInternet = TesthasInternet
$isAtHome = TestisAtHome
$wgvpnon = TestWG
if (-not $hasNetwork) {
write-output "No Network Connection"
exit 1
}
if (-not $hasInternet) {
write-output "No Internet Connection"
exit 1
}
if (-not (Test-Path $wgExe)) {
Write-Output "WireGuard not found."
#Install WireGuard
# Define installer URL and local path
$installerUrl = "https://download.wireguard.com/windows-client/wireguard-installer.exe"
$localPath = "c:\scripts\wireguard\wireguard-installer.exe"
# Download the installer
Invoke-WebRequest -Uri $installerUrl -OutFile $localPath
# Silently install WireGuard
Start-Process -FilePath $localPath -ArgumentList "/S" -Wait
if (-not (Test-Path $wgExe)) {
Write-Output "WireGuard install failed."
exit 1
}
else {
Write-Output "WireGuard installed."
}
}
if (-not (Test-Path $configPath)) {
Write-Output "WireGuard config not found."
exit 1
}
if ($isAtHome) {
if ($wgvpnon) {
write-output "On Local Network - Disconnecting VPN"
Start-Process -FilePath $wgExe -ArgumentList "/uninstalltunnelservice $tunnelName" -Verb RunAs
#check if VPN Connected
#Start-Sleep -Seconds 3
#if (-not (TestWG)) {
#[System.Windows.Forms.MessageBox]::Show("DISCONNECTED: VPN to <NETWORK NAME>", "WireGuard-AlwaysOnVPN")
#}
}
else {
write-output "On Local Network - No VPN Connection"
}
}
elseif (-not $isAtHome) {
if (-not $wgvpnon) {
write-output "Remote - Connecting VPN"
Start-Process -FilePath $wgExe -ArgumentList "/installtunnelservice `"$configPath`"" -Verb RunAs
#check if VPN Connected
#Start-Sleep -Seconds 3
#if (TestWG) {
#[System.Windows.Forms.MessageBox]::Show("CONNECTED: VPN to <NETWORK NAME>", "WireGuard-AlwaysOnVPN")
#}
}
else {
write-output "Remote - VPN Already Connected"
}
}
else {
write-output "Unknown Case, No Actions Taken"
}
Please sign in to leave a comment.
Comments
0 comments