diff options
author | metamuffin <metamuffin@disroot.org> | 2025-03-31 19:45:31 +0200 |
---|---|---|
committer | metamuffin <metamuffin@disroot.org> | 2025-03-31 19:45:31 +0200 |
commit | dd105f82d89070c6929f070a87848b9a9ac8799a (patch) | |
tree | 48395074f0c662d51d6a6cc95d0347ecca3614c5 | |
parent | 939091713a21ac6e508ef365f8ee9f258f6d50f8 (diff) | |
download | gnix-dd105f82d89070c6929f070a87848b9a9ac8799a.tar gnix-dd105f82d89070c6929f070a87848b9a9ac8799a.tar.bz2 gnix-dd105f82d89070c6929f070a87848b9a9ac8799a.tar.zst |
add source_ip_from_header option
-rw-r--r-- | readme.md | 3 | ||||
-rw-r--r-- | src/config.rs | 2 | ||||
-rw-r--r-- | src/error.rs | 3 | ||||
-rw-r--r-- | src/main.rs | 20 |
4 files changed, 26 insertions, 2 deletions
@@ -95,6 +95,9 @@ reported in stderr and are only fatal at startup. - **section `handler`** - A module to handle all requests. Usually an instance of `hosts` or `paths`. +- `source_ip_from_header`: Uses the X-Real-IP header for source ip address, + requests without it will be rejected. Useful when gnix is behing another + proxy. - `watch_config`: boolean if to watch the configuration file for changes and apply them accordingly. Default: true (Note: This will watch the entire parent directory of the config since most editors first move the file. Currently any diff --git a/src/config.rs b/src/config.rs index 4d47757..9473784 100644 --- a/src/config.rs +++ b/src/config.rs @@ -37,6 +37,8 @@ pub struct Config { pub private_key: [u8; 32], #[serde(default)] pub limits: Limits, + #[serde(default)] + pub source_ip_from_header: bool, pub handler: DynNode, #[serde(default)] pub disable_server_header: bool, diff --git a/src/error.rs b/src/error.rs index cccfd78..4237a5e 100644 --- a/src/error.rs +++ b/src/error.rs @@ -53,6 +53,8 @@ pub enum ServiceError { ParseIntError(#[from] std::num::ParseIntError), #[error("invalid header")] InvalidHeader, + #[error("X-Real-IP header missing, your proxy is misconfigured")] + XRealIPMissing, #[error("invalid uri")] InvalidUri, #[error("too many concurrent users, please retry later")] @@ -89,6 +91,7 @@ impl ServiceError { ServiceError::CustomStatic(_) => StatusCode::BAD_REQUEST, ServiceError::ParseIntError(_) => StatusCode::BAD_REQUEST, ServiceError::InvalidHeader => StatusCode::BAD_REQUEST, + ServiceError::XRealIPMissing => StatusCode::INTERNAL_SERVER_ERROR, ServiceError::InvalidUri => StatusCode::BAD_REQUEST, ServiceError::TooManyIdentities => StatusCode::TOO_MANY_REQUESTS, ServiceError::Other => StatusCode::INTERNAL_SERVER_ERROR, diff --git a/src/main.rs b/src/main.rs index 7fb07ca..9f395e2 100644 --- a/src/main.rs +++ b/src/main.rs @@ -40,7 +40,12 @@ use log::{debug, error, info, warn, LevelFilter}; use modules::{NodeContext, MODULES}; use quinn::crypto::rustls::QuicServerConfig; use std::{ - collections::HashMap, net::SocketAddr, path::PathBuf, process::exit, str::FromStr, sync::Arc, + collections::HashMap, + net::{IpAddr, SocketAddr}, + path::PathBuf, + process::exit, + str::FromStr, + sync::Arc, }; use tokio::{ fs::File, @@ -370,7 +375,7 @@ fn error_response(addr: SocketAddr, error: ServiceError) -> Response<BoxBody<Byt async fn service( state: Arc<State>, mut request: Request<BoxBody<Bytes, ServiceError>>, - addr: SocketAddr, + mut addr: SocketAddr, secure: bool, listen_addr: SocketAddr, ) -> Result<hyper::Response<BoxBody<bytes::Bytes, ServiceError>>, ServiceError> { @@ -389,6 +394,17 @@ async fn service( } } + if config.source_ip_from_header { + if let Some(x) = request.headers_mut().remove("x-real-ip") { + addr = SocketAddr::new( + IpAddr::from_str(x.to_str()?).map_err(|_| ServiceError::InvalidHeader)?, + 0, + ); + } else { + return Err(ServiceError::XRealIPMissing); + } + } + debug!( "{addr} ~> {:?} {}", request.headers().get(HOST), |