Monitor Windows App IP Addresses with PowerShell and nftables
Developers and network admins often need to monitor the IP addresses that applications connect to. Static IP lists quickly become outdated due to regional CDN variations and shifting routing paths. This PowerShell script captures active (Established) connections from a specified process in real time, filters out public IPv4 addresses, and pushes them to an OpenWRT router for dynamic insertion into nftables.
The script monitors a defined process (default: Telegram), collects unique RemoteAddress values from Get-NetTCPConnection, excludes private IP ranges and well-known DNS servers (8.8.8.8, 1.1.1.1), then uses SSH to add IPs to an nft set. This enables up-to-date traffic control without manual intervention.
Script Structure and Parameters
The script accepts key parameters for flexible configuration:
ProcessName: name of the process to monitor (e.g., "Telegram")OutputFile: log file for recorded IPs (e.g., "telegram_ips.txt")PollSeconds: connection polling interval (3 seconds)RouterHost,RouterUser: SSH target (e.g., "192.168.1.1", "root")NftFamily,NftTable,NftSet: nftables context (e.g., "inet", "fw4", "vpn_domains")UseTimeout: optional timeout elements (e.g., "1h")SshKeyPath: path to SSH private key
Logic uses HashSet for deduplication and validates public IP status via byte-level checks.
Filtering Public IPv4 Addresses
The Test-PublicIPv4 function excludes RFC1918, link-local, carrier-grade NAT, and popular DNS addresses:
function Test-PublicIPv4([string]$ip) {
try {
$addr = [System.Net.IPAddress]::Parse($ip)
} catch {
return $false
}
if ($addr.AddressFamily -ne [System.Net.Sockets.AddressFamily]::InterNetwork) {
return $false
}
$b = $addr.GetAddressBytes()
if ($b[0] -eq 10) { return $false }
if ($b[0] -eq 127) { return $false }
if ($b[0] -eq 169 -and $b[1] -eq 254) { return $false }
if ($b[0] -eq 172 -and $b[1] -ge 16 -and $b[1] -le 31) { return $false }
if ($b[0] -eq 192 -and $b[1] -eq 168) { return $false }
if ($b[0] -eq 100 -and $b[1] -ge 64 -and $b[1] -le 127) { return $false }
if ($ip -eq "0.0.0.0") { return $false }
if ($ip -eq "8.8.8.8") { return $false }
if ($ip -eq "8.8.4.4") { return $false }
if ($ip -eq "1.1.1.1") { return $false }
if ($ip -eq "1.0.0.1") { return $false }
return $true
}
This prevents false positives from local traffic and DNS resolvers.
Integrating with OpenWRT nftables
The Add-IpToOpenWrt function executes an SSH command to dynamically add IPs to the nft set:
function Add-IpToOpenWrt([string]$ip) {
$target = "$RouterUser@$RouterHost"
if ($UseTimeout) {
$remoteCmd = "nft add element $NftFamily $NftTable $NftSet { $ip timeout $TimeoutValue } 2>/dev/null || true"
} else {
$remoteCmd = "nft add element $NftFamily $NftTable $NftSet { $ip } 2>/dev/null || true"
}
& ssh \
-i $SshKeyPath \
-o IdentitiesOnly=yes \
-o BatchMode=yes \
$target \
$remoteCmd | Out-Null
return $LASTEXITCODE
}
Options like -o BatchMode=yes and || true ensure non-interactive execution. Timeout-based entries auto-expire, reducing maintenance overhead.
Main Monitoring Loop
In an infinite loop:
Get-Process -Name $ProcessNameretrieves the process ID.Get-NetTCPConnection | Where State -eq "Established" -and OwningProcess -eq $PIDextracts RemoteAddress values.- New public IPs are added to the HashSet, output file, and nftables.
Start-Sleep -Seconds $PollSecondspauses before next check.
The full cycle runs in ~3 seconds—balancing responsiveness and system load.
Key Benefits
- Dynamic tracking: Captures live IPs from actual connections, bypassing outdated static lists.
- Traffic filtering: Excludes private ranges, DNS, and loopback addresses for clean data.
- Automated nftables updates: Direct SSH integration with OpenWRT—no API or web UI needed.
- Deduplication: HashSet prevents duplicates in logs and nft sets.
- Flexibility: Configurable for any process, router, or nft context.
Use Cases Beyond Telegram
This approach is highly adaptable: replace ProcessName with any executable (Discord, Zoom, browsers). For multiple processes, use an array of PIDs. Integrate with external systems via webhook instead of SSH. Test on VMs: run a target app with traffic, verify logs, and inspect output with nft list set.
— Editorial Team
No comments yet.