SavageZA.Radius.Client 1.1.0

dotnet add package SavageZA.Radius.Client --version 1.1.0
                    
NuGet\Install-Package SavageZA.Radius.Client -Version 1.1.0
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="SavageZA.Radius.Client" Version="1.1.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="SavageZA.Radius.Client" Version="1.1.0" />
                    
Directory.Packages.props
<PackageReference Include="SavageZA.Radius.Client" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add SavageZA.Radius.Client --version 1.1.0
                    
#r "nuget: SavageZA.Radius.Client, 1.1.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package SavageZA.Radius.Client@1.1.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=SavageZA.Radius.Client&version=1.1.0
                    
Install as a Cake Addin
#tool nuget:?package=SavageZA.Radius.Client&version=1.1.0
                    
Install as a Cake Tool

RadiusClient

A high-performance, thread-safe .NET 8 client library for communicating with RADIUS servers, implementing RFC 2865 (Authentication) and RFC 2866 (Accounting).

Features

  • Full RADIUS protocol support — Access-Request, Access-Accept/Reject/Challenge, Accounting-Request/Response, CoA, Disconnect, and Status-Server (RFC 5997)
  • High throughput — Maintains a single pre-connected UDP socket per instance, eliminating per-request socket creation overhead, ephemeral port exhaustion, and TIME_WAIT accumulation
  • Thread-safe — All public members are safe for concurrent use; responses are correlated by RADIUS Identifier
  • IPv4 and IPv6 — Dual-stack support with automatic address family detection
  • Async/await — Fully asynchronous send/receive with CancellationToken support
  • Configurable retries — Per-request retry count and socket timeout
  • Comprehensive attribute support — Standard attributes, Vendor-Specific Attributes (VSA) with 9 encoding formats, Tunnel attributes, and more
  • Vendor format presets — Built-in RadiusVendorFormats constants for Cisco, Microsoft, Juniper, Aruba, Huawei, Ruckus, Fortinet, US Robotics, and WiMAX
  • Authentication protocols — PAP, CHAP, and EAP (Message-Authenticator) support
  • Security — Sensitive key material is zeroed after use via CryptographicOperations.ZeroMemory; constant-time authenticator comparison prevents timing side-channel attacks
  • Trimming and AOT compatible — Annotated for .NET trimming and Native AOT scenarios

Installation

Clone the repository and add a project reference:

git clone https://github.com/enteriaza/RadiusClient.git

In your project file, add the following reference:

<ProjectReference Include="..\RadiusClient\RadiusClient.csproj" />

Quick Start

PAP Authentication

using Radius;

using var client = new RadiusClient("radius.example.com", "MySharedSecret");

// Build the Access-Request packet
RadiusPacket request = client.CreatePacket(RadiusCode.ACCESS_REQUEST);
request.SetAttribute(new RadiusAttributes(RadiusAttributeType.USER_NAME, "alice"));

// Encode the password using PAP (RFC 2865 §5.2)
byte[] encodedPassword = RadiusUtils.EncodePapPassword(
    System.Text.Encoding.ASCII.GetBytes("password123"),
    request.Authenticator,
    System.Text.Encoding.ASCII.GetBytes("MySharedSecret"));
request.SetAttribute(new RadiusAttributes(RadiusAttributeType.USER_PASSWORD, encodedPassword));

// Sign and send
request.SetAuthenticator(System.Text.Encoding.ASCII.GetBytes("MySharedSecret"));

RadiusPacket? response = await client.SendAndReceivePacketAsync(request);

if (response is not null && client.VerifyAuthenticator(request, response))
{
    Console.WriteLine($"Response: {response.PacketType}");
}

Accounting

using Radius;

using var client = new RadiusClient("radius.example.com", "MySharedSecret");

RadiusPacket acctRequest = client.CreatePacket(RadiusCode.ACCOUNTING_REQUEST);
acctRequest.SetAttribute(new RadiusAttributes(RadiusAttributeType.USER_NAME, "alice"));
acctRequest.SetAttribute(new RadiusAttributes(RadiusAttributeType.ACCT_STATUS_TYPE, (int)ACCT_STATUS_TYPE.START));
acctRequest.SetAttribute(new RadiusAttributes(RadiusAttributeType.ACCT_SESSION_ID, "session-001"));

// Accounting packets use a zeroed-then-hashed authenticator
acctRequest.SetAuthenticator(System.Text.Encoding.ASCII.GetBytes("MySharedSecret"));

RadiusPacket? response = await client.SendAndReceivePacketAsync(acctRequest);

Server Ping (Status-Server)

using Radius;

using var client = new RadiusClient("radius.example.com", "MySharedSecret");
RadiusPacket? pong = await client.PingAsync();

Console.WriteLine(pong is not null ? "Server is reachable" : "Server did not respond");

Vendor-Specific Attributes (VSA)

// Append a vendor-specific attribute (e.g., Cisco AV-Pair)
var vsa = new VendorSpecificAttributes(
    vendorId: 9,           // Cisco
    vendorSpecificType: 1, // AV-Pair
    vendorSpecificData: System.Text.Encoding.UTF8.GetBytes("shell:priv-lvl=15"));

