| Crates.io | abol |
| lib.rs | abol |
| version | 0.1.0 |
| created_at | 2026-01-15 17:11:08.128652+00 |
| updated_at | 2026-01-15 17:11:08.128652+00 |
| description | A high-performance, asynchronous, dictionary-driven RADIUS framework. |
| homepage | |
| repository | |
| max_upload_size | |
| id | 2046057 |
| size | 695,526 |
A high-performance, asynchronous RADIUS implementation for Rust
Type-safe โข Runtime-agnostic โข Dictionary-driven โข Memory-safe
[dependencies]
abol = "0.1.0"
abol-util = { version = "0.1.0", features = ["tokio"] }
tokio = { version = "1.0", features = ["full"] }
Abol is a high-performance, asynchronous RADIUS server framework written in Rust.
It provides a robust, type-safe foundation for building modern authentication and authorization systems, featuring a powerful dictionary-driven code generator that turns standard RADIUS dictionaries into strongly-typed Rust APIs.
Abol is designed for correctness, extensibility, and performance --- without sacrificing ergonomics.
In the traditional Ethiopian coffee ceremony, Abol is the first round of brewing.
It is the strongest, most potent, and most important cup --- representing clarity, connection, and readiness.
Like its namesake, Abol serves as the primary and reliable connection point for your network authentication infrastructure.
Optimized for high performance while remaining compatible with multiple async runtimes, including Tokio and Smol.
Leverages Rust's type system and traits to provide type-safe attribute access with zero runtime overhead.
Automatically generate Rust traits and helpers from standard RADIUS dictionary files at build time.
Implemented 100% in safe Rust, protecting your authentication gateway from memory corruption and buffer overflows.
Abol is engineered for high-concurrency environments. Below are the results of a benchmark conducted on a standard development machine using radperf.
Test Environment
- OS: Kali GNU/Linux 2025.3 (Kernel 6.17.10)
- CPU: Intelยฎ Coreโข i7-8850H @ 2.60GHz (12 Cores)
- RAM: 32 GiB DDR4
- Platform: Wayland / KDE Plasma 6.3.6
Benchmark Command:
radperf -d . -f test_users.csv -a pap -s -c 100000 -p 150 127.0.0.1 auth testing123
| Metric | Result |
|---|---|
| Throughput | ๐ 34,141 packets/s |
| Success Rate | โ
100% (0 failures) |
| Latency | โฑ๏ธ < 10ms (93.5% of reqs) |
| Total Workload | ๐ฆ 100,000 requests |
| Execution Time | โณ 2.92 seconds |
use abol::codegen::rfc2865::Rfc2865Ext;
use abol::core::{Cidr, Code, Request, Response};
use abol::rt::Runtime;
use abol::server::{HandlerFn, SecretManager, SecretSource, Server, BoxError};
use abol_util::rt::tokio::TokioRuntime;
use std::net::SocketAddr;
use std::sync::Arc;
/// A simple "Global Password" provider for your RADIUS server.
///
/// Use this if you want every single client (NAS) to use the same shared secret,
/// regardless of their IP address. It is the easiest way to get started.
pub struct StaticSecretSource {
/// The shared secret (password) used to authenticate RADIUS packets.
pub secret: Vec<u8>,
}
impl SecretSource for StaticSecretSource {
/// Tells the server to use the same secret for the entire internet.
async fn get_all_secrets(&self) -> Result<Vec<(Cidr, Vec<u8>)>, BoxError> {
// Define a "Catch-All" range.
// 0.0.0.0 with a prefix of 0 matches ANY incoming IPv4 address.
let cidr = Cidr {
ip: "0.0.0.0".parse()?,
prefix: 0,
};
// Return the mapping: (Everywhere on IPv4) -> (Our Secret)
Ok(vec![(cidr, self.secret.clone())])
}
}
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let addr: SocketAddr = "0.0.0.0:1812".parse()?;
// 1. Setup the Secret Manager
let source = Arc::new(StaticSecretSource {
secret: b"testing123".to_vec(),
});
let secret_manager = SecretManager::new(source, 3600);
// 2. Define the Request Handler
let handler = HandlerFn(|request: Request| async move {
let name = request
.packet
.get_user_name()
.unwrap_or_else(|| "Guest".to_string());
match request.packet.get_user_password() {
Some(p) if p.as_bytes() == b"supersecretpassword" => {
let mut res = request.packet.create_response_packet(Code::AccessAccept);
res.set_reply_message(format!("Hello {}, access granted!", name));
Ok(Response { packet: res })
}
_ => {
let res = request.packet.create_response_packet(Code::AccessReject);
Ok(Response { packet: res })
}
}
});
// 3. Initialize the Specific Runtime
let runtime = TokioRuntime::new();
let socket = runtime.bind(addr).await?;
// 4. Create and start the server
let server = Server::new(runtime, socket, secret_manager, handler);
server.listen_and_serve().await?;
println!("Abol (Tokio) listening on {}", addr);
Ok(())
}
cargo run --release --example tokio-server --features tokio
cargo run --release --example smol-server --features smol
abol-core -- Packet encoding/decoding and trait definitions\
Licensed under either of:
at your option.
Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.
Crafted with โ in the spirit of the first brew.