Files
lxs/windows/tools/net-diag.ps1
T

198 lines
7.4 KiB
PowerShell

<#
LXS - Network Diagnostics (Windows)
Description: Inspect and repair the network stack.
Everything is read-only except option 8 (stack reset).
Repo: https://git.hyko.cx/hykocx/lxs
#>
# Load LXS common library (colors, UI helpers, spinner, loggers, guards).
# Prefers the sibling ..\lib\common.ps1 (repo checkout or installed layout) and
# only hits the network when this script is run standalone.
$LxsRawBase = if ($env:LXS_RAW_BASE) { $env:LXS_RAW_BASE } else { 'https://git.hyko.cx/hykocx/lxs/raw/branch/main' }
if (-not $env:LXS_RAW_PLATFORM_BASE) { $env:LXS_RAW_PLATFORM_BASE = "$LxsRawBase/windows" }
$LxsLibPath = if ($PSScriptRoot) { Join-Path $PSScriptRoot '..\lib\common.ps1' } else { $null }
if ($LxsLibPath -and (Test-Path $LxsLibPath)) {
. $LxsLibPath
} else {
try {
$LxsLibSource = Invoke-RestMethod -Uri "$env:LXS_RAW_PLATFORM_BASE/lib/common.ps1" -UseBasicParsing -ErrorAction Stop
} catch {
Write-Error 'Failed to fetch lib/common.ps1'
exit 1
}
. ([scriptblock]::Create($LxsLibSource))
}
$env:LXS_LOG_FILE = Join-Path (Get-LxsTempDir) 'lxs_net_diag.log'
function Show-LxsIpConfiguration {
Clear-Host
Show-LxsBoxTop -Title 'IP CONFIGURATION'
Write-Host ''
try {
Get-NetIPConfiguration -Detailed -ErrorAction Stop | ForEach-Object {
Write-Host "$($script:Cyan)$($script:Bold)$($_.InterfaceAlias)$($script:NC) $($script:Gray)($($_.InterfaceDescription))$($script:NC)"
Write-Host " Status : $($_.NetAdapter.Status) | MAC: $($_.NetAdapter.MacAddress) | Speed: $($_.NetAdapter.LinkSpeed)"
Write-Host " IPv4 : $($_.IPv4Address.IPAddress -join ', ')"
Write-Host " IPv6 : $($_.IPv6Address.IPAddress -join ', ')"
Write-Host " Gateway : $($_.IPv4DefaultGateway.NextHop -join ', ')"
Write-Host " DNS : $($_.DNSServer.ServerAddresses -join ', ')"
Write-Host ''
}
} catch {
Write-LxsWarn 'Get-NetIPConfiguration unavailable; falling back to ipconfig /all.'
ipconfig /all | Out-String | Write-Host
}
}
function Show-LxsListeningPorts {
Clear-Host
Show-LxsBoxTop -Title 'LISTENING PORTS'
Write-Host ''
try {
$rows = Get-NetTCPConnection -State Listen -ErrorAction Stop | ForEach-Object {
$procName = try { (Get-Process -Id $_.OwningProcess -ErrorAction Stop).ProcessName } catch { 'unknown' }
[pscustomobject]@{
Local = "$($_.LocalAddress):$($_.LocalPort)"
Port = $_.LocalPort
PID = $_.OwningProcess
Process = $procName
}
}
$rows | Sort-Object Port | Format-Table -AutoSize Local, PID, Process | Out-String | Write-Host
} catch {
Write-LxsWarn 'Get-NetTCPConnection unavailable; falling back to netstat.'
netstat -ano | Select-String 'LISTENING' | Out-String | Write-Host
}
}
function Clear-LxsDnsCache {
Clear-Host
Show-LxsBoxTop -Title 'FLUSH DNS CACHE'
Write-Host ''
try {
Clear-DnsClientCache -ErrorAction Stop
Write-LxsOk 'DNS resolver cache flushed'
} catch {
Write-LxsWarn 'Clear-DnsClientCache failed; falling back to ipconfig /flushdns.'
ipconfig /flushdns | Out-String | Write-Host
}
}
function Invoke-LxsPing {
Clear-Host
Show-LxsBoxTop -Title 'PING'
Write-Host ''
$target = Read-Host -Prompt 'Host to ping (default: 1.1.1.1)'
if ([string]::IsNullOrWhiteSpace($target)) { $target = '1.1.1.1' }
Write-Host ''
ping.exe -n 4 $target | Out-String | Write-Host
}
function Invoke-LxsTraceroute {
Clear-Host
Show-LxsBoxTop -Title 'TRACEROUTE'
Write-Host ''
$target = Read-Host -Prompt 'Host to trace (default: 1.1.1.1)'
if ([string]::IsNullOrWhiteSpace($target)) { $target = '1.1.1.1' }
Write-Host ''
Write-LxsInfo "Tracing route to $target (this can take a minute)..."
tracert.exe -d -h 20 $target | Out-String | Write-Host
}
function Test-LxsRemotePort {
Clear-Host
Show-LxsBoxTop -Title 'TEST TCP PORT'
Write-Host ''
$target = Read-Host -Prompt 'Host'
if ([string]::IsNullOrWhiteSpace($target)) { Write-LxsErr 'No host given.'; return }
$port = Read-Host -Prompt 'Port'
if ($port -notmatch '^\d+$') { Write-LxsErr 'Port must be a number.'; return }
Write-Host ''
try {
$result = Test-NetConnection -ComputerName $target -Port ([int]$port) -WarningAction SilentlyContinue -ErrorAction Stop
if ($result.TcpTestSucceeded) {
Write-LxsOk "${target}:${port} is reachable ($($result.RemoteAddress))"
} else {
Write-LxsErr "${target}:${port} is NOT reachable"
}
} catch {
Write-LxsErr "Test failed: $($_.Exception.Message)"
}
}
function Show-LxsPublicIp {
Clear-Host
Show-LxsBoxTop -Title 'PUBLIC IP'
Write-Host ''
Write-LxsInfo 'Querying...'
Write-Host ''
Write-Host " $($script:White)$($script:Bold)$(Get-LxsPublicIP)$($script:NC)"
Write-Host ''
}
function Reset-LxsNetworkStack {
Clear-Host
Show-LxsBoxTop -Title 'RESET NETWORK STACK' -Right 'DESTRUCTIVE'
Write-Host ''
Write-Host 'This resets the Winsock catalog and the TCP/IP stack. It clears'
Write-Host 'third-party LSP entries, static IP settings and proxy configuration,'
Write-Host "and $($script:Bold)requires a reboot$($script:NC) to take effect."
Write-Host ''
if (-not (Confirm-LxsAction -Question 'Reset the network stack now?')) {
Write-LxsInfo 'Cancelled.'
return
}
if (-not (Test-LxsAdmin)) {
Write-LxsErr 'This action requires administrator rights. Re-run lxs from an elevated terminal.'
return
}
Write-Host ''
netsh winsock reset | Out-String | Write-Host
netsh int ip reset | Out-String | Write-Host
Clear-DnsClientCache -ErrorAction SilentlyContinue
Write-Host ''
Write-LxsOk 'Network stack reset'
Write-LxsWarn 'Reboot required for the change to take effect.'
}
function Show-LxsNetDiagMenu {
while ($true) {
Clear-Host
Show-LxsBoxTop -Title 'NETWORK DIAG'
Write-Host ''
Show-LxsMenuItem '1' 'Show IP configuration'
Show-LxsMenuItem '2' 'Show listening ports'
Show-LxsMenuItem '3' 'Flush DNS cache'
Show-LxsMenuItem '4' 'Ping a host'
Show-LxsMenuItem '5' 'Traceroute a host'
Show-LxsMenuItem '6' 'Test a TCP port'
Show-LxsMenuItem '7' 'Show public IP'
Show-LxsMenuItem '8' 'Reset network stack' 'needs admin + reboot'
Show-LxsMenuItem '0' 'Back' '' -Exit
Write-Host ''
Show-LxsBoxBottom
Write-Host ''
$choice = Read-LxsChoice
Write-Host ''
switch ($choice) {
'1' { Show-LxsIpConfiguration; Read-LxsEnter }
'2' { Show-LxsListeningPorts; Read-LxsEnter }
'3' { Clear-LxsDnsCache; Read-LxsEnter }
'4' { Invoke-LxsPing; Read-LxsEnter }
'5' { Invoke-LxsTraceroute; Read-LxsEnter }
'6' { Test-LxsRemotePort; Read-LxsEnter }
'7' { Show-LxsPublicIp; Read-LxsEnter }
'8' { Reset-LxsNetworkStack; Read-LxsEnter }
'0' { return }
default { Write-LxsErr 'Invalid protocol. Select 0-8.'; Start-Sleep -Seconds 1 }
}
}
}
if (-not (Assert-LxsWindows)) { exit 1 }
Show-LxsNetDiagMenu
exit 75