Why Per-Process Networking Still Doesn't Exist on Windows
DEV Community

Why Per-Process Networking Still Doesn't Exist on Windows

Windows has one of the most mature networking stacks in the world. It supports:

  • high-performance TCP/UDP
  • modern VPN protocols
  • virtual network adapters
  • enterprise-grade routing policies

And yet, one thing is still missing at the system level: True per-process networking control. Not “proxy per app”. Not “VPN split tunneling by rules”. Not “firewall-based heuristics”. But deterministic, low-level, per-process routing at the packet level. This post explains why.

The illusion of per-process networking

At first glance, it looks like Windows already solves this. You have:

  • Proxy settings (WinHTTP / WinINET)
  • Firewall rules (Windows Filtering Platform)
  • VPN split tunneling
  • SOCKS proxies
  • Application-level SDKs (Electron, browsers, etc.)

So it feels like: “Just configure rules per app.” But in practice, none of these operate at the same layer. They are fragmented across the stack:

Layer Mechanism Scope
Application HTTP proxy Partial (HTTP only)
OS Firewall (WFP) Packet filtering, not routing ownership
Network VPN (TUN/TAP) System-wide routing
App SDK Custom networking Only inside that app

No layer provides a unified answer to: “Which process owns this packet, and where should it go?”

The fundamental gap

The core issue is architectural: Windows networking is packet-centric, not process-centric. At the lowest level:

  • The network stack sees packets
  • Not “applications”
  • Not “user intent”
  • Not “workspace contexts”

Even though Windows internally tracks sockets per process, that mapping is not exposed as a routing primitive. You can ask:

  • “Which process owns this socket?”

But you cannot say:

  • “Route all traffic from this process into a different network stack.”

This is the missing abstraction.

Why this is hard

To support per-process networking properly, you need to solve three problems simultaneously:

  1. Packet ↔ Process attribution (real-time)
    You must reliably map: TCP/UDP packet → socket → PID → process tree
    This is non-trivial because:

    • sockets are ephemeral
    • ports are reused
    • NAT and loopback obscure ownership
    • WSL2/Docker add virtual layers
  2. Routing without kernel-level control
    Windows routing is designed around:

    • interface metrics
    • IP tables
    • global policies
      Not:
    • per-process routing graphs
      So you either:
    • modify packets in kernel space (WFP / drivers)
    • or reconstruct routing logic in user space (with tradeoffs)
  3. Multi-context coexistence
    Modern workflows require:

    • multiple VPNs at the same time
    • multiple client environments
    • local dev stack + remote cloud access
      But Windows assumes: One machine = one network context
      This assumption no longer holds.

Why existing solutions don’t solve it

VPN clients (WireGuard, OpenVPN, corporate VPNs)
They operate at: network interface level
Meaning:

  • all traffic goes through one tunnel
  • split tunneling is coarse and IP-based
    Not process-aware.

Proxies (system or app-level)
They operate at: application protocol level (HTTP/SOCKS)
Limitations:

  • only certain apps respect proxy settings
  • raw TCP/UDP traffic bypasses them
  • no kernel-level enforcement

Firewall (WFP)
WFP can inspect packets and associate metadata. But:

  • it is policy-driven, not routing-driven
  • building complex per-process routing logic becomes extremely complex
  • performance and maintainability degrade quickly

The uncomfortable truth

To this day: Windows does not provide a first-class abstraction for “process as a network routing entity”. Everything is either:

  • too high-level (proxy)
  • too low-level (packet filtering)
  • or too global (VPN)

Nothing sits in the middle.

What this implies

If you want true per-process networking, you are forced into one of two directions:

Option A - Kernel-driven architecture

  • WFP drivers
  • virtual adapters
  • packet interception
  • complex state tracking

Powerful, but heavy and fragile.

Option B - User-space reconstruction

  • capture traffic via virtual interfaces (e.g., Wintun)
  • reconstruct socket ↔ process mapping
  • maintain routing state in user space

More flexible, but requires careful engineering around:

  • latency
  • packet buffering
  • correctness under concurrency

Why this matters now

This problem was not critical 10 years ago. But today:

  • developers work across multiple client VPNs
  • cloud-native workflows create overlapping networks
  • local + remote environments coexist constantly
  • security requirements isolate network contexts

The machine is no longer a single network unit. It is a collection of overlapping network identities.

Closing thought

Per-process networking doesn’t exist on Windows not because it is impossible. But because: The OS was designed before “multiple simultaneous network contexts per user process” became a normal requirement.

I’m currently exploring this space by building an application-aware networking layer for Windows, focusing on per-process routing and workspace isolation. I’ll share the architecture decisions, failures, and performance tradeoffs as the project evolves.

Comments

No comments yet. Start the discussion.