Manchmal ist es praktisch, wenn ein WireGuard-Tunnel nicht immer gleich aktiv ist, sondern sich automatisch an den aktuell angemeldeten Windows-User anpasst. Genau das lässt sich mit einem kleinen PowerShell-Skript und der Windows-Aufgabenplanung ziemlich elegant lösen. In meinem Fall entstand die Idee aus einem ganz konkreten Problem: Microsoft Outlook wollte sich mit privaten GMail-Konten nicht verbinden, solange der WireGuard-Tunnel aktiv war. Das passierte sogar trotz Split-Tunneling und statischer Routen. Erst nachdem der Tunnel vollständig deaktiviert wurde, konnte Outlook wieder problemlos per IMAP auf die GMail-Konten zugreifen.
In dieser Anleitung geht es darum, den WireGuard-Tunnel
- bei einem lokalen Windows-Konto zu deaktivieren
- bei einem Domain-Konto wieder zu aktivieren
Das Ganze läuft automatisch im Hintergrund, sobald sich ein User anmeldet oder eine Sitzung entsperrt wird.
Die Idee
- Windows erkennt, welcher User gerade angemeldet ist
- Ein PowerShell-Skript vergleicht diesen User mit einem fest definierten Domain-Account
- Je nach Ergebnis wird der WireGuard-Tunnel ein- oder ausgeschaltet
Das PowerShell-Skript
Hier ist das Skript:
# Run as Administrator
# --- CONFIGURATION ---
$targetUser = "DOMAIN\USER" # User to check
$wgTunnelName = "WG_TUNNEL_NAME" # WireGuard tunnel name
$wgTunnelPath = "C:\Program Files\WireGuard\Data\Configurations\WG_TUNNEL_NAME.conf.dpapi"
$wgExePath = "C:\Program Files\WireGuard\wireguard.exe" # Path to WireGuard
# Uncomment below to log the script events
#$logFile = "C:\WireGuard\WG_Debug.txt"
# --- CHECK CURRENT USER ---
$currentUser = (Get-WmiObject -Class Win32_ComputerSystem).UserName
"$((Get-Date).ToString()) - Detected logged-in user: $currentUser" | Out-File $logFile -Append
#Race condition?
#Start-Sleep -Seconds 10
# --- ENABLE OR DISABLE TUNNEL ---
if ($currentUser -ieq $targetUser) {
# Enable tunnel if not already enabled
"$((Get-Date).ToString()) - User matched. Enabling WireGuard." | Out-File $logFile -Append
& "$wgExePath" /installtunnelservice $wgTunnelPath 2>$null
} else {
# Disable tunnel if it is enabled
"$((Get-Date).ToString()) - User did NOT match. Disabling WireGuard." | Out-File $logFile -Append
& "$wgExePath" /uninstalltunnelservice "$wgTunnelName" 2>$null
}
Was das Skript macht
1. Ziel-User festlegen
Ganz oben wird festgelegt, für welchen Benutzer der Tunnel aktiv sein soll:
$targetUser = "DOMAIN\USER"
Hier kommt also der Domain-Account rein, bei dem WireGuard später aktiv sein soll.
2. WireGuard-Pfade setzen
Danach werden Name und Pfad des Tunnels definiert:
$wgTunnelName = "WG_TUNNEL_NAME" $wgTunnelPath = "C:\Program Files\WireGuard\Data\Configurations\WG_TUNNEL_NAME.conf.dpapi" $wgExePath = "C:\Program Files\WireGuard\wireguard.exe"
Wichtig ist, dass diese Werte zu deiner Installation passen.
3. Aktuell angemeldeten User auslesen
Dann holt sich das Skript den aktuell angemeldeten Benutzer:
$currentUser = (Get-WmiObject -Class Win32_ComputerSystem).UserName
Das Ergebnis wird mit dem Ziel-User verglichen.
4. Tunnel aktivieren oder deaktivieren
Wenn der angemeldete User dem Ziel-User entspricht, wird der Tunnel aktiviert:
& "$wgExePath" /installtunnelservice $wgTunnelPath
Passt der User nicht, wird der Tunnel deaktiviert:
& "$wgExePath" /uninstalltunnelservice "$wgTunnelName"
So lässt sich der Tunnel automatisch an den Login anpassen.
Die Aufgabenplanung einrichten
Damit das Skript nicht manuell gestartet werden muss, übernimmt die Windows-Aufgabenplanung den Job.
Die Aufgabe wird bei zwei Ereignissen ausgelöst:
- Logon
- Session Unlock
Das bedeutet:
Sobald sich ein User anmeldet oder den Bildschirm wieder entsperrt, läuft das Skript erneut.
Exportierte XML der Aufgabe
Hier die XML-Datei aus der Aufgabenplanung als Referenz:
<Task xmlns="http://schemas.microsoft.com/windows/2004/02/mit/task" version="1.2"> <RegistrationInfo> <Date>2026-02-19T20:45:38.5559898</Date> <Author>DOMAIN\USER</Author> <Description>C:/WireGuard/Wireguard_Toggle_User.ps1</Description> <URI>\WireGuard Toggle Tunnel By Logged In User</URI> </RegistrationInfo> <Triggers> <LogonTrigger> <Enabled>true</Enabled> </LogonTrigger> <SessionStateChangeTrigger> <Enabled>true</Enabled> <StateChange>SessionUnlock</StateChange> </SessionStateChangeTrigger> </Triggers> <Principals> <Principal id="Author"> <UserId>S-1-5-18</UserId> <RunLevel>HighestAvailable</RunLevel> </Principal> </Principals> <Settings> <MultipleInstancesPolicy>IgnoreNew</MultipleInstancesPolicy> <DisallowStartIfOnBatteries>false</DisallowStartIfOnBatteries> <StopIfGoingOnBatteries>false</StopIfGoingOnBatteries> <AllowHardTerminate>true</AllowHardTerminate> <StartWhenAvailable>false</StartWhenAvailable> <RunOnlyIfNetworkAvailable>false</RunOnlyIfNetworkAvailable> <IdleSettings> <StopOnIdleEnd>true</StopOnIdleEnd> <RestartOnIdle>false</RestartOnIdle> </IdleSettings> <AllowStartOnDemand>true</AllowStartOnDemand> <Enabled>true</Enabled> <Hidden>false</Hidden> <RunOnlyIfIdle>false</RunOnlyIfIdle> <WakeToRun>false</WakeToRun> <ExecutionTimeLimit>PT72H</ExecutionTimeLimit> <Priority>7</Priority> </Settings> <Actions Context="Author"> <Exec> <Command>powershell.exe</Command> <Arguments>-WindowStyle Hidden -ExecutionPolicy Bypass -File "C:\WireGuard\Wireguard_Toggle_User.ps1"</Arguments> </Exec> </Actions> </Task>
So ist die Aufgabe aufgebaut
Ein paar Punkte sind hier besonders wichtig:
Trigger
Die Aufgabe startet bei:
- Benutzeranmeldung
- Entsperren der Sitzung
Damit reagiert das Skript auch dann, wenn der Benutzer zwischendurch nur kurz gesperrt war.
Ausführung als Systemuser
Der Task läuft als:
<UserId>S-1-5-18</UserId>
Das ist das SYSTEM-Konto. Dadurch hat das Skript die nötigen Rechte, um WireGuard zu steuern.
Unsichtbarer Start
Der PowerShell-Aufruf läuft versteckt:
<Arguments>-WindowStyle Hidden -ExecutionPolicy Bypass -File "C:\WireGuard\Wireguard_Toggle_User.ps1"</Arguments>
So bekommt der Benutzer davon nichts mit.
Kleiner Hinweis zur Zuverlässigkeit
Direkt beim Login kann es manchmal zu einem Timing-Problem kommen. Dann ist der User noch nicht sauber verfügbar, wenn das Skript startet.
In deinem Skript ist dafür schon ein Kommentar vorbereitet:
#Start-Sleep -Seconds 10
Wenn es bei dir mal nicht sofort sauber funktioniert, kann eine kurze Verzögerung helfen.
Außerdem ist Logging vorbereitet:
#$logFile = "C:\WireGuard\WG_Debug.txt"
Das ist super praktisch, wenn du später nachvollziehen willst, was das Skript gerade gemacht hat.
WireGuard-Tunnel automatisch je nach Windows-Login (Domain- und lokales Konto) umschalten