diff options
author | metamuffin <metamuffin@disroot.org> | 2025-03-04 21:46:50 +0100 |
---|---|---|
committer | metamuffin <metamuffin@disroot.org> | 2025-03-04 21:51:06 +0100 |
commit | 5d3cc44e423e40b0485167fc5d2e89a80d4d6e8f (patch) | |
tree | 088ba186f750bda0cee5e214e80f89f7266412ae | |
parent | 96da4a575ebcfa38ab0a789ac8c25a0af03896a7 (diff) | |
download | gnix-5d3cc44e423e40b0485167fc5d2e89a80d4d6e8f.tar gnix-5d3cc44e423e40b0485167fc5d2e89a80d4d6e8f.tar.bz2 gnix-5d3cc44e423e40b0485167fc5d2e89a80d4d6e8f.tar.zst |
x-forwaded-... headers in proxy module
-rw-r--r-- | readme.md | 4 | ||||
-rw-r--r-- | src/main.rs | 14 | ||||
-rw-r--r-- | src/modules/mod.rs | 1 | ||||
-rw-r--r-- | src/modules/proxy.rs | 36 |
4 files changed, 47 insertions, 8 deletions
@@ -110,6 +110,10 @@ themselves; in that case the request is passed on. added to the request. Connection upgrades are handled by direct forwarding of network traffic. - `backend`: socket address (string) to the backend server + - `set_real_ip`: Sets the `X-Real-IP` header. (boolean) + - `set_forwarded_for`: Sets the `X-Forwarded-For`, `X-Forwarded-Host`, + `X-Forwaded-Proto`, `X-Forwarded-Scheme` and `X-Forwarded-Port` headers. + (boolean) - **module `files`** - Provides a simple built-in fileserver. The server handles `accept-ranges`. diff --git a/src/main.rs b/src/main.rs index c3e8cc7..fe7856e 100644 --- a/src/main.rs +++ b/src/main.rs @@ -127,7 +127,7 @@ async fn serve_http(state: Arc<State>) -> Result<()> { debug!("connection from {addr}"); let stream = TokioIo::new(stream); let state = state.clone(); - tokio::spawn(async move { serve_stream(state, stream, addr).await }); + tokio::spawn(async move { serve_stream(state, stream, addr, false).await }); } })) .await; @@ -163,7 +163,7 @@ async fn serve_https(state: Arc<State>) -> Result<()> { tokio::task::spawn(async move { debug!("connection from {addr}"); match tls_acceptor.accept(stream).await { - Ok(stream) => serve_stream(state, TokioIo::new(stream), addr).await, + Ok(stream) => serve_stream(state, TokioIo::new(stream), addr, true).await, Err(e) => warn!("error accepting tls: {e}"), }; }); @@ -178,6 +178,7 @@ pub async fn serve_stream<T: Unpin + Send + 'static + hyper::rt::Read + hyper::r state: Arc<State>, stream: T, addr: SocketAddr, + secure: bool, ) { if let Ok(_semaphore) = state.l_incoming.try_acquire() { let builder = hyper_util::server::conn::auto::Builder::new(TokioExecutor::new()); @@ -187,7 +188,7 @@ pub async fn serve_stream<T: Unpin + Send + 'static + hyper::rt::Read + hyper::r let state = state.clone(); async move { let config = state.config.read().await.clone(); - match service(state, config, req, addr).await { + match service(state, config, req, addr, secure).await { Ok(r) => Ok(r), Err(ServiceError::Hyper(e)) => Err(e), Err(error) => Ok({ @@ -220,6 +221,7 @@ async fn service( config: Arc<Config>, mut request: Request<Incoming>, addr: SocketAddr, + secure: bool, ) -> Result<hyper::Response<BoxBody<bytes::Bytes, ServiceError>>, ServiceError> { // move uri authority used in HTTP/2 to Host header field { @@ -241,7 +243,11 @@ async fn service( request.uri() ); - let mut context = NodeContext { addr, state }; + let mut context = NodeContext { + addr, + state, + secure, + }; let mut resp = config .handler .handle(&mut context, request.map(|body| body.boxed())) diff --git a/src/modules/mod.rs b/src/modules/mod.rs index 97dee1a..d3e0dd3 100644 --- a/src/modules/mod.rs +++ b/src/modules/mod.rs @@ -55,6 +55,7 @@ pub static MODULES: &[&dyn NodeKind] = &[ pub struct NodeContext { pub state: Arc<State>, pub addr: SocketAddr, + pub secure: bool, } pub trait NodeKind: Send + Sync + 'static { diff --git a/src/modules/proxy.rs b/src/modules/proxy.rs index 763129f..b1af3d9 100644 --- a/src/modules/proxy.rs +++ b/src/modules/proxy.rs @@ -15,9 +15,16 @@ pub struct ProxyKind; #[derive(Debug, Deserialize)] struct Proxy { + set_forwarded_for: bool, + #[serde(default = "ret_true")] + set_real_ip: bool, backend: SocketAddr, } +fn ret_true() -> bool { + true +} + impl NodeKind for ProxyKind { fn name(&self) -> &'static str { "proxy" @@ -33,10 +40,31 @@ impl Node for Proxy { mut request: NodeRequest, ) -> Pin<Box<dyn Future<Output = Result<NodeResponse, ServiceError>> + Send + Sync + 'a>> { Box::pin(async move { - request.headers_mut().insert( - "x-real-ip", - HeaderValue::from_str(&format!("{}", context.addr.ip())).unwrap(), - ); + if self.set_real_ip { + request.headers_mut().insert( + "x-real-ip", + HeaderValue::from_str(&format!("{}", context.addr.ip())).unwrap(), + ); + } + if self.set_forwarded_for { + request.headers_mut().insert( + "x-forwarded-for", + HeaderValue::from_str(&format!("{}", context.addr.ip())).unwrap(), + ); + request.headers_mut().insert( + "x-forwarded-port", + HeaderValue::from_str(&context.addr.port().to_string()).unwrap(), + ); + let scheme = + HeaderValue::from_str(if context.secure { "https" } else { "http" }).unwrap(); + request + .headers_mut() + .insert("x-forwarded-scheme", scheme.clone()); + request.headers_mut().insert("x-forwarded-proto", scheme); + if let Some(host) = request.headers().get("host").cloned() { + request.headers_mut().insert("x-forwarded-host", host); + } + } let on_upgrade_downstream = request.extensions_mut().remove::<OnUpgrade>(); |