Fetch client ip from X-Forwarded-For, if possible
This commit is contained in:
parent
e21e5fffa5
commit
4007c07dc5
3 changed files with 18 additions and 7 deletions
1
Cargo.lock
generated
1
Cargo.lock
generated
|
@ -224,6 +224,7 @@ dependencies = [
|
||||||
"clap",
|
"clap",
|
||||||
"flume",
|
"flume",
|
||||||
"hashbrown",
|
"hashbrown",
|
||||||
|
"http",
|
||||||
"http-body",
|
"http-body",
|
||||||
"itertools 0.14.0",
|
"itertools 0.14.0",
|
||||||
"rand",
|
"rand",
|
||||||
|
|
|
@ -11,6 +11,7 @@ chrono = "0.4.40"
|
||||||
clap = { version = "4.5.37", features = ["derive"] }
|
clap = { version = "4.5.37", features = ["derive"] }
|
||||||
flume = "0.11.1"
|
flume = "0.11.1"
|
||||||
hashbrown = "0.15.2"
|
hashbrown = "0.15.2"
|
||||||
|
http = "1.3.1"
|
||||||
http-body = "1.0.1"
|
http-body = "1.0.1"
|
||||||
itertools = "0.14.0"
|
itertools = "0.14.0"
|
||||||
rand = "0.9.1"
|
rand = "0.9.1"
|
||||||
|
|
23
src/main.rs
23
src/main.rs
|
@ -10,6 +10,7 @@ use axum::{
|
||||||
use axum_server::{bind_rustls, tls_rustls::RustlsConfig};
|
use axum_server::{bind_rustls, tls_rustls::RustlsConfig};
|
||||||
use clap::Parser;
|
use clap::Parser;
|
||||||
use hashbrown::HashMap;
|
use hashbrown::HashMap;
|
||||||
|
use http::HeaderMap;
|
||||||
use http_body::Frame;
|
use http_body::Frame;
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
use rand::{prelude::*, Rng as _};
|
use rand::{prelude::*, Rng as _};
|
||||||
|
@ -17,7 +18,7 @@ use rand_chacha::{rand_core::SeedableRng, ChaCha8Rng};
|
||||||
use std::{
|
use std::{
|
||||||
borrow::Cow,
|
borrow::Cow,
|
||||||
convert::Infallible,
|
convert::Infallible,
|
||||||
net::SocketAddr,
|
net::{IpAddr, SocketAddr},
|
||||||
path::PathBuf,
|
path::PathBuf,
|
||||||
pin::Pin,
|
pin::Pin,
|
||||||
sync::{
|
sync::{
|
||||||
|
@ -93,7 +94,7 @@ impl IntoResponse for SlowBody {
|
||||||
}
|
}
|
||||||
|
|
||||||
struct RequestStats {
|
struct RequestStats {
|
||||||
sock: SocketAddr,
|
ip: IpAddr,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
|
@ -124,11 +125,19 @@ async fn main() {
|
||||||
Router::new().route(
|
Router::new().route(
|
||||||
"/{id}",
|
"/{id}",
|
||||||
get(
|
get(
|
||||||
|Path(id): Path<String>, ConnectInfo(sock): ConnectInfo<SocketAddr>| async move {
|
|Path(id): Path<String>,
|
||||||
|
ConnectInfo(sock): ConnectInfo<SocketAddr>,
|
||||||
|
headers: HeaderMap| async move {
|
||||||
// Create a RNG for this path (deterministic, to simulate static pages)
|
// Create a RNG for this path (deterministic, to simulate static pages)
|
||||||
let mut rng = create_rng(id.bytes());
|
let mut rng = create_rng(id.bytes());
|
||||||
|
|
||||||
stats_tx.send(RequestStats { sock }).unwrap();
|
let ip = headers
|
||||||
|
.get("X-Forwarded-For")
|
||||||
|
.and_then(|h| h.to_str().ok())
|
||||||
|
.and_then(|h| h.split(',').next())
|
||||||
|
.and_then(|s| s.trim().parse().ok())
|
||||||
|
.unwrap_or_else(|| sock.ip());
|
||||||
|
stats_tx.send(RequestStats { ip }).unwrap();
|
||||||
|
|
||||||
// Count the request. Also doubles as the non-deterministic seed
|
// Count the request. Also doubles as the non-deterministic seed
|
||||||
let count = counter.fetch_add(1, Ordering::Relaxed);
|
let count = counter.fetch_add(1, Ordering::Relaxed);
|
||||||
|
@ -197,7 +206,7 @@ async fn main() {
|
||||||
interval.tick().await;
|
interval.tick().await;
|
||||||
|
|
||||||
while let Ok(stats) = stats_rx.try_recv() {
|
while let Ok(stats) = stats_rx.try_recv() {
|
||||||
*worst_offenders.entry(stats.sock.ip()).or_default() += 1;
|
*worst_offenders.entry(stats.ip).or_default() += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
let count = counter.load(Ordering::Relaxed);
|
let count = counter.load(Ordering::Relaxed);
|
||||||
|
@ -210,8 +219,8 @@ async fn main() {
|
||||||
let stats = worst_offenders
|
let stats = worst_offenders
|
||||||
.iter()
|
.iter()
|
||||||
.enumerate()
|
.enumerate()
|
||||||
.map(|(i, (sock, n))| format!("#{:>4} | {:>4} | {}", i + 1, n, sock))
|
.map(|(i, (ip, n))| format!("#{:>4} | {:>4} | {}\n", i + 1, n, ip))
|
||||||
.join("\n");
|
.collect::<String>();
|
||||||
let _ = std::fs::write(STATS_FILE, &stats);
|
let _ = std::fs::write(STATS_FILE, &stats);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue