mirror of
https://github.com/NexusOne23/noid-privacy.git
synced 2026-02-07 04:01:52 +01:00
183 lines
7.6 KiB
PowerShell
183 lines
7.6 KiB
PowerShell
function Set-DNSServers {
|
|
<#
|
|
.SYNOPSIS
|
|
Set DNS server addresses on network adapter
|
|
|
|
.DESCRIPTION
|
|
Configures DNS server addresses (IPv4 and IPv6) on specified network adapter.
|
|
Uses Microsoft Best Practice: Set-DnsClientServerAddress with -Validate parameter.
|
|
|
|
Always configures both IPv4 and IPv6 addresses. Windows will use IPv6 when available,
|
|
and fall back to IPv4 otherwise.
|
|
|
|
.PARAMETER InterfaceIndex
|
|
Network adapter interface index
|
|
|
|
.PARAMETER IPv4Primary
|
|
Primary IPv4 DNS server address
|
|
|
|
.PARAMETER IPv4Secondary
|
|
Secondary IPv4 DNS server address
|
|
|
|
.PARAMETER IPv6Primary
|
|
Primary IPv6 DNS server address
|
|
|
|
.PARAMETER IPv6Secondary
|
|
Secondary IPv6 DNS server address
|
|
|
|
.PARAMETER Validate
|
|
Validate DNS servers are reachable before applying (recommended)
|
|
|
|
.PARAMETER DryRun
|
|
Show what would be configured without applying changes
|
|
|
|
.EXAMPLE
|
|
Set-DNSServers -InterfaceIndex 12 -IPv4Primary "1.1.1.1" -IPv4Secondary "1.0.0.1" `
|
|
-IPv6Primary "2606:4700:4700::1111" -IPv6Secondary "2606:4700:4700::1001" -Validate
|
|
|
|
.OUTPUTS
|
|
System.Boolean - $true if successful, $false otherwise
|
|
|
|
.NOTES
|
|
Uses Set-DnsClientServerAddress cmdlet (PowerShell Best Practice)
|
|
NEVER uses netsh (deprecated legacy method)
|
|
#>
|
|
|
|
[CmdletBinding()]
|
|
param(
|
|
[Parameter(Mandatory = $true)]
|
|
[int]$InterfaceIndex,
|
|
|
|
[Parameter(Mandatory = $true)]
|
|
[string]$IPv4Primary,
|
|
|
|
[Parameter(Mandatory = $true)]
|
|
[string]$IPv4Secondary,
|
|
|
|
[Parameter(Mandatory = $true)]
|
|
[string]$IPv6Primary,
|
|
|
|
[Parameter(Mandatory = $true)]
|
|
[string]$IPv6Secondary,
|
|
|
|
[Parameter()]
|
|
[switch]$Validate,
|
|
|
|
[Parameter()]
|
|
[switch]$DryRun
|
|
)
|
|
|
|
try {
|
|
$adapter = Get-NetAdapter -InterfaceIndex $InterfaceIndex -ErrorAction Stop
|
|
$adapterName = $adapter.Name
|
|
|
|
Write-Log -Level INFO -Message "Configuring DNS servers on adapter: $adapterName" -Module $script:ModuleName
|
|
|
|
# Prepare IPv4 addresses array
|
|
$ipv4Addresses = @($IPv4Primary, $IPv4Secondary)
|
|
|
|
# Prepare IPv6 addresses array
|
|
$ipv6Addresses = @($IPv6Primary, $IPv6Secondary)
|
|
|
|
Write-Log -Level DEBUG -Message " IPv4: $($ipv4Addresses -join ', ')" -Module $script:ModuleName
|
|
Write-Log -Level DEBUG -Message " IPv6: $($ipv6Addresses -join ', ')" -Module $script:ModuleName
|
|
|
|
if ($DryRun) {
|
|
Write-Log -Level INFO -Message "[DRYRUN] Would configure DNS servers on $adapterName" -Module $script:ModuleName
|
|
return $true
|
|
}
|
|
|
|
# Configure IPv4 DNS servers with retry logic (fixes 0x80004005 errors)
|
|
Write-Log -Level DEBUG -Message "Setting IPv4 DNS servers..." -Module $script:ModuleName
|
|
|
|
$ipv4Params = @{
|
|
InterfaceIndex = $InterfaceIndex
|
|
ServerAddresses = $ipv4Addresses
|
|
ErrorAction = 'Stop'
|
|
}
|
|
|
|
if ($Validate) {
|
|
$ipv4Params['Validate'] = $true
|
|
Write-Log -Level DEBUG -Message "Validation enabled for IPv4 DNS servers" -Module $script:ModuleName
|
|
}
|
|
|
|
# Retry logic with fast retries (adapter stabilization or offline detection)
|
|
$maxRetries = 3
|
|
$retryDelay = 1 # Fast 1-second retries (no exponential backoff needed)
|
|
|
|
for ($attempt = 1; $attempt -le $maxRetries; $attempt++) {
|
|
try {
|
|
Set-DnsClientServerAddress @ipv4Params
|
|
Write-Log -Level SUCCESS -Message "IPv4 DNS servers configured: $($ipv4Addresses -join ', ')" -Module $script:ModuleName
|
|
break
|
|
}
|
|
catch {
|
|
if ($attempt -lt $maxRetries) {
|
|
Write-Log -Level DEBUG -Message "Attempt $attempt failed, retrying... ($($_.Exception.Message))" -Module $script:ModuleName
|
|
Start-Sleep -Seconds $retryDelay
|
|
}
|
|
else {
|
|
# Fallback to netsh if CIM fails (General Error fix - often happens when offline)
|
|
Write-Log -Level DEBUG -Message "PowerShell cmdlet failed, using netsh fallback..." -Module $script:ModuleName
|
|
|
|
try {
|
|
# Use netsh for IPv4 configuration
|
|
$netshResult = & netsh interface ip set dns name="$adapterName" source=static address=$IPv4Primary validate=no 2>&1
|
|
|
|
if ($LASTEXITCODE -eq 0) {
|
|
# Add secondary DNS
|
|
$null = & netsh interface ip add dns name="$adapterName" address=$IPv4Secondary index=2 validate=no 2>&1
|
|
|
|
Write-Log -Level SUCCESS -Message "IPv4 DNS configured via netsh fallback: $($ipv4Addresses -join ', ')" -Module $script:ModuleName
|
|
break # Success, exit retry loop
|
|
}
|
|
else {
|
|
throw "Netsh fallback also failed: $netshResult"
|
|
}
|
|
}
|
|
catch {
|
|
throw "All DNS configuration methods failed: $_"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
# Configure IPv6 DNS servers
|
|
# Note: IPv6 configuration uses the same cmdlet with IPv6 addresses
|
|
Write-Log -Level DEBUG -Message "Setting IPv6 DNS servers..." -Module $script:ModuleName
|
|
|
|
# For IPv6, we need to configure it separately
|
|
# Get the IPv6 interface
|
|
$ipv6Interface = Get-NetAdapter -InterfaceIndex $InterfaceIndex |
|
|
Get-NetAdapterBinding -ComponentID ms_tcpip6 -ErrorAction SilentlyContinue
|
|
|
|
if ($ipv6Interface -and $ipv6Interface.Enabled) {
|
|
try {
|
|
# Set IPv6 DNS using netsh as PowerShell cmdlet doesn't support dual-stack properly
|
|
# NOTE: This is one of the few cases where netsh is still needed for IPv6
|
|
$primaryResult = & netsh interface ipv6 set dnsservers name="$adapterName" source=static address=$IPv6Primary validate=no 2>&1
|
|
$secondaryResult = & netsh interface ipv6 add dnsservers name="$adapterName" address=$IPv6Secondary index=2 validate=no 2>&1
|
|
|
|
if ($LASTEXITCODE -eq 0) {
|
|
Write-Log -Level SUCCESS -Message "IPv6 DNS servers configured: $($ipv6Addresses -join ', ')" -Module $script:ModuleName
|
|
}
|
|
else {
|
|
Write-Log -Level WARNING -Message "IPv6 DNS configuration had issues (non-fatal): $primaryResult $secondaryResult" -Module $script:ModuleName
|
|
}
|
|
}
|
|
catch {
|
|
Write-Log -Level WARNING -Message "Could not configure IPv6 DNS (non-fatal): $_" -Module $script:ModuleName
|
|
}
|
|
}
|
|
else {
|
|
Write-Log -Level INFO -Message "IPv6 binding is disabled on this adapter - skipping IPv6 DNS server assignment (IPv4 + DoH templates will still be used)" -Module $script:ModuleName
|
|
}
|
|
|
|
# Configuration complete - Windows cmdlets verify automatically
|
|
return $true
|
|
}
|
|
catch {
|
|
Write-ErrorLog -Message "Failed to set DNS servers on interface $InterfaceIndex" -Module $script:ModuleName -ErrorRecord $_
|
|
return $false
|
|
}
|
|
}
|