Pierre HUBERT ba33939326
All checks were successful
continuous-integration/drone/push Build is passing
fix: typo in readme
2026-04-15 18:27:57 +02:00
2026-04-15 18:23:47 +02:00
2026-04-15 18:23:47 +02:00
2026-04-15 17:42:37 +02:00
2026-04-15 17:55:36 +02:00
2026-04-15 18:23:47 +02:00
2026-04-15 18:27:57 +02:00
2026-04-15 18:23:47 +02:00

Axum remote IP

Crate

Tiny extractor of remote user IP address, that handles reverse proxy.

The X-Forwarded-For header is automatically parsed when the request comes from a defined proxy, to determine the real remote client IP Address.

This crate is designed for axum. If your project is based on actix please have a look at actix-remote-ip

Note : regarding IPv6 addresses, the local part of the address is discarded. For example, the IPv6 client 2001:0db8:85a3:0000:0000:8a2e:0370:7334 will be returned as 2001:0db8:85a3:0000:0000:0000:0000:0000

Configuration

Configure it when you configure your Axum server:

#[tokio::main]
async fn main() {
    tracing_subscriber::fmt::init();

    let app = Router::new().route("/", get(home)).layer(
        ServiceBuilder::new()
            .layer(RemoteIPConfig::parse_opt(Some("10.0.0.0/24, 2001:2345:2345:1234::/48")).into_extension())
            .layer(TraceLayer::new_for_http()),
    );

    tracing::info!("start to listen on http://0.0.0.0:8000");
    let listener = tokio::net::TcpListener::bind("0.0.0.0:8000")
        .await
        .expect("Failed to bind server!");
    axum::serve(
        listener,
        app.into_make_service_with_connect_info::<SocketAddr>(), // this is mandatory to check if remote client is a trusted proxy or not
    )
        .await
        .expect("Failed to run server!");
}

Usage

In your routes, add a RemoteIP parameter:

async fn home(RemoteIP(ip): RemoteIP) -> String {
    ip.to_string()
}
Description
Tiny crate to determine real client IP address on Axum
Readme 38 KiB
Languages
Rust 100%