DEV Community

Cover image for Why Per-Process Networking Still Doesn't Exist on Windows
blackbear
blackbear

Posted on

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
Enter fullscreen mode Exit fullscreen mode

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.


Top comments (0)