Table of Contents

Class WindowsVpnKillSwitch

Namespace
VpnHood.Core.Client.Devices.WindowsTun
Assembly
VpnHood.Core.Client.Devices.WindowsTun.dll

Represents the kill switch's block on Windows: the Windows Filtering Platform's own filters, under a provider and a sublayer of ours.

public sealed class WindowsVpnKillSwitch : IVpnKillSwitch
Inheritance
WindowsVpnKillSwitch
Implements
Inherited Members

Remarks

The filters are persistent: the Base Filtering Engine keeps them through a crash of the service and restores them when it starts at boot, so the block holds through both, as a crash lifting it would defeat its purpose. They are not boot-time filters, so they hold once the engine has started. Not a dynamic session's, which the engine deletes with its process: WireGuard for Windows uses one, and its block goes with a crash.

The connect and accept layers (ALE) judge a flow at its start, and again where Windows reauthorizes it, nothing per packet; the forward layers judge what Windows routes itself, which would otherwise go around the block. They have no port field, so DNS routed to an address of the split passes. A known limit: WinNAT's traffic — WSL2's NAT mode, so Docker Desktop's too — is seen by no WFP layer (seen on Windows Server 2025 with WSL 3.0.3), so it goes into the tunnel while one is up and around the block while none is. The Hyper-V firewall could stop it only while the service runs, never after a crash.

The keys are the SDK's, so every app built on VpnHood shares the one block; the provider's data names the app whose block it is. It needs an administrator: the service, which runs as SYSTEM.

Constructors

WindowsVpnKillSwitch(string, string?)

Represents the kill switch's block on Windows: the Windows Filtering Platform's own filters, under a provider and a sublayer of ours.

public WindowsVpnKillSwitch(string owner, string? serviceName)

Parameters

owner string

The app's storage folder, which names the app whose block it is and an update keeps, where the exe's folder changes.

serviceName string

The service whose processes the block lets out; null in a run as the person, whose block lets out none of its processes.

Remarks

The filters are persistent: the Base Filtering Engine keeps them through a crash of the service and restores them when it starts at boot, so the block holds through both, as a crash lifting it would defeat its purpose. They are not boot-time filters, so they hold once the engine has started. Not a dynamic session's, which the engine deletes with its process: WireGuard for Windows uses one, and its block goes with a crash.

The connect and accept layers (ALE) judge a flow at its start, and again where Windows reauthorizes it, nothing per packet; the forward layers judge what Windows routes itself, which would otherwise go around the block. They have no port field, so DNS routed to an address of the split passes. A known limit: WinNAT's traffic — WSL2's NAT mode, so Docker Desktop's too — is seen by no WFP layer (seen on Windows Server 2025 with WSL 3.0.3), so it goes into the tunnel while one is up and around the block while none is. The Hyper-V firewall could stop it only while the service runs, never after a crash.

The keys are the SDK's, so every app built on VpnHood shares the one block; the provider's data names the app whose block it is. It needs an administrator: the service, which runs as SYSTEM.

Methods

Block(VpnKillSwitchRules, CancellationToken)

Puts this app's block up, or re-points it, in one change with no gap, in place of any app's.

public Task Block(VpnKillSwitchRules rules, CancellationToken cancellationToken)

Parameters

rules VpnKillSwitchRules

What the block lets pass.

cancellationToken CancellationToken

The token to monitor for cancellation requests.

Returns

Task

A task that completes once the block is up.

Remarks

It fails where it cannot, and then nothing may connect: a connect never goes on unprotected.

Exceptions

NotSupportedException

Linux has no nftables, or the service is in no cgroup v2 group of its own.

ExternalException

The OS refused the block: Linux's nft, or Windows' filtering engine, as without an administrator.

OperationCanceledException

cancellationToken was canceled.

Win32Exception

The filtering engine refused a change, as without an administrator.

IsBlocking(CancellationToken)

Determines whether this app's block is up.

public Task<bool> IsBlocking(CancellationToken cancellationToken)

Parameters

cancellationToken CancellationToken

The token to monitor for cancellation requests.

Returns

Task<bool>

A task whose result is true if this app's block is up; otherwise, false.

Remarks

It runs at once; the token is not watched.

Exceptions

ExternalException

The OS's rules could not be read: Linux's nft, or Windows' filtering engine.

OperationCanceledException

cancellationToken was canceled.

Win32Exception

The filtering engine could not be opened or read.

Unblock(bool, CancellationToken)

Removes this app's block, or, with anyApp, any app's: the tunnel's holder's call.

public Task Unblock(bool anyApp, CancellationToken cancellationToken)

Parameters

anyApp bool

true to remove any app's block; false to remove this app's only.

cancellationToken CancellationToken

The token to monitor for cancellation requests.

Returns

Task

A task that completes once the block is gone.

Remarks

It runs at once, in one transaction of the filtering engine; the token is not watched.

Exceptions

ExternalException

The OS refused the change: Linux's nft, or Windows' filtering engine.

OperationCanceledException

cancellationToken was canceled.

Win32Exception

The filtering engine refused a change, as without an administrator.