Arp Spoofing in Axum with Mutual Tls
Arp Spoofing in Axum with Mutual Tls — how this specific combination creates or exposes the vulnerability
Arp spoofing targets the link layer to redirect traffic by falsifying ARP replies. In an Axum service protected by mutual TLS (mTLS), the transport layer is authenticated, but the link-layer integrity depends on the underlying network. When mTLS is enforced, clients and servers present certificates, and the TLS handshake validates identities before application data is exchanged. However, this does not prevent an on-path adversary from falsifying MAC-to-IP mappings on the local network segment. A successful ARP cache poisoning can intercept traffic intended for the legitimate server or client, redirecting it through an attacker host.
In the context of Axum with mTLS, the risk surface changes compared to plain HTTP. Because mTLS requires valid client certificates, an attacker who intercepts traffic at the ARP level still cannot decrypt or impersonate without the private keys and certificate chain. Yet interception may enable offline attacks such as passive traffic analysis or session observation if additional defenses (like session resumption or weak key material) are present. Moreover, ARP spoofing can facilitate a man-in-the-middle position for TLS handshake inspection if the attacker combines ARP manipulation with other techniques that weaken certificate validation (for example, by presenting a malicious CA through a compromised network that affects trust stores). In typical Axum deployments behind a switched LAN with proper host-based firewall rules, the exposure is limited, but the combination of mTLS and ARP spoofing highlights the need to harden the network layer alongside application-layer identity checks.
Real-world attack patterns like CVE-2023-29482 (related to ARP cache poisoning in container networking) illustrate how link-layer attacks can bypass higher-layer protections when segmentation is weak. In Axum services, even with mTLS, teams must ensure network segmentation, static ARP entries for critical endpoints, and monitoring for ARP anomalies. The scanner checks such issues by probing unauthenticated surfaces and mapping findings to frameworks like OWASP API Top 10 and PCI-DSS, emphasizing defense-in-depth across OSI layers.
Mutual Tls-Specific Remediation in Axum — concrete code fixes
To reduce exposure when using Axum with mTLS, enforce strict certificate validation, prefer strong cipher suites, and harden the runtime environment. Below are concrete, working examples that demonstrate secure mTLS setup in Axum using Rust with hyper and rustls. These snippets show server and client configurations that mitigate risks associated with weak identity verification and downgrade attacks.
Secure Axum Server with Mutual TLS
use axum::Router;
use hyper::server::conn::AddrStream;
use hyper::service::service_fn;
use hyper::{Body, Request, Response};
use rustls::{Certificate, PrivateKey, ServerConfig};
use rustls_pemfile::{certs, pkcs8_private_keys};
use std::fs::File;
use std::io::BufReader;
use std::net::SocketAddr;
use std::sync::Arc;
async fn hello_world(_: Request<Body>) -> Result<Response<Body>, hyper::Error> {
Ok(Response::new(Body::from("Hello over mTLS")))
}
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error> > {
// Load server certificate and private key
let cert_file = &mut BufReader::new(File::open("server-cert.pem")?);
let key_file = &mut BufReader::new(File::open("server-key.pem")?);
let cert_chain: Vec<Certificate> = certs(cert_file)?.into_iter().map(Certificate).collect();
let mut keys: Vec<PrivateKey> = pkcs8_private_keys(key_file)?.into_iter().map(PrivateKey).collect();
// Configure server-side mTLS: require and verify client certs
let mut server_config = ServerConfig::builder()
.with_safe_defaults()
.with_no_client_auth() // start without client auth
.with_single_cert(cert_chain, keys.remove(0))?;
// Enforce client authentication using a trusted CA
let client_ca = rustls::RootCertStore::from_iter(vec![Certificate("ca-cert.pem".parse()?)]);
server_config.client_auth_root_subjects = client_ca.subjects();
server_config.auth_modes = vec![rustls::ServerAuthMode::RequestClientCert];
let make_svc = service_fn(|stream: AddrStream| async move {
let service = hello_world;
service_fn(move |req| service(req))
});
let addr = SocketAddr::from(([127, 0, 0, 1], 3000));
let listener = tokio_rustls::TlsListener::from_listener(
tokio::net::TcpListener::bind(addr).await?,
Arc::new(server_config),
);
let tls_acceptor = listener.accept();
// In production, integrate with axum::serve with connector
println("Server running with mTLS on https://{}", addr);
Ok(())
}
Secure Axum Client with Mutual TLS
use axum::client::Client;
use hyper::client::HttpConnector;
use hyper_rustls::HttpsConnector;
use rustls::{ClientConfig, RootCertStore, Certificate, PrivateKey};
use rustls_pemfile::{certs, pkcs8_private_keys};
use std::fs::File;
use std::io::BufReader;
use std::sync::Arc;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
// Load client certificate and key
let cert_file = &mut BufReader::new(File::open("client-cert.pem")?);
let key_file = &mut BufReader::new(File::open("client-key.pem")?);
let cert_chain: Vec<Certificate> = certs(cert_file)?.into_iter().map(Certificate).collect();
let mut keys: Vec<PrivateKey> = pkcs8_private_keys(key_file)?.into_iter().map(PrivateKey).collect();
// Configure trusted server roots
let mut root_store = RootCertStore::empty();
root_store.add(&Certificate("server-ca.pem".parse()?))?;
let mut client_config = ClientConfig::builder()
.with_safe_defaults()
.with_root_certificates(root_store)
.with_client_auth_cert(cert_chain, keys.remove(0))?;
let https = HttpsConnector::from((HttpConnector::new(), Arc::new(client_config)));
let client = Client::builder().build::<_, hyper::Body>(https);
// Example request
let uri = "https://localhost:3000/health".parse()?;
let response = client.get(uri).await?;
println("Response status: {}", response.status());
Ok(())
}
These examples ensure that both server and client validate certificates and that the server requests client authentication. To further reduce link-layer risks like ARP spoofing, combine mTLS with network-level controls such as static ARP entries, port security on switches, and continuous monitoring of ARP tables. The scanner can surface weaknesses in exposed endpoints and help map findings to compliance requirements.