Note to self: Endre DNS i Wireguard i Windows hos domenebruker
Dette gjelder på Windows-maskiner i domener, hvor (domene)brukeren ikke har adminrettigheter. Scriptet kan trolig benyttes til andre ting, men i dette tilfellet skal vi endre dns-innstillingene.
Den praktiske konsekvensen av akkurat denne linjen er at den løser to helt sentrale nettverksproblemer for hjemmekontoret på én gang. Den er delt i to funksjoner (adskilt med komma):
1. xxx.xxx.xxx.xxx (Hvem PC-en skal spørre)
Når laptopen er koblet til et hjemmenettverk, vil den normalt spørre hjemmeruteren (eller internettleverandøren) om adresser. Hjemmeruteren aner ikke hva "filserver" er.
Ved å sette inn domenekontrollerens IP her, tvinger du WireGuard til å dirigere DNS-forespørslene inn gjennom VPN-tunnelen og rett til domenekontrolleren deres. På denne måten kan pc'en få svar på hvilken intern IP-adresse en server (f.eks \\filserver) har.
2. eksempel.local (Søkedomene for auto-utfylling)
Dette er den lille detaljen som gjør at alt føles som før for brukeren og programmene. Det fungerer som et usynlig suffiks (etternavn) for Windows.
Uten dette: Ville brukere (og programmene) alltid måttet bruke det fulle domenenavnet (FQDN) for å finne noe. Han måtte skrevet \\filserver.eksempel.local.
Med dette: Kan han nøye seg med å skrive kortnavnet \\filserver. Windows skjønner da at den automatisk skal lime på .eksempel.local i bakgrunnen før den sender spørringen til domenekontrolleren.
Takket være denne linjen i WireGuard vil programmene klare å finne serveren like raskt hjemmefra som når laptopen står fysisk plassert på kontoret.
<#
Update-WgDns.ps1
Bytter DNS-linja i WireGuard-tunneler UTEN å røre nøkler/Address/Peer.
Bruk (interaktivt): kjør fra en HEVET (Kjør som administrator) PowerShell:
.\Update-WgDns.ps1
.\Update-WgDns.ps1 -TunnelName "MinTunnel"
.\Update-WgDns.ps1 -NewDns "xxx.xxx.xxx.xxx, domene.local"
Skriptet hever seg selv til SYSTEM (kreves for å dekryptere .conf.dpapi).
Kjøres det allerede som SYSTEM (f.eks. via RMM-agent), går det rett på jobben.
#>
[CmdletBinding()]
param(
[string]$NewDns = "xxx.xxx.xxx.xxx, domene.local", # IP + søkedomene = split-DNS via NRPT
[string]$TunnelName = "", # tom = alle tunneler på maskinen
[string]$LogPath = "" # intern: brukes av SYSTEM-passet
)
$ErrorActionPreference = "Stop"
$confDir = Join-Path $env:ProgramFiles "WireGuard\Data\Configurations"
$wgExe = Join-Path $env:ProgramFiles "WireGuard\wireguard.exe"
# --- 1) Hev til SYSTEM hvis vi ikke allerede er det ------------------------
$me = [Security.Principal.WindowsIdentity]::GetCurrent()
if (-not $me.IsSystem) {
$p = New-Object Security.Principal.WindowsPrincipal($me)
if (-not $p.IsInRole([Security.Principal.WindowsBuiltinRole]::Administrator)) {
Write-Host "Start dette fra en HEVET (admin) PowerShell." -ForegroundColor Red; exit 1
}
$log = Join-Path $env:TEMP ("wgdns_{0}.log" -f ([guid]::NewGuid().ToString('N')))
$task = "WgDnsUpdate_{0}" -f ([guid]::NewGuid().ToString('N'))
$a = '-NoProfile -ExecutionPolicy Bypass -File "{0}" -NewDns "{1}" -LogPath "{2}"' -f $PSCommandPath,$NewDns,$log
if ($TunnelName) { $a += ' -TunnelName "{0}"' -f $TunnelName }
$act = New-ScheduledTaskAction -Execute "$env:SystemRoot\System32\WindowsPowerShell\v1.0\powershell.exe" -Argument $a
$prn = New-ScheduledTaskPrincipal -UserId "SYSTEM" -LogonType ServiceAccount -RunLevel Highest
Register-ScheduledTask -TaskName $task -Action $act -Principal $prn -Force | Out-Null
Start-ScheduledTask -TaskName $task
Start-Sleep -Seconds 1
$to = (Get-Date).AddMinutes(2)
while (((Get-ScheduledTask -TaskName $task).State -eq 'Running') -and ((Get-Date) -lt $to)) { Start-Sleep -Milliseconds 500 }
Unregister-ScheduledTask -TaskName $task -Confirm:$false
if (Test-Path $log) { Get-Content $log; Remove-Item $log -Force }
exit
}
# --- 2) Herfra kjører vi som SYSTEM ---------------------------------------
function Log($m){ if($LogPath){ Add-Content -Path $LogPath -Value $m } else { Write-Host $m } }
Add-Type -AssemblyName System.Security | Out-Null
try { if((Get-Service WireGuardManager).Status -ne 'Running'){ Start-Service WireGuardManager } } catch {}
$backup = Join-Path $confDir ("_backup_{0}" -f (Get-Date -Format "yyyyMMdd_HHmmss"))
New-Item -ItemType Directory -Path $backup -Force | Out-Null
$targets = if ($TunnelName) { @(Join-Path $confDir "$TunnelName.conf.dpapi") }
else { Get-ChildItem -Path $confDir -Filter *.conf.dpapi | Select-Object -Expand FullName }
foreach ($dpapi in $targets) {
if (-not (Test-Path $dpapi)) { Log "HOPPER OVER (finnes ikke): $dpapi"; continue }
$name = [IO.Path]::GetFileName($dpapi) -replace '\.conf\.dpapi$',''
Log "=== $name ==="
try {
Copy-Item $dpapi (Join-Path $backup ([IO.Path]::GetFileName($dpapi))) -Force
# dekrypter (SYSTEM, bruker-scope) -> klartekst med nøkler intakt
$enc = [IO.File]::ReadAllBytes($dpapi)
$dec = [Security.Cryptography.ProtectedData]::Unprotect($enc, $null, [Security.Cryptography.DataProtectionScope]::CurrentUser)
$conf = [Text.Encoding]::UTF8.GetString($dec).TrimStart([char]0xFEFF)
$dnsLine = "DNS = $NewDns"
if ($conf -match '(?im)^[ \t]*DNS[ \t]*=.*$') {
$conf = [regex]::Replace($conf, '(?im)^[ \t]*DNS[ \t]*=.*$', $dnsLine); Log " DNS erstattet -> $dnsLine"
} else {
$conf = [regex]::Replace($conf, '(?im)^[ \t]*\[Interface\][ \t]*$', "`$0`r`n$dnsLine", 1); Log " DNS lagt til -> $dnsLine"
}
# deaktiver KUN hvis tunnelen faktisk er aktiv (ellers finnes ingen tjeneste)
if (Get-Service -Name "WireGuardTunnel`$$name" -ErrorAction SilentlyContinue) {
$eap = $ErrorActionPreference; $ErrorActionPreference = 'Continue'
& $wgExe /uninstalltunnelservice $name 2>$null | Out-Null
$ErrorActionPreference = $eap
Start-Sleep -Seconds 1
}
Remove-Item $dpapi -Force
$plain = Join-Path $confDir "$name.conf"
[IO.File]::WriteAllText($plain, $conf, (New-Object Text.UTF8Encoding($false))) # manageren krypterer & sletter klartekst
$limit = (Get-Date).AddSeconds(20)
while ((Test-Path $plain) -and ((Get-Date) -lt $limit)) { Start-Sleep -Milliseconds 500 }
if (Test-Path (Join-Path $confDir "$name.conf.dpapi")) {
Log " OK: oppdatert og re-kryptert."
if (Test-Path $plain) { Remove-Item $plain -Force }
} else { Log " ADVARSEL: fant ikke ny .conf.dpapi - sjekk $plain manuelt." }
} catch { Log " FEIL: $($_.Exception.Message)" }
}
# oppdater skuffen slik at tunnelen vises med ny config med en gang
try { Restart-Service WireGuardManager -ErrorAction Stop; Log "Skuff oppdatert (WireGuardManager restartet)." }
catch { Log "Merk: klarte ikke restarte WireGuardManager ($($_.Exception.Message)) - configen er likevel oppdatert." }
Log "Backup: $backup"
Log "Ferdig. Bruker kan koble til pa nytt fra WireGuard-skuffen."
$targets = if ($TunnelName) { @(Join-Path $confDir "$TunnelName.conf.dpapi") }
else { Get-ChildItem -Path $confDir -Filter *.conf.dpapi | Select-Object -Expand FullName }
foreach ($dpapi in $targets) {
if (-not (Test-Path $dpapi)) { Log "HOPPER OVER (finnes ikke): $dpapi"; continue }
$name = [IO.Path]::GetFileName($dpapi) -replace '\.conf\.dpapi$',''
Log "=== $name ==="
try {
Copy-Item $dpapi (Join-Path $backup ([IO.Path]::GetFileName($dpapi))) -Force
# dekrypter (SYSTEM, bruker-scope) -> klartekst med nøkler intakt
$enc = [IO.File]::ReadAllBytes($dpapi)
$dec = [Security.Cryptography.ProtectedData]::Unprotect($enc, $null, [Security.Cryptography.DataProtectionScope]::CurrentUser)
$conf = [Text.Encoding]::UTF8.GetString($dec).TrimStart([char]0xFEFF)
$dnsLine = "DNS = $NewDns"
if ($conf -match '(?im)^[ \t]*DNS[ \t]*=.*$') {
$conf = [regex]::Replace($conf, '(?im)^[ \t]*DNS[ \t]*=.*$', $dnsLine); Log " DNS erstattet -> $dnsLine"
} else {
$conf = [regex]::Replace($conf, '(?im)^[ \t]*\[Interface\][ \t]*$', "`$0`r`n$dnsLine", 1); Log " DNS lagt til -> $dnsLine"
}
# deaktiver KUN hvis tunnelen faktisk er aktiv (ellers finnes ingen tjeneste)
if (Get-Service -Name "WireGuardTunnel`$$name" -ErrorAction SilentlyContinue) {
$eap = $ErrorActionPreference; $ErrorActionPreference = 'Continue'
& $wgExe /uninstalltunnelservice $name 2>$null | Out-Null
$ErrorActionPreference = $eap
Start-Sleep -Seconds 1
}
Remove-Item $dpapi -Force
$plain = Join-Path $confDir "$name.conf"
[IO.File]::WriteAllText($plain, $conf, (New-Object Text.UTF8Encoding($false))) # manageren krypterer & sletter klartekst
$limit = (Get-Date).AddSeconds(20)
while ((Test-Path $plain) -and ((Get-Date) -lt $limit)) { Start-Sleep -Milliseconds 500 }
if (Test-Path (Join-Path $confDir "$name.conf.dpapi")) {
Log " OK: oppdatert og re-kryptert."
if (Test-Path $plain) { Remove-Item $plain -Force }
} else { Log " ADVARSEL: fant ikke ny .conf.dpapi - sjekk $plain manuelt." }
} catch { Log " FEIL: $($_.Exception.Message)" }
}
Log "Backup: $backup"
Log "Ferdig. Bruker kan koble til pa nytt fra WireGuard-skuffen."
Lagre koden som f.eks UpdateDNS.ps1.
På maskinen hvor dette skal gjøres:
- Start Powershell som administrator
- Naviger til mappen hvor du har lagret UpdateDNS.ps1.
- Kjør følgende kode for å få lov til å starte scriptet i utgangspunktet:
Set-ExecutionPolicy -Scope Process -ExecutionPolicy Bypass -Force - Deretter:
.\Update-WgDns.ps1 - Det er sikkert lurt å slette scriptet fra arbeidsstasjonen når du er ferdig.
