radius-server

Crates.ioradius-server
lib.rsradius-server
version0.2.3
created_at2025-07-08 13:51:24.286682+00
updated_at2025-08-24 19:12:49.152916+00
descriptionA minimal async multi-threaded RADIUS server framework with dictionary support.
homepagehttps://github.com/SetliteWeb/radius-server
repositoryhttps://github.com/SetliteWeb/radius-server
max_upload_size
id1742798
size82,758
DAVID KIARIE MACHARIA (david-macharia)

documentation

https://github.com/SetliteWeb/radius-server/blob/main/examples/server.rs

README

Sure! Here's the full raw markdown for your updated README.md, with both Access and Accounting support documented cleanly:


# radius-server

A lightweight, async RADIUS server library written in Rust. Built for performance, extensibility, and compatibility with FreeRADIUS-style dictionaries.

---

## โœจ Features

- โœ… Parses and builds RADIUS packets
- ๐Ÿ“š Loads FreeRADIUS-style dictionaries
- ๐Ÿ”’ Shared secret authenticator validation
- โš™๏ธ Custom packet handlers via async closures
- ๐Ÿงฉ Vendor-Specific Attribute (VSA) support
- ๐Ÿ“ก Built-in support for **Access** and **Accounting**
- ๐Ÿš€ Fully async with `tokio`

---

## ๐Ÿ“ฆ Usage

### Add to your `Cargo.toml`:

```toml
radius-server = "0.2.0"

๐Ÿš€ Access Server Example (Auth)

use std::sync::Arc;
use radius_server::{
    dictionary::Dictionary,
    packet::RadiusAttribute,
    serve_async,
};

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let dict = Arc::new(Dictionary::load_embedded()?);
    let secret = "test123";

    serve_async("0.0.0.0:1812", dict, secret, move |packet| async move {
        println!("๐Ÿ” Incoming ID {} from {:?}", packet.identifier, packet.username());

        if let Some(username) = packet.username() {
            if username.trim() == "ec:30:b3:6d:24:6a" {
                Ok(packet.reply_accept(vec![
                    RadiusAttribute::session_timeout(3600),
                    RadiusAttribute::reply_message("Welcome, admin."),
                ]))
            } else {
                Ok(packet.reply_reject("User not allowed"))
            }
        } else {
            Ok(packet.reply_reject("Missing username"))
        }
    }).await
}

๐Ÿ“Š Accounting Server Example

use std::sync::Arc;
use radius_server::{
    dictionary::Dictionary,
    handler::serve_accounting_async,
};

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let dict = Arc::new(Dictionary::load_embedded()?);
    let secret = "test123";

    serve_accounting_async("0.0.0.0:1813", dict, secret, move |packet| async move {
        println!("๐Ÿ“จ Accounting ID {} from {:?}", packet.identifier, packet.username());
        for attr in packet.attributes {
            println!("  โ†’ Type {}: {:?}", attr.typ, attr.value);
        }
        Ok(())
    }).await
}

Accounting-Request packets (Code 4) are validated against RFC 2866 and automatically responded to with a proper Accounting-Response (Code 5) including a correct MD5 authenticator.


๐Ÿ“‚ Dictionary Support

Supports FreeRADIUS-style dictionaries (e.g., dictionary, dictionary.rfc2865, dictionary.vsa).

You can load:

Dictionary::load_embedded()?;
// or
Dictionary::from_file("path/to/dictionary")?;

๐Ÿงช Testing Tools

You can test with radclient:

echo "User-Name = test, Acct-Status-Type = Start" | radclient -x 127.0.0.1:1813 acct test123

Or test authentication:

echo "User-Name = ec:30:b3:6d:24:6a, User-Password = secret" | radclient -x 127.0.0.1 auth test123

๐Ÿ›  Status Types You Can Handle

Use Acct-Status-Type to differentiate events:

  • Start
  • Stop
  • Interim-Update
  • Accounting-On
  • Accounting-Off

๐Ÿ”Œ Architecture

  • serve_async(...) โ†’ Access (Auth) handler
  • serve_accounting_async(...) โ†’ Accounting handler
  • Use closures for custom logic
  • Runs fully async on tokio

๐Ÿ“„ License

MIT License. Contributions welcome.


---

Let me know if you'd like to:

- Add a badge section (crates.io, docs.rs, license)
- Add examples for custom dictionaries
- Generate it as an `mdbook` or `docs.rs` doc

Happy to help.
Commit count: 10

cargo fmt