128 lines
4.2 KiB
PowerShell
128 lines
4.2 KiB
PowerShell
param(
|
|
[string]$HostLanIp = "192.168.178.58",
|
|
[string]$FritzBoxIp = "192.168.178.1",
|
|
[ValidateSet("LanPreflight", "Guest")]
|
|
[string]$Mode = "LanPreflight",
|
|
[string]$ReportPath = ""
|
|
)
|
|
|
|
$ErrorActionPreference = "Stop"
|
|
|
|
function Test-TcpPort {
|
|
param(
|
|
[string]$RemoteHost,
|
|
[int]$Port,
|
|
[int]$TimeoutMs = 1500
|
|
)
|
|
|
|
$client = [System.Net.Sockets.TcpClient]::new()
|
|
try {
|
|
$async = $client.BeginConnect($RemoteHost, $Port, $null, $null)
|
|
$ok = $async.AsyncWaitHandle.WaitOne($TimeoutMs, $false)
|
|
if (-not $ok) {
|
|
return $false
|
|
}
|
|
$client.EndConnect($async)
|
|
return $true
|
|
} catch {
|
|
return $false
|
|
} finally {
|
|
$client.Close()
|
|
}
|
|
}
|
|
|
|
function Add-Result {
|
|
param(
|
|
[System.Collections.Generic.List[object]]$Results,
|
|
[string]$Name,
|
|
[string]$Target,
|
|
[bool]$Reachable,
|
|
[string]$ExpectedGuest,
|
|
[string]$Risk
|
|
)
|
|
|
|
$Results.Add([pscustomobject]@{
|
|
Name = $Name
|
|
Target = $Target
|
|
Reachable = $Reachable
|
|
ExpectedFromGuest = $ExpectedGuest
|
|
RiskIfReachableFromGuest = $Risk
|
|
})
|
|
}
|
|
|
|
$adapters = Get-NetIPConfiguration |
|
|
Where-Object { $_.IPv4Address -and $_.NetAdapter.Status -eq "Up" } |
|
|
Select-Object InterfaceAlias,
|
|
@{Name="IPv4";Expression={$_.IPv4Address.IPAddress -join ", "}},
|
|
@{Name="Gateway";Expression={$_.IPv4DefaultGateway.NextHop -join ", "}},
|
|
@{Name="DnsServer";Expression={$_.DNSServer.ServerAddresses -join ", "}}
|
|
|
|
$results = [System.Collections.Generic.List[object]]::new()
|
|
|
|
Add-Result $results "Unraid HTTP/LAN" "${HostLanIp}:80" (Test-TcpPort $HostLanIp 80) "blocked" "Guest can reach LAN web entrypoint directly"
|
|
Add-Result $results "Unraid HTTPS/LAN" "${HostLanIp}:443" (Test-TcpPort $HostLanIp 443) "blocked" "Guest can reach LAN HTTPS entrypoint directly"
|
|
Add-Result $results "Gitea SSH/LAN" "${HostLanIp}:222" (Test-TcpPort $HostLanIp 222) "blocked" "Guest can reach Git SSH"
|
|
Add-Result $results "AdGuard Admin/LAN" "${HostLanIp}:8082" (Test-TcpPort $HostLanIp 8082) "blocked" "Guest can reach AdGuard admin UI"
|
|
Add-Result $results "InfluxDB LAN" "${HostLanIp}:8181" (Test-TcpPort $HostLanIp 8181) "blocked" "Guest can reach InfluxDB writer endpoint"
|
|
Add-Result $results "FRITZ!Box LAN UI" "${FritzBoxIp}:80" (Test-TcpPort $FritzBoxIp 80) "blocked-or-guest-gateway-only" "Guest can reach main router UI"
|
|
|
|
$risk = if ($Mode -eq "Guest") {
|
|
$results | Where-Object {
|
|
$_.ExpectedFromGuest -like "blocked*" -and $_.Reachable
|
|
}
|
|
} else {
|
|
$results | Where-Object {
|
|
$_.Name -in @("AdGuard Admin/LAN", "InfluxDB LAN") -and $_.Reachable
|
|
}
|
|
}
|
|
|
|
$timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
|
|
$lines = [System.Collections.Generic.List[string]]::new()
|
|
$lines.Add("# Guest/IoT Isolation Check")
|
|
$lines.Add("")
|
|
$lines.Add("Timestamp: $timestamp")
|
|
$lines.Add("Mode: $Mode")
|
|
$lines.Add("Host LAN IP: $HostLanIp")
|
|
$lines.Add("FRITZ!Box IP: $FritzBoxIp")
|
|
$lines.Add("Risk count: $($risk.Count)")
|
|
$lines.Add("")
|
|
$lines.Add("## Active Network Adapters")
|
|
$lines.Add("")
|
|
$lines.Add("| Interface | IPv4 | Gateway | DNS |")
|
|
$lines.Add("|---|---|---|---|")
|
|
foreach ($adapter in $adapters) {
|
|
$lines.Add("| $($adapter.InterfaceAlias) | $($adapter.IPv4) | $($adapter.Gateway) | $($adapter.DnsServer) |")
|
|
}
|
|
$lines.Add("")
|
|
$lines.Add("## Port Tests")
|
|
$lines.Add("")
|
|
$lines.Add("| Name | Target | Reachable | Expected from guest Wi-Fi | Risk if reachable from guest |")
|
|
$lines.Add("|---|---|---:|---|---|")
|
|
foreach ($result in $results) {
|
|
$lines.Add("| $($result.Name) | $($result.Target) | $($result.Reachable) | $($result.ExpectedFromGuest) | $($result.RiskIfReachableFromGuest) |")
|
|
}
|
|
$lines.Add("")
|
|
$lines.Add("## Interpretation")
|
|
$lines.Add("")
|
|
$lines.Add("- `LanPreflight`: reachable `80/443/222` can be normal; `8082` and `8181` should still be blocked.")
|
|
$lines.Add("- `Guest`: all listed LAN targets should be blocked. Public domains may still work via the internet path.")
|
|
$lines.Add("- A non-zero risk count means the selected mode failed.")
|
|
|
|
$text = $lines -join [Environment]::NewLine
|
|
|
|
if ($ReportPath) {
|
|
$parent = Split-Path -Parent $ReportPath
|
|
if ($parent) {
|
|
New-Item -ItemType Directory -Force -Path $parent | Out-Null
|
|
}
|
|
Set-Content -Path $ReportPath -Value $text -Encoding UTF8
|
|
}
|
|
|
|
Write-Output $text
|
|
|
|
if ($risk.Count -gt 0) {
|
|
exit 2
|
|
}
|
|
|
|
exit 0
|