aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--readme.md3
-rw-r--r--src/config.rs2
-rw-r--r--src/error.rs3
-rw-r--r--src/main.rs20
4 files changed, 26 insertions, 2 deletions
diff --git a/readme.md b/readme.md
index c8ed4e5..f93438d 100644
--- a/readme.md
+++ b/readme.md
@@ -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),