request.SetAttribute(vsa);

Vendor-Specific Attribute (VSA) Format Support

The VendorSpecificAttributes class supports all known VSA sub-attribute encoding formats used by RADIUS vendors, as specified in RFC 2865 §5.26, RFC 6929 §2.4, and real-world vendor dictionaries:

Format Enum Value Type Field Length Field Extra Example Vendors
format=1,1 Type1Len1 1 byte 1 byte — Most vendors (Cisco, Juniper, HP, etc.) — RFC 2865 §5.26 standard
format=1,0 Type1Len0 1 byte None — Vendors with type-only sub-attributes
format=2,1 Type2Len1 2 bytes 1 byte — Vendors with extended type spaces
format=2,0 Type2Len0 2 bytes None — Vendors with 2-byte type, no length
format=2,2 Type2Len2 2 bytes 2 bytes — Vendors with 2-byte type and 2-byte length
format=4,0 Type4Len0 4 bytes None — US Robotics / 3Com (PEN 429)
format=4,1 Type4Len1 4 bytes 1 byte — Vendors with 4-byte type and 1-byte length
format=4,2 Type4Len2 4 bytes 2 bytes — Vendors with 4-byte type and 2-byte length
format=1,1,c Type1Len1Continuation 1 byte 1 byte Continuation byte WiMAX Forum (PEN 24757) — RFC 6929 §2.4

Standard VSA (format=1,1)

// Most vendors use standard format — the byte constructor selects it   automatically.
var vsa = new VendorSpecificAttributes(
    vendorId: 9,           // Cisco
    vendorSpecificType: 1, // AV-Pair
    vendorSpecificData: Encoding.UTF8.GetBytes("shell:priv-lvl=15"));

Extended 4-byte Type VSA (format=4,0)

// US Robotics / 3Com uses 4-byte vendor types with no length field.
var vsa = new VendorSpecificAttributes(
    vendorId: 429,
    vendorSpecificType: 0xBE45,
    vendorSpecificData: Encoding.UTF8.GetBytes("+15551234567"),
    format: VendorSpecificFormat.Type4Len0);

WiMAX Continuation VSA (format=1,1,c)

// WiMAX attributes include a continuation byte (RFC 6929 §2.4).
var vsa = new VendorSpecificAttributes(
    vendorId: 24757,
    vendorSpecificType: 1,
    vendorSpecificData: myData,
    format: VendorSpecificFormat.Type1Len1Continuation,
    continuationFlag: 0x00); // 0x80 = more fragments follow

API Overview

Core Classes

Class Description
RadiusClient High-throughput UDP client for sending/receiving RADIUS packets. Implements IDisposable.
RadiusPacket Represents a RADIUS packet — construct outbound requests or parse inbound responses.
RadiusAttributes Standard RADIUS attribute in TLV format (RFC 2865 §5). Supports byte[], string, int, long, DateTime, and IPAddress values.
VendorSpecificAttributes Vendor-Specific Attribute (Type 26, RFC 2865 §5.26).
TunnelTypeAttributes Tunnel-Type attribute (Type 64, RFC 2868 §3.1).
TunnelMediumTypeAttributes Tunnel-Medium-Type attribute (Type 65, RFC 2868 §3.2).
RadiusUtils Static utilities for authenticator computation, PAP/CHAP encoding, Tunnel-Password obfuscation, and binary helpers.

RadiusClient Constructor

public RadiusClient(
    string hostName,
    string sharedSecret,
    int sockTimeout = 3000,
    int authPort = 1812,
    int acctPort = 1813,
    IPEndPoint? localEndPoint = null)

Key Methods

Method Description
CreatePacket(RadiusCode) Creates a new outbound packet with a random Identifier.
SendAndReceivePacketAsync(RadiusPacket, int, CancellationToken) Sends a packet and awaits a matching response, with configurable retries.
PingAsync(CancellationToken) Sends a Status-Server probe (RFC 5997) — single attempt, no retries.
VerifyAuthenticator(RadiusPacket, RadiusPacket) Verifies the Response Authenticator of a received reply (constant-time comparison).

Packet Construction Sequence

  1. Create a packet via CreatePacket() or new RadiusPacket(RadiusCode).
  2. Add attributes via SetAttribute().
  3. (Optional) Call SetMessageAuthenticator() for EAP or enhanced security (RFC 3579 §3.2).
  4. Call SetAuthenticator() to finalize the packet.
  5. Send via SendAndReceivePacketAsync().

RFC Compliance

RFC Description Support
RFC 2865 RADIUS Authentication ✅ Full
RFC 2866 RADIUS Accounting ✅ Full
RFC 2868 RADIUS Tunnel Attributes ✅ Full
RFC 3579 RADIUS EAP Support (Message-Authenticator) ✅ Full
RFC 5176 Dynamic Authorization (CoA / Disconnect) ✅ Full
RFC 5997 Status-Server ✅ Full

Requirements

  • .NET 8.0 or later

License

This project is licensed under the MIT License.

Product 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. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.
  • net8.0

    • No dependencies.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.1.0 147 3/6/2026
1.0.0 126 2/26/2026