mirror of
https://github.com/NexusOne23/noid-privacy.git
synced 2026-02-07 20:14:25 +01:00
150 lines
6.4 KiB
PowerShell
150 lines
6.4 KiB
PowerShell
function Get-PhysicalAdapters {
|
|
<#
|
|
.SYNOPSIS
|
|
Get physical network adapters (LAN/WLAN) excluding virtual adapters
|
|
|
|
.DESCRIPTION
|
|
Retrieves physical network adapters using multi-layer filtering to exclude:
|
|
- Virtual adapters (Hyper-V, VMware, VirtualBox)
|
|
- VPN adapters (TAP, OpenVPN, WireGuard, Cisco, etc.)
|
|
- Tunnel adapters (Teredo, 6to4, ISATAP)
|
|
- Loopback adapters
|
|
|
|
Uses Microsoft Best Practice: Get-NetAdapter with -Physical switch
|
|
and additional filtering based on InterfaceDescription patterns.
|
|
|
|
.PARAMETER IncludeDisabled
|
|
Include disabled adapters in results
|
|
|
|
.EXAMPLE
|
|
Get-PhysicalAdapters
|
|
Returns all active physical network adapters
|
|
|
|
.EXAMPLE
|
|
Get-PhysicalAdapters -IncludeDisabled
|
|
Returns all physical adapters including disabled ones
|
|
|
|
.OUTPUTS
|
|
Microsoft.Management.Infrastructure.CimInstance#ROOT/StandardCimv2/MSFT_NetAdapter
|
|
|
|
.NOTES
|
|
Uses Get-NetAdapter -Physical for primary filtering (Microsoft Best Practice)
|
|
Additional filtering excludes known virtual adapter patterns
|
|
#>
|
|
|
|
[CmdletBinding()]
|
|
param(
|
|
[Parameter()]
|
|
[switch]$IncludeDisabled
|
|
)
|
|
|
|
try {
|
|
Write-Log -Level DEBUG -Message "Retrieving physical network adapters..." -Module $script:ModuleName
|
|
|
|
# Layer 1: Get physical adapters only (Microsoft Best Practice)
|
|
$adapters = Get-NetAdapter -Physical -ErrorAction Stop
|
|
|
|
# Layer 2: Filter by status if required
|
|
if (-not $IncludeDisabled) {
|
|
# Allow 'Up' (Connected) and 'Disconnected' (Cable unplugged)
|
|
# Only filter out 'Disabled' (Administratively down) or 'Not Present'
|
|
$adapters = $adapters | Where-Object { $_.Status -eq "Up" -or $_.Status -eq "Disconnected" }
|
|
Write-Log -Level DEBUG -Message "Filtering to active/disconnected adapters (excluding disabled)" -Module $script:ModuleName
|
|
}
|
|
|
|
# Layer 3: Exclude virtual adapter patterns (COMPREHENSIVE!)
|
|
# NOTE: We distinguish between HOST-side and GUEST-side virtual adapters:
|
|
# - HOST-side (vEthernet, VMware Network Adapter VMnet*) → EXCLUDE
|
|
# - GUEST-side (Microsoft Hyper-V Network Adapter in VM) → KEEP!
|
|
$virtualPatterns = @(
|
|
# Host-side virtualization adapters (NOT guest adapters!)
|
|
'*vEthernet*', # Hyper-V HOST virtual switch
|
|
'*VMware Network Adapter*', # VMware HOST adapters (VMnet1, VMnet8)
|
|
'*VirtualBox Host-Only*', # VirtualBox HOST-only adapter
|
|
'*Virtual*Adapter*', # Generic virtual adapters
|
|
'*Container*', '*WSL*', '*Docker*',
|
|
# Generic VPN protocols
|
|
'*VPN*', '*OpenVPN*', '*WireGuard*', '*TAP*',
|
|
'*L2TP*', '*IKEv2*', '*RAS*', '*PPTP*',
|
|
# Consumer VPN vendors
|
|
'*NordVPN*', '*NordLynx*', '*ExpressVPN*', '*ProtonVPN*', '*Mullvad*',
|
|
# Enterprise VPN vendors
|
|
'*Cisco*', '*Pulse*', '*FortiClient*',
|
|
'*Palo Alto*', '*PANGP*', # Palo Alto GlobalProtect (no "VPN" in name!)
|
|
'*F5*', '*Checkpoint*', '*Check Point*', '*Sonicwall*', '*Juniper*',
|
|
# Tunnel adapters
|
|
'*Tunnel*', '*Teredo*', '*6to4*', '*ISATAP*', '*Loopback*'
|
|
)
|
|
|
|
# Layer 4: Check for active Windows VPN connections
|
|
$activeVpnConnections = @()
|
|
try {
|
|
$vpnConns = Get-VpnConnection -ErrorAction SilentlyContinue
|
|
$activeVpnConnections = $vpnConns | Where-Object { $_.ConnectionStatus -eq 'Connected' }
|
|
}
|
|
catch {
|
|
Write-Log -Level DEBUG -Message "Get-VpnConnection not available or failed: $_" -Module $script:ModuleName
|
|
}
|
|
|
|
$filteredAdapters = @($adapters | Where-Object {
|
|
$description = $_.InterfaceDescription
|
|
$name = $_.Name
|
|
$skipAdapter = $false
|
|
$skipReason = ""
|
|
|
|
# Check if adapter matches any virtual pattern
|
|
foreach ($pattern in $virtualPatterns) {
|
|
if ($description -like $pattern -or $name -like $pattern) {
|
|
$skipAdapter = $true
|
|
$skipReason = "Pattern match: $pattern"
|
|
break
|
|
}
|
|
}
|
|
|
|
# Check if InterfaceType is Tunnel (131)
|
|
if (-not $skipAdapter -and $_.InterfaceType -eq 131) {
|
|
$skipAdapter = $true
|
|
$skipReason = "InterfaceType = 131 (Tunnel)"
|
|
}
|
|
|
|
# Check MediaType for Tunnel
|
|
if (-not $skipAdapter -and $_.MediaType -match "Tunnel") {
|
|
$skipAdapter = $true
|
|
$skipReason = "MediaType contains 'Tunnel'"
|
|
}
|
|
|
|
# Check for native Windows VPN connection
|
|
if (-not $skipAdapter -and $activeVpnConnections) {
|
|
$currentAdapterAlias = $_.InterfaceAlias
|
|
$matchingVpn = $activeVpnConnections | Where-Object { $_.InterfaceAlias -eq $currentAdapterAlias }
|
|
if ($matchingVpn) {
|
|
$skipAdapter = $true
|
|
$skipReason = "Native Windows VPN active: $($matchingVpn.Name)"
|
|
}
|
|
}
|
|
|
|
if ($skipAdapter) {
|
|
Write-Log -Level DEBUG -Message "Excluding adapter: $name - $skipReason" -Module $script:ModuleName
|
|
}
|
|
|
|
-not $skipAdapter
|
|
}) # Close @( array wrapper
|
|
|
|
if ($filteredAdapters.Count -eq 0) {
|
|
Write-Log -Level WARNING -Message "No physical network adapters found" -Module $script:ModuleName
|
|
return @()
|
|
}
|
|
|
|
Write-Log -Level DEBUG -Message "Found $($filteredAdapters.Count) physical network adapter(s)" -Module $script:ModuleName
|
|
|
|
foreach ($adapter in $filteredAdapters) {
|
|
Write-Log -Level DEBUG -Message " - $($adapter.Name) ($($adapter.InterfaceDescription)) [Status: $($adapter.Status)]" -Module $script:ModuleName
|
|
}
|
|
|
|
return $filteredAdapters # Already wrapped as array in line 83
|
|
}
|
|
catch {
|
|
Write-ErrorLog -Message "Failed to retrieve physical network adapters" -Module $script:ModuleName -ErrorRecord $_
|
|
return @()
|
|
}
|
|
}
|