WatcherWall is a local-only Windows desktop widget for passive endpoint network visibility. It shows local TCP/UDP ports as compact color-coded tiles, with drill-down details for socket state and owning process metadata where Windows allows it.
The first implementation is C#/.NET WPF with a small core library. This was chosen over Electron to avoid a local browser server, reduce footprint, and use Windows networking APIs directly. The core is split behind provider interfaces so Linux/macOS providers, or a future Rust backend, can be added without mixing OS inspection code into the UI.
Implemented:
- Always-on-top, frameless, draggable, resizable WPF widget.
- System tray show/hide/quit.
- Pause/resume monitoring.
- TCP/UDP/state/search filters.
- Hide system processes, listening-only, established-only settings.
- Pin/hide port entries.
- Details window with local address, port, protocol, state, PID, process name/path, user, parent process, remote endpoints, first/last seen, access status.
- JSON snapshot export and clipboard copy.
- Minimal optional local audit log.
- Safe mock mode for UI development.
- Windows socket enumeration through IP Helper APIs.
- Guarded TCP connection termination for established IPv4 TCP connections through
SetTcpEntry. - Guarded process kill path with exact confirmation phrase and PID/process-name re-check.
- Live Traffic panel showing rolling local socket-table events for a selected port.
- Explicit tshark packet capture mode when tshark/Npcap are available.
- Detection of Wireshark/tshark/dumpcap/Npcap availability before offering packet capture.
- Optional active-tile flicker for a switch-light style display.
- WatcherWall v2 firewall mode backed by Windows Firewall COM APIs.
- Right-click tile actions for firewall status, lock/block port, open/unblock WatcherWall rules, TCP connection termination, and guarded process kill.
- Single-port, selected-port, visible-port, filtered, manual range, and guarded inbound lockdown firewall previews.
- WatcherWall-owned firewall rule tracking, verification, rollback records, and local audit entries.
- Disabled-by-default auto-block modes: notify-only, dry-run preview, or auto-block newly opened listening TCP ports.
Still intentionally limited:
- Per-process byte counters.
- PCAP save/export.
- Packet injection, active scanning, remote capture, remote control.
- Creating allow rules or weakening existing firewall policy.
WatcherWall is local-only. It does not open listening ports, create network services, expose HTTP/WebSocket/IPC/named-pipe control surfaces, collect telemetry, or send data anywhere.
The app polls local OS networking tables. It does not scan the host and does not attempt to connect to local or remote ports. Red tiles mean local inaccessible/closed/recently removed states, not maliciousness.
In v2, Block port means WatcherWall creates host firewall block rule(s). Open port or Unblock port means WatcherWall removes matching WatcherWall-created block rules only. It does not add broad allow rules, disable Wi-Fi, disable adapters, or change unrelated firewall policy.
- Green /
A: active TCP state, usually established. - Orange /
O: listening TCP socket, UDP endpoint, or open endpoint without an established remote peer. - Red /
L: inaccessible process metadata, usually access denied. - Dark red /
C: recently closed/removed socket retained briefly in local history.
Color is paired with a text glyph so color is not the only indicator.
- Socket enumeration:
GetExtendedTcpTableandGetExtendedUdpTablefromiphlpapi.dll, using owner-PID TCP/UDP tables for IPv4 and IPv6. - Process metadata:
Process.GetProcessById,OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION),QueryFullProcessImageName,OpenProcessToken,WindowsIdentity, andNtQueryInformationProcessfor parent PID. - Live Traffic v1: scoped polling of local socket tables for the selected port/process. This is intentionally not packet capture.
- Terminate TCP connection:
SetTcpEntrywithDELETE_TCB, limited to established IPv4 TCP rows. - Kill process fallback:
.NET Process.Kill(entireProcessTree: false)after confirmation and PID/name re-check. - Firewall control: Windows Firewall COM APIs through
HNetCfg.FwPolicy2andHNetCfg.FWRule. WatcherWall does not use PowerShell,netsh, shell command strings, or localized CLI parsing for firewall rules.
Runs as a normal user by default.
Usually no admin required:
- Basic TCP/UDP socket enumeration.
- Basic process name lookup for accessible processes.
- Widget UI, filters, settings, export, copy.
May require admin:
- Process path/user/token details for protected processes.
- Terminating TCP connections through
SetTcpEntry. - Killing processes owned by another user or protected by Windows.
- Creating, removing, or verifying Windows Firewall rules.
- Future raw packet capture through Npcap/dumpcap/tshark.
WatcherWall does not silently elevate. If an action is denied, it reports that administrator rights may be required.
The FW button opens the compact firewall control panel. Right-click any port tile for direct actions:
- Firewall Status shows matching WatcherWall and external block rule counts.
- Lock Port (Block) previews and applies inbound/outbound WatcherWall block rules for that port.
- Open Port (Unblock) removes matching WatcherWall-owned block rules only.
- Terminate Connection uses the existing guarded TCP connection deletion path when supported.
- Kill Process uses the existing exact-phrase process-kill confirmation flow.
Bulk controls always preview before applying. Inbound lockdown blocks detected non-allowlisted listening/local endpoints while skipping loopback-only and common essential networking ports by default. Strict lockdown includes a stronger warning and may include more ports. Multi-rule actions create rollback records under local app data so WatcherWall can revert the last rollbackable WatcherWall action.
Click a port tile, then click Live Traffic. If tshark is detected, WatcherWall asks before starting packet capture. The capture process:
- Starts
tshark.exedirectly without a shell. - Uses
-nto avoid DNS lookups. - Uses a strict BPF filter for the selected protocol and port.
- Captures into memory only.
- Writes no PCAP file.
- Stops when the Live Traffic window closes.
If tshark is missing, cannot find a usable Npcap interface, or lacks permission, WatcherWall falls back to the socket-state event view and reports the reason.
Prerequisites:
- Windows 10/11.
- .NET SDK with Windows Desktop workload/runtime. This workspace was verified with .NET 10 SDK targeting
net8.0-windows.
Build:
dotnet restore .\src\WatcherWall.App\WatcherWall.App.csproj --configfile .\NuGet.Config
dotnet build .\WatcherWall.slnx --no-restoreRun against live local socket data:
dotnet run --project .\src\WatcherWall.App\WatcherWall.App.csprojRun mock mode:
dotnet run --project .\src\WatcherWall.App\WatcherWall.App.csproj -- --mockRun tests:
dotnet run --project .\tests\WatcherWall.Tests\WatcherWall.Tests.csproj- If system processes show locked/red, run normally first and only use elevated launch when you explicitly need extra metadata.
- If TCP termination fails with access denied, Windows likely requires admin rights.
- If command line is unavailable, that is expected in this build. WatcherWall avoids WMI/shell parsing by default.
- If Live Traffic does not show packets, check that
tshark.exeis installed or in PATH and that Npcap capture permissions allow your user to capture. - If per-user proxy settings show stale localhost values but
ProxyEnable=0, Windows is not using that proxy for normal user proxy behavior.
- Windows-first.
- No per-process byte counts.
- Specific connection termination supports established IPv4 TCP only.
- IPv6 TCP connection deletion is not implemented.
- Process command line is not collected to avoid WMI dependency and shell parsing.
- Packet capture depends on external tshark/Npcap and is limited to selected-port BPF filters, not per-process kernel filtering.
- Firewall control requires Windows Firewall to be available and may require administrator rights.
- WatcherWall does not create allow rules; unblocking only removes WatcherWall-created block rules.
- Screenshots are not committed yet; run
--mockmode to get stable UI data for screenshots.
See docs/TODO.md.