Public/network/Export-NetworkConfig.ps1
|
#Requires -Version 5.1 function Export-NetworkConfig { <# .SYNOPSIS Exports a complete network configuration snapshot to JSON or displays it as a summary. .DESCRIPTION Collects all network configuration data from one or more computers into a single structured object: adapters, IP addresses, routes, DNS, ARP cache, listening ports, and firewall profile status. The output can be piped to ConvertTo-Json for documentation, compared between machines, or used for audit/compliance purposes. .PARAMETER ComputerName One or more computer names to collect config from. Defaults to the local machine. Accepts pipeline input. .PARAMETER Credential Optional credential for remote computer connections. .PARAMETER Path Optional file path to export JSON directly. If not specified, returns objects. .PARAMETER IncludeFirewall Include Windows Firewall profile status. Default: $true. .PARAMETER IncludeListeners Include listening ports. Default: $true. .PARAMETER IncludeARP Include ARP cache. Default: $false (can be large). .EXAMPLE Export-NetworkConfig Returns a complete network config object for the local machine. .EXAMPLE Export-NetworkConfig -Path 'C:\docs\netconfig.json' Exports local network config to a JSON file. .EXAMPLE Export-NetworkConfig -ComputerName 'SRV01' -Credential (Get-Credential) | ConvertTo-Json -Depth 5 Exports remote server config as JSON. .EXAMPLE 'SRV01', 'SRV02' | Export-NetworkConfig -IncludeARP Exports config including ARP cache from two servers. .OUTPUTS PSWinOps.NetworkConfig .NOTES Author: Franck SALLET Version: 1.0.0 Last Modified: 2026-03-21 Requires: PowerShell 5.1+ / Windows only Permissions: Admin recommended for full details, required for remote #> [CmdletBinding()] [OutputType('PSWinOps.NetworkConfig')] param ( [Parameter(Mandatory = $false, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true)] [ValidateNotNullOrEmpty()] [Alias('CN', 'DNSHostName')] [string[]]$ComputerName = $env:COMPUTERNAME, [Parameter(Mandatory = $false)] [PSCredential]$Credential, [Parameter(Mandatory = $false)] [string]$Path, [Parameter(Mandatory = $false)] [bool]$IncludeFirewall = $true, [Parameter(Mandatory = $false)] [bool]$IncludeListeners = $true, [Parameter(Mandatory = $false)] [switch]$IncludeARP ) begin { Write-Verbose "[$($MyInvocation.MyCommand)] Starting network config export" $localNames = @($env:COMPUTERNAME, 'localhost', '.') $hasCredential = $PSBoundParameters.ContainsKey('Credential') $queryScriptBlock = { param([bool]$CollectFirewall, [bool]$CollectListeners, [bool]$CollectARP) $config = @{} # Hostname $config['Hostname'] = $env:COMPUTERNAME # Adapters $config['Adapters'] = @(Get-NetAdapter -ErrorAction SilentlyContinue | ForEach-Object { @{ Name = $_.Name Description = $_.InterfaceDescription Status = [string]$_.Status Speed = $_.LinkSpeed MacAddress = $_.MacAddress MTU = $_.MtuSize IfIndex = $_.ifIndex } }) # IP Addresses $config['IPAddresses'] = @(Get-NetIPAddress -ErrorAction SilentlyContinue | Where-Object { $_.AddressFamily -eq 2 -and $_.IPAddress -ne '127.0.0.1' } | ForEach-Object { @{ InterfaceAlias = $_.InterfaceAlias IPAddress = $_.IPAddress PrefixLength = $_.PrefixLength AddressFamily = 'IPv4' Type = [string]$_.PrefixOrigin } }) # DNS $config['DnsServers'] = @(Get-DnsClientServerAddress -ErrorAction SilentlyContinue | Where-Object { $_.ServerAddresses } | ForEach-Object { @{ InterfaceAlias = $_.InterfaceAlias Servers = $_.ServerAddresses } }) # DNS Suffix try { $dnsSuffix = (Get-DnsClient -ErrorAction SilentlyContinue | Where-Object { $_.ConnectionSpecificSuffix } | Select-Object -First 1).ConnectionSpecificSuffix $config['DnsSuffix'] = $dnsSuffix } catch { $config['DnsSuffix'] = $null } # Routes $config['Routes'] = @(Get-NetRoute -ErrorAction SilentlyContinue | Where-Object { $_.DestinationPrefix -ne 'ff00::/8' -and $_.DestinationPrefix -ne '::/0' } | Where-Object { $_.AddressFamily -eq 2 } | ForEach-Object { @{ DestinationPrefix = $_.DestinationPrefix NextHop = $_.NextHop RouteMetric = $_.RouteMetric InterfaceAlias = $_.InterfaceAlias } }) # Firewall profiles if ($CollectFirewall) { $config['FirewallProfiles'] = @(Get-NetFirewallProfile -ErrorAction SilentlyContinue | ForEach-Object { @{ Name = $_.Name Enabled = $_.Enabled DefaultInboundAction = [string]$_.DefaultInboundAction DefaultOutboundAction = [string]$_.DefaultOutboundAction } }) } # Listening ports if ($CollectListeners) { $processCache = @{} Get-Process -ErrorAction SilentlyContinue | ForEach-Object { $processCache[$_.Id] = $_.ProcessName } $config['ListeningPorts'] = @(Get-NetTCPConnection -State Listen -ErrorAction SilentlyContinue | ForEach-Object { @{ Protocol = 'TCP' LocalPort = $_.LocalPort LocalAddress = $_.LocalAddress ProcessName = if ($processCache.ContainsKey($_.OwningProcess)) { $processCache[$_.OwningProcess] } else { "PID:$($_.OwningProcess)" } } }) } # ARP cache if ($CollectARP) { $config['ARPCache'] = @(Get-NetNeighbor -AddressFamily IPv4 -ErrorAction SilentlyContinue | ForEach-Object { @{ IPAddress = $_.IPAddress LinkLayerAddr = $_.LinkLayerAddress State = [string]$_.State } }) } return $config } } process { foreach ($targetComputer in $ComputerName) { try { $isLocal = $localNames -contains $targetComputer $timestamp = Get-Date -Format 'o' Write-Verbose "[$($MyInvocation.MyCommand)] Collecting network config from '$targetComputer'" $queryArgs = @($IncludeFirewall, $IncludeListeners, $IncludeARP.IsPresent) if ($isLocal) { $rawConfig = & $queryScriptBlock @queryArgs } else { $invokeParams = @{ ComputerName = $targetComputer ScriptBlock = $queryScriptBlock ArgumentList = $queryArgs ErrorAction = 'Stop' } if ($hasCredential) { $invokeParams['Credential'] = $Credential } $rawConfig = Invoke-Command @invokeParams } $configObj = [PSCustomObject]@{ PSTypeName = 'PSWinOps.NetworkConfig' ComputerName = $targetComputer Hostname = $rawConfig.Hostname Adapters = $rawConfig.Adapters IPAddresses = $rawConfig.IPAddresses DnsServers = $rawConfig.DnsServers DnsSuffix = $rawConfig.DnsSuffix Routes = $rawConfig.Routes FirewallProfiles = $rawConfig.FirewallProfiles ListeningPorts = $rawConfig.ListeningPorts ARPCache = $rawConfig.ARPCache Timestamp = $timestamp } # Export to file if Path specified if ($Path) { $jsonPath = if ($ComputerName.Count -gt 1 -or $PSCmdlet.MyInvocation.ExpectingInput) { $dir = Split-Path $Path -Parent $base = [System.IO.Path]::GetFileNameWithoutExtension($Path) $ext = [System.IO.Path]::GetExtension($Path) Join-Path $dir "${base}_${targetComputer}${ext}" } else { $Path } $configObj | ConvertTo-Json -Depth 10 | Set-Content -Path $jsonPath -Encoding UTF8 -ErrorAction Stop Write-Verbose "[$($MyInvocation.MyCommand)] Exported config to '$jsonPath'" } $configObj } catch { Write-Error "[$($MyInvocation.MyCommand)] Failed on '$targetComputer': $_" } } } end { Write-Verbose "[$($MyInvocation.MyCommand)] Completed network config export" } } |