Files
linux-scripts/windows-network-smoke-tests.ps1
T
chiefgeek a1a17e81a1 Sync all scripts from website downloads — 352 scripts total
Includes updated JS challenge scripts with Claude-User whitelist,
same-site referer bypass, Blackbox-Exporter allowed bot, and all
new exporters, cheat sheets, and automation scripts.
2026-05-25 03:31:08 +02:00

401 lines
17 KiB
PowerShell

######################################################################################
#### windows-network-smoke-tests.ps1 — Verify Windows network configuration ####
#### Checks NIC status, IP config, gateway, DNS, DC, firewall, NTP, link speed. ####
#### ####
#### Author: Phil Connor ####
#### Contact: contact@mylinux.work ####
#### License: MIT ####
#### Version: 1.0 ####
#### ####
#### Usage: .\windows-network-smoke-tests.ps1 ####
#### .\windows-network-smoke-tests.ps1 -Gateway 10.0.0.1 ####
#### .\windows-network-smoke-tests.ps1 -OutputFormat tap ####
#### ####
#### See -Help for all options. ####
######################################################################################
[CmdletBinding()]
param(
[string]$Gateway,
[string]$DnsServer,
[string]$DomainController,
[int]$ExpectedLinkSpeedMbps = 1000,
[string]$NtpServer,
[string]$TestUrl = "http://www.msftconnecttest.com/connecttest.txt",
[ValidateSet("text", "tap")]
[string]$OutputFormat = "text",
[switch]$NoColor,
[switch]$Help
)
$ErrorActionPreference = "Continue"
# ============================================================================
# STATE & HELPERS
# ============================================================================
$script:Pass = 0; $script:Fail = 0; $script:Skip = 0; $script:Total = 0
$script:Results = @(); $script:StartTime = $null
function Write-Color {
param([string]$Text, [string]$Color = "White")
if ($NoColor) { Write-Host $Text } else { Write-Host $Text -ForegroundColor $Color }
}
function Write-Log { param([string]$Msg) Write-Color "[INFO] $Msg" "Cyan" }
function Write-Warn { param([string]$Msg) Write-Color "[WARN] $Msg" "Yellow" }
function Write-Err { param([string]$Msg) Write-Color "[ERROR] $Msg" "Red" }
function Record-Pass {
param([string]$Name, [string]$Detail = "")
$script:Pass++; $script:Total++
$script:Results += [PSCustomObject]@{ Status = "PASS"; Name = $Name; Detail = $Detail }
if ($OutputFormat -eq "tap") {
Write-Host "ok $($script:Total) - $Name"
} else {
$msg = " $(if ($NoColor) { '[PASS]' } else { [char]0x2713 }) $Name"
if ($Detail) { $msg += " - $Detail" }
Write-Color $msg "Green"
}
}
function Record-Fail {
param([string]$Name, [string]$Detail = "")
$script:Fail++; $script:Total++
$script:Results += [PSCustomObject]@{ Status = "FAIL"; Name = $Name; Detail = $Detail }
if ($OutputFormat -eq "tap") {
Write-Host "not ok $($script:Total) - $Name"
if ($Detail) { Write-Host " # $Detail" }
} else {
$msg = " $(if ($NoColor) { '[FAIL]' } else { [char]0x2717 }) $Name"
if ($Detail) { $msg += " - $Detail" }
Write-Color $msg "Red"
}
}
function Record-Skip {
param([string]$Name, [string]$Reason = "")
$script:Skip++; $script:Total++
$script:Results += [PSCustomObject]@{ Status = "SKIP"; Name = $Name; Detail = $Reason }
if ($OutputFormat -eq "tap") {
Write-Host "ok $($script:Total) - $Name # SKIP $Reason"
} else {
$msg = " $(if ($NoColor) { '[SKIP]' } else { [char]0x2298 }) $Name"
if ($Reason) { $msg += " - $Reason" }
Write-Color $msg "Yellow"
}
}
function Write-TapHeader { Write-Host "TAP version 13" }
function Write-TapFooter {
Write-Host "1..$($script:Total)"
Write-Host "# pass $($script:Pass)"
Write-Host "# fail $($script:Fail)"
Write-Host "# skip $($script:Skip)"
}
function Write-Summary {
$duration = [math]::Floor(((Get-Date) - $script:StartTime).TotalSeconds)
Write-Host ""
$separator = [string]::new([char]0x2500, 50)
Write-Color $separator "White"
Write-Color "Windows Network Smoke Tests - Summary" "White"
$summaryLine = " $($script:Pass) passed $($script:Fail) failed $($script:Skip) skipped (${duration}s)"
Write-Host $summaryLine
Write-Color $separator "White"
if ($script:Fail -eq 0) { Write-Color "All tests passed." "Green" }
else { Write-Color "$($script:Fail) test(s) failed." "Red" }
}
function Show-Usage {
@"
Usage: .\windows-network-smoke-tests.ps1 [OPTIONS]
Smoke-test Windows network configuration. PowerShell 5.1+, no modules.
Auto-detects gateway, DNS, DC, and NTP when not specified.
Parameters:
-Gateway STR Default gateway IP (default: auto-detect)
-DnsServer STR DNS server IP (default: auto-detect)
-DomainController STR Domain controller hostname/IP (default: auto-detect)
-ExpectedLinkSpeedMbps N Minimum link speed in Mbps (default: 1000)
-NtpServer STR NTP server (default: auto-detect from w32tm)
-TestUrl STR URL for internet test (default: msftconnecttest.com)
-OutputFormat FORMAT Output: text (default), tap
-NoColor Disable colored output
-Help Show this help message
Examples:
.\windows-network-smoke-tests.ps1
.\windows-network-smoke-tests.ps1 -Gateway 10.0.0.1 -DnsServer 10.0.0.53
.\windows-network-smoke-tests.ps1 -DomainController dc01.corp.local
.\windows-network-smoke-tests.ps1 -ExpectedLinkSpeedMbps 10000
.\windows-network-smoke-tests.ps1 -OutputFormat tap
.\windows-network-smoke-tests.ps1 -NoColor
"@
}
# ============================================================================
# TESTS
# ============================================================================
function Test-NicStatus {
try {
$adapters = Get-NetAdapter | Where-Object { $_.Status -eq "Up" }
if ($adapters -and @($adapters).Count -gt 0) {
$first = @($adapters)[0].Name
Record-Pass "NIC status ($first is Up)"
} else {
Record-Fail "NIC status" "no adapter is Up"
}
} catch { Record-Fail "NIC status" $_.Exception.Message }
}
function Test-IpConfiguration {
try {
$ips = Get-NetIPAddress -AddressFamily IPv4 -ErrorAction Stop |
Where-Object { $_.IPAddress -ne "127.0.0.1" -and $_.PrefixOrigin -ne "WellKnown" }
if ($ips) {
$first = @($ips)[0]
Record-Pass "IPv4 address assigned ($($first.IPAddress)/$($first.PrefixLength))"
} else {
Record-Fail "IPv4 address assigned" "no IPv4 address found"
}
} catch { Record-Fail "IPv4 address assigned" $_.Exception.Message }
}
function Test-DefaultGateway {
$gw = $Gateway
if (-not $gw) {
try {
$route = Get-NetRoute -DestinationPrefix "0.0.0.0/0" -ErrorAction Stop | Select-Object -First 1
$gw = $route.NextHop
} catch {
Record-Fail "default gateway exists" "no default route found"
return
}
}
if (-not $gw -or $gw -eq "0.0.0.0") {
Record-Fail "default gateway exists" "no gateway configured"
return
}
Record-Pass "default gateway exists ($gw)"
try {
$ping = Test-Connection -ComputerName $gw -Count 2 -Quiet -ErrorAction Stop
if ($ping) { Record-Pass "default gateway reachable" }
else { Record-Fail "default gateway reachable" "$gw did not respond" }
} catch { Record-Fail "default gateway reachable" $_.Exception.Message }
}
function Test-DnsServers {
$dns = $DnsServer
if (-not $dns) {
try {
$dnsAddrs = Get-DnsClientServerAddress -AddressFamily IPv4 -ErrorAction Stop |
Where-Object { $_.ServerAddresses.Count -gt 0 } |
Select-Object -ExpandProperty ServerAddresses -First 1
if ($dnsAddrs) { $dns = @($dnsAddrs)[0] }
} catch { }
}
if ($dns) { Record-Pass "DNS servers configured ($dns)" }
else { Record-Fail "DNS servers configured" "no DNS servers found" }
}
function Test-DnsResolution {
try {
$result = Resolve-DnsName -Name "www.microsoft.com" -Type A -DnsOnly -ErrorAction Stop
if ($result) { Record-Pass "DNS resolution (www.microsoft.com)" }
else { Record-Fail "DNS resolution" "no result for www.microsoft.com" }
} catch { Record-Fail "DNS resolution" $_.Exception.Message }
}
function Test-DomainController {
$dc = $DomainController
if (-not $dc) {
try {
$nltest = nltest /dsgetdc: 2>&1
$dcLine = $nltest | Select-String "DC: \\\\"
if ($dcLine) { $dc = ($dcLine -replace ".*DC: \\\\", "").Trim() }
} catch { }
}
if (-not $dc) {
$isDomain = $false
try {
$cs = Get-CimInstance -ClassName Win32_ComputerSystem -ErrorAction Stop
if ($cs.PartOfDomain) { $isDomain = $true }
} catch { }
if (-not $isDomain) {
Record-Skip "domain controller reachable" "not domain-joined"
Record-Skip "domain controller LDAP port 389" "not domain-joined"
} else {
Record-Fail "domain controller reachable" "domain-joined but DC not found"
Record-Skip "domain controller LDAP port 389" "DC not identified"
}
return
}
try {
$ping = Test-Connection -ComputerName $dc -Count 2 -Quiet -ErrorAction Stop
if ($ping) { Record-Pass "domain controller reachable ($dc)" }
else { Record-Fail "domain controller reachable" "$dc did not respond" }
} catch { Record-Fail "domain controller reachable" $_.Exception.Message }
try {
$ldap = Test-NetConnection -ComputerName $dc -Port 389 -WarningAction SilentlyContinue -ErrorAction Stop
if ($ldap.TcpTestSucceeded) { Record-Pass "domain controller LDAP port 389" }
else { Record-Fail "domain controller LDAP port 389" "TCP 389 connection failed" }
} catch { Record-Fail "domain controller LDAP port 389" $_.Exception.Message }
}
function Test-FirewallProfile {
try {
$profiles = Get-NetFirewallProfile -ErrorAction Stop | Where-Object { $_.Enabled -eq $true }
if (-not $profiles) {
Record-Fail "firewall profile" "no firewall profile is enabled"
return
}
$activeNames = ($profiles | ForEach-Object { $_.Name }) -join ", "
$hasPublic = $profiles | Where-Object { $_.Name -eq "Public" }
if ($hasPublic) { Record-Fail "firewall profile ($activeNames)" "Public profile is active - expected Domain or Private" }
else { Record-Pass "firewall profile ($activeNames)" }
} catch { Record-Fail "firewall profile" $_.Exception.Message }
}
function Test-FirewallRules {
$checks = @(
@{ Name = "RDP"; Pattern = "*Remote Desktop*" }
@{ Name = "WinRM"; Pattern = "*Windows Remote Management*" }
@{ Name = "ICMP"; Pattern = "*ICMPv4*" }
)
$found = @(); $missing = @()
foreach ($check in $checks) {
try {
$rule = Get-NetFirewallRule -Enabled True -ErrorAction SilentlyContinue |
Where-Object { $_.DisplayName -like $check.Pattern } | Select-Object -First 1
if ($rule) { $found += $check.Name } else { $missing += $check.Name }
} catch { $missing += $check.Name }
}
if ($missing.Count -eq 0) { Record-Pass "firewall rules ($($found -join ', '))" }
elseif ($found.Count -gt 0) { Record-Fail "firewall rules" "missing: $($missing -join ', '); found: $($found -join ', ')" }
else { Record-Fail "firewall rules" "none of RDP, WinRM, ICMP rules found enabled" }
}
function Test-NtpSync {
try {
$status = w32tm /query /status 2>&1
if ($LASTEXITCODE -ne 0) {
Record-Fail "NTP synchronization" "w32tm query failed - is the Windows Time service running?"
return
}
$sourceLine = $status | Select-String "Source:"
$source = if ($sourceLine) { ($sourceLine -replace "Source:\s*", "").Trim() } else { "unknown" }
if ($source -match "Free-Running|Local CMOS|VM IC") {
Record-Fail "NTP synchronization" "source is $source - not synced to a remote server"
return
}
$lastSync = $status | Select-String "Last Successful Sync Time:"
if ($lastSync) { Record-Pass "NTP synchronized ($source)" }
else { Record-Fail "NTP synchronization" "no successful sync recorded" }
} catch { Record-Fail "NTP synchronization" $_.Exception.Message }
}
function Test-TimeDrift {
$ntp = $NtpServer
if (-not $ntp) {
try {
$cfg = w32tm /query /status 2>&1
$sourceLine = $cfg | Select-String "Source:"
if ($sourceLine) { $ntp = ($sourceLine -replace "Source:\s*", "").Trim() }
} catch { }
}
if (-not $ntp -or $ntp -match "Free-Running|Local CMOS|VM IC") {
Record-Skip "time drift" "no valid NTP source available"
return
}
try {
$strip = w32tm /stripchart /computer:$ntp /samples:1 /dataonly 2>&1
if ($LASTEXITCODE -ne 0) {
Record-Fail "time drift" "w32tm stripchart failed for $ntp"
return
}
$offsetLine = $strip | Select-String "[\+\-]?\d+\.\d+s" | Select-Object -Last 1
if ($offsetLine) {
$match = [regex]::Match($offsetLine, "([\+\-]?\d+\.\d+)s")
if ($match.Success) {
$offset = [math]::Abs([double]$match.Groups[1].Value)
if ($offset -le 1.0) { Record-Pass "time drift (${offset}s offset from $ntp)" }
else { Record-Fail "time drift" "${offset}s offset exceeds 1.0s threshold" }
} else { Record-Fail "time drift" "could not parse offset from w32tm output" }
} else { Record-Fail "time drift" "no offset data in w32tm output" }
} catch { Record-Fail "time drift" $_.Exception.Message }
}
function Test-LinkSpeed {
try {
$adapter = Get-NetAdapter | Where-Object { $_.Status -eq "Up" } | Select-Object -First 1
if (-not $adapter) { Record-Fail "link speed" "no active adapter found"; return }
$linkSpeedStr = $adapter.LinkSpeed
$speedMbps = 0
if ($linkSpeedStr -match "(\d+(\.\d+)?)\s*Gbps") { $speedMbps = [int]([double]$Matches[1] * 1000) }
elseif ($linkSpeedStr -match "(\d+)\s*Mbps") { $speedMbps = [int]$Matches[1] }
elseif ($linkSpeedStr -match "(\d+)\s*Kbps") { $speedMbps = [int]([double]$Matches[1] / 1000) }
if ($speedMbps -ge $ExpectedLinkSpeedMbps) { Record-Pass "link speed ($speedMbps Mbps >= $ExpectedLinkSpeedMbps Mbps)" }
else { Record-Fail "link speed" "$speedMbps Mbps is below expected $ExpectedLinkSpeedMbps Mbps" }
} catch { Record-Fail "link speed" $_.Exception.Message }
}
function Test-VlanTagging {
try {
$adapters = Get-NetAdapter | Where-Object { $_.Status -eq "Up" }
if (-not $adapters) { Record-Skip "VLAN tagging" "no active adapter"; return }
$tagged = @($adapters) | Where-Object { $_.VlanID -and $_.VlanID -ne 0 }
if ($tagged) {
$first = @($tagged)[0]
Record-Pass "VLAN tagging ($($first.Name) VLAN $($first.VlanID))"
} else { Record-Skip "VLAN tagging" "adapter not VLAN-tagged" }
} catch { Record-Skip "VLAN tagging" "VlanID property not available" }
}
function Test-InternetConnectivity {
try {
$response = Invoke-WebRequest -Uri $TestUrl -UseBasicParsing -TimeoutSec 10 -ErrorAction Stop
if ($response.StatusCode -eq 200) { Record-Pass "internet connectivity (HTTP $($response.StatusCode))" }
else { Record-Fail "internet connectivity" "HTTP $($response.StatusCode)" }
} catch { Record-Fail "internet connectivity" $_.Exception.Message }
}
# ============================================================================
# MAIN
# ============================================================================
if ($Help) { Show-Usage; exit 0 }
$script:StartTime = Get-Date
if ($OutputFormat -eq "tap") {
Write-TapHeader
} else {
Write-Host ""
Write-Color "Windows Network Smoke Tests" "White"
Write-Host "Host: $($env:COMPUTERNAME)"
Write-Host "Time: $(Get-Date -Format 'yyyy-MM-ddTHH:mm:ssZ')"
Write-Host ""
}
Test-NicStatus
Test-IpConfiguration
Test-DefaultGateway
Test-DnsServers
Test-DnsResolution
Test-DomainController
Test-FirewallProfile
Test-FirewallRules
Test-NtpSync
Test-TimeDrift
Test-LinkSpeed
Test-VlanTagging
Test-InternetConnectivity
if ($OutputFormat -eq "tap") { Write-TapFooter } else { Write-Summary }
if ($script:Fail -eq 0) { exit 0 } else { exit 1 }