Back to Home

PowerShell monitoring IP Windows nftables

The article describes a PowerShell script for real-time monitoring of IP addresses of Windows application connections. Implemented filtering of public IPv4, deduplication and automatic addition to nftables OpenWRT via SSH. The approach is suitable for dynamic traffic control.

IP tracking of applications: PowerShell + nftables
Advertisement 728x90

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:

Google AdInline article slot
  • 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.

Google AdInline article slot

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:

Google AdInline article slot
  • Get-Process -Name $ProcessName retrieves the process ID.
  • Get-NetTCPConnection | Where State -eq "Established" -and OwningProcess -eq $PID extracts RemoteAddress values.
  • New public IPs are added to the HashSet, output file, and nftables.
  • Start-Sleep -Seconds $PollSeconds pauses 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

Advertisement 728x90

Read Next