Shared/Get-ActiveNetworkAdapterWinSecureDNS.psm1
function Get-ActiveNetworkAdapterWinSecureDNS { [CmdletBinding()] [OutputType([Microsoft.Management.Infrastructure.CimInstance])] param() <# .SYNOPSIS Get the active physical network adapter that is providing Internet access and is not VPN virtual adapter .NOTES luckily, it's not normally possible to change description of network interfaces/adapters so it is a solid criteria for choosing our network adapter/interface https://serverfault.com/questions/862065/changing-nic-interface-descriptions-in-windows#:~:text=You%20can%27t%20change%20the%20name%20of%20the%20NICs,you%27ll%20have%20to%20do%20lots%20of%20name%20swapping .INPUTS None .OUTPUTS Microsoft.Management.Infrastructure.CimInstance #> Begin { # Importing the $PSDefaultParameterValues to the current session, prior to everything else . "$WinSecureDNSMgrModuleRootPath\MainExt\PSDefaultParameterValues.ps1" } Process { # get the currently active network interface/adapter that is being used for Internet access # This gets the top most active adapter based on route metric $ActiveNetworkInterface = Get-NetRoute -DestinationPrefix '0.0.0.0/0', '::/0' -ErrorAction SilentlyContinue | Sort-Object -Property { $_.InterfaceMetric + $_.RouteMetric } -Top 1 -PipelineVariable ActiveAdapter | Get-NetAdapter -ErrorAction SilentlyContinue | Where-Object -FilterScript { $_.ifIndex -eq $ActiveAdapter.ifIndex } # check if the top most active adapter that we got has an interface index # Windows built-in VPN client connections don't have interface index and don't appear in Get-NetAdapter results if (!$ActiveNetworkInterface) { Write-Verbose -Message "This adapter doesn't even exist in get-NetAdapter results and doesn't have interface index, must be built-in Windows VPN client adapter" # then we get the 2nd adapter from the top $ActiveNetworkInterface = Get-NetRoute -DestinationPrefix '0.0.0.0/0', '::/0' -ErrorAction SilentlyContinue | Sort-Object -Property { $_.InterfaceMetric + $_.RouteMetric } -Top 2 | Select-Object -Skip 1 | Select-Object -First 1 -PipelineVariable ActiveAdapter | Get-NetAdapter | Where-Object -FilterScript { $_.ifIndex -eq $ActiveAdapter.ifIndex } } # if the top most adapter that we got has an interface index else { # check if the detected active interface from the previous step is virtual, if it is, checks if it's an external virtual Hyper-V network adapter or VPN virtual network adapter if ((Get-NetAdapter | Where-Object { $_.InterfaceGuid -eq $ActiveNetworkInterface.InterfaceGuid }).Virtual) { Write-Verbose -Message "Interface is virtual, trying to find out if it's a VPN virtual adapter or Hyper-V External virtual switch" # if it's an external virtual Hyper-V network adapter, it must be the correct adapter if ($ActiveNetworkInterface.InterfaceDescription -like '*Hyper-V Virtual Ethernet Adapter*' ) { Write-Verbose -Message "The detected active network adapter is virtual, it's Hyper-V External switch" $ActiveNetworkInterface = $ActiveNetworkInterface } # if the detected active network adapter is virtual but Not virtual external Hyper-V network adapter, which means it is VPN virtual network adapter (but not Windows built-in VPN client), # choose the second prioritized adapter/interface based on route metric # tested with Cloudflare WARP, Wintun, TAP, OpenVPN and has been always successful in detecting the correct network adapter/interface else { Write-Verbose -Message 'Detected active network adapter is virtual but not virtual Hyper-V adapter, most likely a VPN virtual network adapter, choosing the second prioritized adapter/interface based on route metric' $ActiveNetworkInterface = Get-NetRoute -DestinationPrefix '0.0.0.0/0', '::/0' -ErrorAction SilentlyContinue | Sort-Object -Property { $_.InterfaceMetric + $_.RouteMetric } -Top 2 | Select-Object -Skip 1 | Select-Object -First 1 -PipelineVariable ActiveAdapter | Get-NetAdapter | Where-Object -FilterScript { $_.ifIndex -eq $ActiveAdapter.ifIndex } } } } } End { Write-Verbose -Message 'This is the automatically detected network adapter the module is going to set Secure DNS for' return [Microsoft.Management.Infrastructure.CimInstance]$ActiveNetworkInterface } } Export-ModuleMember -Function 'Get-ActiveNetworkAdapterWinSecureDNS' |