136 lines
4.3 KiB
Markdown
136 lines
4.3 KiB
Markdown
|
|
# @push.rocks/smartradius/server
|
||
|
|
|
||
|
|
> 🖥️ RADIUS Server Implementation - Full RFC 2865/2866 compliant authentication and accounting server
|
||
|
|
|
||
|
|
## Overview
|
||
|
|
|
||
|
|
This module provides a complete RADIUS server implementation supporting both authentication (RFC 2865) and accounting (RFC 2866) protocols. It handles PAP and CHAP authentication, accounting session tracking, and includes duplicate detection with response caching.
|
||
|
|
|
||
|
|
## Features
|
||
|
|
|
||
|
|
- ✅ **PAP Authentication** - Password Authentication Protocol with RFC-compliant encryption
|
||
|
|
- ✅ **CHAP Authentication** - Challenge-Handshake Authentication Protocol
|
||
|
|
- ✅ **Accounting** - Session start/stop/interim-update tracking
|
||
|
|
- ✅ **Duplicate Detection** - Automatic response caching for retransmitted requests
|
||
|
|
- ✅ **Per-Client Secrets** - Support for different shared secrets per NAS
|
||
|
|
- ✅ **Statistics** - Built-in request/response counters
|
||
|
|
- ✅ **VSA Support** - Vendor-Specific Attributes handling
|
||
|
|
- ✅ **Message-Authenticator** - HMAC-MD5 for EAP support
|
||
|
|
|
||
|
|
## Exports
|
||
|
|
|
||
|
|
### Classes
|
||
|
|
|
||
|
|
| Class | Description |
|
||
|
|
|-------|-------------|
|
||
|
|
| `RadiusServer` | Main server class handling authentication and accounting |
|
||
|
|
| `RadiusPacket` | Packet encoder/decoder for RADIUS protocol |
|
||
|
|
| `RadiusAttributes` | Attribute parsing and encoding utilities |
|
||
|
|
| `RadiusAuthenticator` | Cryptographic operations (PAP encryption, CHAP, authenticators) |
|
||
|
|
| `RadiusSecrets` | Client secret management |
|
||
|
|
|
||
|
|
### Interfaces (Server-Specific)
|
||
|
|
|
||
|
|
| Interface | Description |
|
||
|
|
|-----------|-------------|
|
||
|
|
| `IRadiusServerOptions` | Server configuration options |
|
||
|
|
| `IRadiusServerStats` | Server statistics counters |
|
||
|
|
| `IAuthenticationRequest` | Request context passed to auth handler |
|
||
|
|
| `IAuthenticationResponse` | Response from auth handler |
|
||
|
|
| `IAccountingRequest` | Request context passed to accounting handler |
|
||
|
|
| `IAccountingResponse` | Response from accounting handler |
|
||
|
|
| `TAuthenticationHandler` | Handler function type for authentication |
|
||
|
|
| `TAccountingHandler` | Handler function type for accounting |
|
||
|
|
| `TSecretResolver` | Function type for resolving client secrets |
|
||
|
|
|
||
|
|
## Usage
|
||
|
|
|
||
|
|
```typescript
|
||
|
|
import { RadiusServer, ERadiusCode } from '@push.rocks/smartradius';
|
||
|
|
|
||
|
|
const server = new RadiusServer({
|
||
|
|
authPort: 1812,
|
||
|
|
acctPort: 1813,
|
||
|
|
defaultSecret: 'shared-secret',
|
||
|
|
|
||
|
|
authenticationHandler: async (request) => {
|
||
|
|
// PAP authentication
|
||
|
|
if (request.password === 'correct-password') {
|
||
|
|
return {
|
||
|
|
code: ERadiusCode.AccessAccept,
|
||
|
|
replyMessage: 'Welcome!',
|
||
|
|
sessionTimeout: 3600,
|
||
|
|
};
|
||
|
|
}
|
||
|
|
|
||
|
|
// CHAP authentication
|
||
|
|
if (request.chapPassword && request.chapChallenge) {
|
||
|
|
const isValid = RadiusAuthenticator.verifyChapResponse(
|
||
|
|
request.chapPassword,
|
||
|
|
request.chapChallenge,
|
||
|
|
'expected-password'
|
||
|
|
);
|
||
|
|
if (isValid) {
|
||
|
|
return { code: ERadiusCode.AccessAccept };
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
return { code: ERadiusCode.AccessReject };
|
||
|
|
},
|
||
|
|
|
||
|
|
accountingHandler: async (request) => {
|
||
|
|
console.log(`Session ${request.sessionId}: ${request.statusType}`);
|
||
|
|
return { success: true };
|
||
|
|
},
|
||
|
|
});
|
||
|
|
|
||
|
|
await server.start();
|
||
|
|
```
|
||
|
|
|
||
|
|
## Low-Level Packet Operations
|
||
|
|
|
||
|
|
```typescript
|
||
|
|
import {
|
||
|
|
RadiusPacket,
|
||
|
|
RadiusAuthenticator,
|
||
|
|
RadiusAttributes,
|
||
|
|
ERadiusAttributeType,
|
||
|
|
} from '@push.rocks/smartradius';
|
||
|
|
|
||
|
|
// Decode incoming packet
|
||
|
|
const packet = RadiusPacket.decodeAndParse(buffer);
|
||
|
|
|
||
|
|
// Encrypt PAP password
|
||
|
|
const encrypted = RadiusAuthenticator.encryptPassword(
|
||
|
|
password, authenticator, secret
|
||
|
|
);
|
||
|
|
|
||
|
|
// Verify CHAP response
|
||
|
|
const valid = RadiusAuthenticator.verifyChapResponse(
|
||
|
|
chapPassword, challenge, expectedPassword
|
||
|
|
);
|
||
|
|
|
||
|
|
// Create Vendor-Specific Attribute
|
||
|
|
const vsa = RadiusAttributes.createVendorAttribute(
|
||
|
|
9, // Cisco vendor ID
|
||
|
|
1, // Vendor type
|
||
|
|
Buffer.from('value')
|
||
|
|
);
|
||
|
|
```
|
||
|
|
|
||
|
|
## Server Options
|
||
|
|
|
||
|
|
| Option | Type | Default | Description |
|
||
|
|
|--------|------|---------|-------------|
|
||
|
|
| `authPort` | number | 1812 | Authentication port |
|
||
|
|
| `acctPort` | number | 1813 | Accounting port |
|
||
|
|
| `bindAddress` | string | '0.0.0.0' | Address to bind to |
|
||
|
|
| `defaultSecret` | string | - | Default shared secret |
|
||
|
|
| `secretResolver` | function | - | Per-client secret resolver |
|
||
|
|
| `duplicateDetectionWindow` | number | 10000 | Duplicate detection window (ms) |
|
||
|
|
| `maxPacketSize` | number | 4096 | Maximum packet size |
|
||
|
|
|
||
|
|
## Re-exports
|
||
|
|
|
||
|
|
This module re-exports all types from `ts_shared` for convenience, so you can import everything from a single location.
|