| Crates.io | mtls-actix |
| lib.rs | mtls-actix |
| version | 0.1.0 |
| created_at | 2026-01-01 15:43:09.0803+00 |
| updated_at | 2026-01-01 15:43:09.0803+00 |
| description | Actix-web middleware for mTLS authentication with IP whitelisting |
| homepage | |
| repository | https://github.com/Crellsin/mtls-rs |
| max_upload_size | |
| id | 2016351 |
| size | 77,153 |
Actix Web middleware for mTLS authentication with IP whitelisting.
mtls-actix provides Actix Web middleware for integrating mTLS (mutual TLS) authentication and IP whitelisting into your Actix applications. It validates client certificates and IP addresses before requests reach your handlers.
Add to your Cargo.toml:
[dependencies]
mtls-actix = "0.1.0"
mtls-core = "0.1.0"
use actix_web::{web, App, HttpServer, Responder};
use mtls_actix::MtlsMiddleware;
use mtls_core::validator::ConnectionValidator;
use mtls_core::config::ServerConfig;
use std::path::Path;
async fn hello() -> impl Responder {
"Hello from mTLS-protected server!"
}
#[actix_web::main]
async fn main() -> std::io::Result<()> {
// Configure mTLS server
let server_config = ServerConfig::new(
Path::new("certs/server.crt"),
Path::new("certs/server.key"),
Path::new("certs/ca.crt"),
);
// Create connection validator
let validator = ConnectionValidator::create_for_server(server_config)
.expect("Failed to create connection validator");
// Create mTLS middleware
let mtls_middleware = MtlsMiddleware::new(validator);
// Start HTTP server with mTLS middleware
HttpServer::new(move || {
App::new()
.wrap(mtls_middleware.clone())
.route("/", web::get().to(hello))
})
.bind("127.0.0.1:8080")?
.run()
.await
}
use mtls_core::validator::ConnectionValidator;
use mtls_core::config::ClientConfig;
use std::path::Path;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let client_config = ClientConfig::new(
Path::new("certs/client.crt"),
Path::new("certs/client.key"),
)
.with_ca_cert_path(Path::new("certs/ca.crt"));
let validator = ConnectionValidator::create_for_client(client_config)?;
// Validate connection before making requests
let result = validator.validate_outgoing("example.com", 443).await?;
if result.is_valid {
println!("Connection validated successfully!");
// Now you can make HTTP requests with the validated connection
// or use the validator to configure your HTTP client
}
Ok(())
}
The middleware requires a ConnectionValidator configured for server use:
use mtls_core::config::ServerConfig;
use ipnetwork::IpNetwork;
let server_config = ServerConfig::new(
Path::new("server.crt"),
Path::new("server.key"),
Path::new("ca.crt"),
)
.with_client_ipv4_whitelist(vec![
IpNetwork::new("192.168.1.0".parse()?, 24)?,
IpNetwork::new("10.0.0.0".parse()?, 8)?,
])
.with_require_client_auth(true);
let validator = ConnectionValidator::create_for_server(server_config)?;
let middleware = MtlsMiddleware::new(validator);
For clients that need to validate outgoing connections:
use mtls_core::config::ClientConfig;
let client_config = ClientConfig::new(
Path::new("client.crt"),
Path::new("client.key"),
)
.with_ca_cert_path(Path::new("ca.crt"))
.with_verify_server(true);
let validator = ConnectionValidator::create_for_client(client_config)?;
X-Client-Cert headerRequest → Extract IP → Validate IP → Extract Certificate → Validate Certificate → Handler
↓ ↓ ↓ ↓ ↓
↓ [Invalid] [Reject] [Missing] [Invalid]
↓ ↓ ↓
↓ [Optional] [Reject]
By default, the middleware looks for certificates in the X-Client-Cert header. You can extract certificates from different headers by extending the middleware:
// Custom middleware that extracts from different headers
pub struct CustomMtlsMiddleware {
validator: Rc<ConnectionValidator>,
cert_header: String,
}
impl CustomMtlsMiddleware {
pub fn new(validator: ConnectionValidator, cert_header: &str) -> Self {
Self {
validator: Rc::new(validator),
cert_header: cert_header.to_string(),
}
}
}
The mTLS middleware can be combined with other Actix middleware:
App::new()
.wrap(Logger::default())
.wrap(mtls_middleware)
.wrap(Compress::default())
.route("/", web::get().to(handler))
The middleware returns appropriate HTTP status codes:
X-Forwarded-For headers are properly validatedTest your mTLS-protected endpoints:
#[cfg(test)]
mod tests {
use actix_web::{test, web, App};
use super::*;
#[actix_web::test]
async fn test_mtls_protected_endpoint() {
// Create test validator with test certificates
// ...
let app = test::init_service(
App::new()
.wrap(MtlsMiddleware::new(validator))
.route("/", web::get().to(hello))
).await;
// Test with valid certificate header
let req = test::TestRequest::get()
.insert_header(("X-Client-Cert", "valid-cert-base64"))
.to_request();
let resp = test::call_service(&app, req).await;
assert_eq!(resp.status(), 200);
}
}
Dual-licensed under either:
at your option.
Contributions are welcome! Please see the main project repository for contribution guidelines.