Proxylity.WireGuardClient
0.1.1
dotnet add package Proxylity.WireGuardClient --version 0.1.1
NuGet\Install-Package Proxylity.WireGuardClient -Version 0.1.1
<PackageReference Include="Proxylity.WireGuardClient" Version="0.1.1" />
<PackageVersion Include="Proxylity.WireGuardClient" Version="0.1.1" />
<PackageReference Include="Proxylity.WireGuardClient" />
paket add Proxylity.WireGuardClient --version 0.1.1
#r "nuget: Proxylity.WireGuardClient, 0.1.1"
#:package Proxylity.WireGuardClient@0.1.1
#addin nuget:?package=Proxylity.WireGuardClient&version=0.1.1
#tool nuget:?package=Proxylity.WireGuardClient&version=0.1.1
Proxylity.WireGuardClient
A standalone, UdpClient-compatible WireGuard client library for .NET. It implements the full Noise_IKpsk2_25519_ChaChaPoly_BLAKE2s handshake and ChaCha20-Poly1305 transport encryption — no kernel modules, no platform binaries, pure managed code.
Features
- Drop-in
UdpClientfacade — sameSendAsync/ReceiveAsyncAPI - Full WireGuard handshake (Noise IKpsk2) and transport encryption
- Automatic session re-keying on expiry
- Thread-safe; background receive loop with back-pressure via
Channel<T> - Zero unmanaged dependencies at the .NET level (NSec wraps libsodium)
Installation
dotnet add package Proxylity.WireGuardClient
Or via the NuGet Package Manager:
<PackageReference Include="Proxylity.WireGuardClient" Version="0.1.0" />
Quick Start
using System.Net;
using Proxylity.WireGuardClient;
// Keys are 32-byte raw X25519 values, typically base64-encoded
var serverEndpoint = IPEndPoint.Parse("203.0.113.1:51820");
var serverPublicKey = Convert.FromBase64String("<server public key base64>");
var clientPrivateKey = Convert.FromBase64String("<client private key base64>");
await using var wg = new WireGuardClient(serverEndpoint, serverPublicKey, clientPrivateKey);
await wg.SendAsync(Encoding.UTF8.GetBytes("hello"), CancellationToken.None);
var result = await wg.ReceiveAsync(CancellationToken.None);
Console.WriteLine(Encoding.UTF8.GetString(result.Buffer));
API
WireGuardClient(IPEndPoint serverEndpoint, byte[] serverPublicKey, byte[] clientPrivateKey)
Creates a new client. The client opens an ephemeral local UDP socket.
| Parameter | Description |
|---|---|
serverEndpoint |
IP + port of the WireGuard peer |
serverPublicKey |
32-byte X25519 server public key |
clientPrivateKey |
32-byte X25519 client private key |
An overload accepting an existing UdpClient is also available for socket re-use or testing.
SendAsync(byte[] datagram, CancellationToken ct)
Performs the Noise handshake on first call (or after session expiry), then encrypts and sends the datagram.
ReceiveAsync(CancellationToken ct)
Returns the next decrypted datagram as UdpReceiveResult.
Close() / Dispose()
Closes the underlying UDP socket and releases all resources.
Key Generation
WireGuard uses X25519 (Curve25519 ECDH) key pairs. You can generate a key pair with:
Using the wg tool (recommended, requires WireGuard installed):
# Generate private key
wg genkey | tee client_private.key
# Derive the matching public key (needed as a parameter when deploying the stack)
wg pubkey < client_private.key | tee client_public.key
Using the library itself (in a small .NET script):
// Derive public key from a randomly generated private key
byte[] privateKey = new byte[32];
System.Security.Cryptography.RandomNumberGenerator.Fill(privateKey);
byte[] publicKey = Proxylity.WireGuardClient.Protocol.DerivePublicKey(privateKey);
Console.WriteLine("Private: " + Convert.ToBase64String(privateKey));
Console.WriteLine("Public: " + Convert.ToBase64String(publicKey));
Important: Generate your client key pair before deploying the integration test stack — the public key is a required CloudFormation parameter.
Testing
Unit and Protocol Tests (no setup required)
dotnet test --filter "Category!=Integration"
These tests are fully in-memory and have no external dependencies.
Integration Tests (requires AWS deployment)
The integration test (WireGuardClientTests) exercises a live WireGuard echo endpoint backed by an AWS Lambda function. It requires:
- AWS CLI and SAM CLI installed and configured with appropriate credentials
- A client key pair generated before deployment (see Key Generation)
Deploy the backend stack
cd tests
sam deploy --guided
During the guided deployment you will be prompted for:
| Parameter | Value |
|---|---|
ClientPublicKey |
The base64 public key you generated (contents of client_public.key) |
ClientCidr |
IP CIDR allowed to connect — use 0.0.0.0/0 for testing |
sam deploy --guided creates a samconfig.toml file in the tests/ directory with your choices so you can redeploy with just sam deploy later. Do not commit samconfig.toml — it contains account-specific configuration.
Collect stack outputs
After a successful deploy, the SAM CLI prints the stack outputs. Capture these two values:
| Output key | Description |
|---|---|
Endpoint |
host:port of the WireGuard gateway |
ServerPublicKey |
Base64 server public key |
Set environment variables and run
# Windows (PowerShell)
$env:WG_SERVER_ENDPOINT = "host:port from stack output"
$env:WG_SERVER_KEY = "base64 server public key from stack output"
$env:WG_CLIENT_PRIVATE_KEY = "base64 private key you generated"
dotnet test --filter "Category=Integration"
# Linux / macOS
export WG_SERVER_ENDPOINT="host:port from stack output"
export WG_SERVER_KEY="base64 server public key from stack output"
export WG_CLIENT_PRIVATE_KEY="base64 private key you generated"
dotnet test --filter "Category=Integration"
If the environment variables are not set the test is skipped automatically — it will never fail CI due to missing infrastructure.
Contributing
See CONTRIBUTING.md.
Security
See SECURITY.md for our responsible-disclosure policy.
License
MIT © 2026 Proxylity LLC
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 was computed. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 was computed. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net8.0
- NSec.Cryptography (>= 25.4.0)
- SauceControl.Blake2Fast (>= 2.0.0)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.