The rule sounds precise: allow local traffic on the private profile and only VPN traffic on the public one. It is not, because a network profile selects which firewall rule set applies and says nothing about which adapter carried a packet. Treating the profile name as a path requirement is the mistake that makes a restricted egress design look finished when it is not.

Write down the flows first, then decide which mechanism can actually enforce each one. That flow list is the only artefact which survives the next rule change.

The category chooses rules, not routes

When Windows classifies a network as public or private, the firewall applies the rule set configured for that profile. The classification follows the network the adapter joined, and the rule set decides what is permitted on it. Neither of those facts depends on whether an application's traffic used the tunnel. That independence is the whole difficulty.

Routing makes the path choice, through the interface metric and the prefix the tunnel installs. A profile can therefore be labelled public while an application's connection takes the physical path, and the firewall will still report that the public rule set applied.

This is why a rule scoped to the profile cannot mean tunnel-only. The two properties are decided by different components and one cannot stand in for the other.

FlowWhat decides itWhat a rule can enforce
VPN client to its endpointRouting plus the outer transportAllow the client process before the tunnel exists
Application to an internet hostInterface metric and prefix lengthBlock the process unless the tunnel interface is up
Application to a LAN hostLocal subnet routeAllow one destination, not the whole category

An explicit block outranks a narrower allow

Microsoft's firewall rule guidance distinguishes an allow exception to a default block action from an explicit block that conflicts with an allow. Explicit blocks win that conflict, and outbound rules obey the same precedence.

So the popular recipe of adding a block-everything rule and relying on a narrower allow placed above it does not do what its author expects. Windows Firewall does not resolve the conflict by administrator-assigned rule order. The block simply applies, and the connecting application reports a timeout. The rule that looked like the exception was never in the running.

The supported shape is a default-deny policy with approved allow rules, where each allow names a program, a service or a destination precisely enough to be reviewed. That design survives an audit, because every exception is visible and none of them depend on the order they were created in.

Two rules that contradict each other are worse than one rule, because the resulting behaviour is correct and unexplainable at the same time.

Give the outbound policy a single owner

A supported VPN client already maintains its own blocking behaviour and its own endpoint exceptions. Adding uncoordinated manual rules can strand that client outside the tunnel it needs for setup, or leave a second path open that nobody noticed.

Decide who owns the outbound policy before writing rules: the client's own configuration, a managed firewall policy, or a documented local exception list with an owner. Then reconcile the layers instead of stacking experiments until something connects. A named owner is also who you ask when two layers disagree.

Preserve a recovery channel before changing anything. A remote machine locked out of its own management path is a worse outcome than the policy gap you were closing. The recovery rule is easier to justify when it is written down in advance, and easier to find when a change goes wrong at an hour nobody enjoys.

Test four outcomes instead of reading the label

A policy is only as good as the cases it distinguishes, so treat the profile label as a starting point rather than a result. Four outcomes tell you whether it works: the intended LAN request succeeds, a covered internet request succeeds, a prohibited direct request fails, and the tunnel-failure case behaves as designed instead of falling back quietly. Write the four results down next to the rule change. A test plan with four named cases is short enough to run every time and specific enough to fail loudly.

Get-NetConnectionProfile | Select-Object Name,NetworkCategory,InterfaceAlias
Get-NetFirewallProfile | Select-Object Name,DefaultOutboundAction
Get-NetFirewallRule -Direction Outbound -Enabled True | Where-Object Action -eq Block |
  Select-Object DisplayName,Profile

The first command shows how each connected network is classified, which is often not what the person who wrote the rule assumed. The second shows the default action per profile, and the third lists enabled outbound blocks, including any that will quietly override a narrower allow.

Run the four cases again after a network change, because a profile can be reclassified when the machine joins a different network. A matching profile label is not evidence that the path was the one you intended.

Nuŋlɔɖi siwo ku ɖe eŋu