From 0ddc7979ea2ce24c85b59a44f4dbd95e4ac8b1bc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?N=C3=A9fix=20Estrada?= Date: Fri, 2 Feb 2024 12:34:53 +0100 Subject: [PATCH] feat(http): add remote_addr to logs With this change, the remote address will be logged. This enables other software, such as fail2ban, to monitor the logs and make actions if required. Closes #944 --- warpgate-protocol-http/src/lib.rs | 11 +++++-- warpgate-protocol-http/src/logging.rs | 41 +++++++++++++++------------ warpgate-protocol-http/src/proxy.rs | 9 ++++-- 3 files changed, 38 insertions(+), 23 deletions(-) diff --git a/warpgate-protocol-http/src/lib.rs b/warpgate-protocol-http/src/lib.rs index 8870f93..567d312 100644 --- a/warpgate-protocol-http/src/lib.rs +++ b/warpgate-protocol-http/src/lib.rs @@ -19,7 +19,7 @@ use async_trait::async_trait; use common::page_admin_auth; pub use common::PROTOCOL_NAME; use http::HeaderValue; -use logging::{log_request_result, span_for_request}; +use logging::{get_client_ip, log_request_result, span_for_request}; use poem::endpoint::{EmbeddedFileEndpoint, EmbeddedFilesEndpoint}; use poem::listener::{Listener, RustlsConfig, TcpListener}; use poem::middleware::SetHeader; @@ -122,8 +122,11 @@ impl ProtocolServer for HTTPProtocolServer { .around(move |ep, req| async move { let method = req.method().clone(); let url = req.original_uri().clone(); + let client_ip = get_client_ip(&req).await?; + let response = ep.call(req).await?; - log_request_result(&method, &url, &response.status()); + + log_request_result(&method, &url, client_ip, &response.status()); Ok(response) }), ) @@ -206,7 +209,9 @@ impl ProtocolServer for HTTPProtocolServer { async fn test_target(&self, target: Target) -> Result<(), TargetTestError> { let TargetOptions::Http(options) = target.options else { - return Err(TargetTestError::Misconfigured("Not an HTTP target".to_owned())); + return Err(TargetTestError::Misconfigured( + "Not an HTTP target".to_owned(), + )); }; let request = poem::Request::builder().uri_str("http://host/").finish(); crate::proxy::proxy_normal_request(&request, poem::Body::empty(), &options) diff --git a/warpgate-protocol-http/src/logging.rs b/warpgate-protocol-http/src/logging.rs index 19ac325..3d94f7c 100644 --- a/warpgate-protocol-http/src/logging.rs +++ b/warpgate-protocol-http/src/logging.rs @@ -8,22 +8,8 @@ use crate::session_handle::WarpgateServerHandleFromRequest; pub async fn span_for_request(req: &Request) -> poem::Result { let handle = WarpgateServerHandleFromRequest::from_request_without_body(req).await; - let services: Data<&Services> = <_>::from_request_without_body(req).await?; - let config = services.config.lock().await; - let remote_ip = req - .remote_addr() - .as_socket_addr() - .map(|x| x.ip().to_string()) - .unwrap_or("".into()); - - let client_ip = match config.store.http.trust_x_forwarded_headers { - true => req - .header("x-forwarded-for") - .map(|x| x.to_string()) - .unwrap_or(remote_ip), - false => remote_ip, - }; + let client_ip = get_client_ip(req).await?; Ok(match handle { Ok(ref handle) => { @@ -40,10 +26,29 @@ pub async fn span_for_request(req: &Request) -> poem::Result { }) } -pub fn log_request_result(method: &Method, url: &Uri, status: &StatusCode) { +pub fn log_request_result(method: &Method, url: &Uri, client_ip: String, status: &StatusCode) { if status.is_server_error() || status.is_client_error() { - warn!(%method, %url, %status, "Request failed"); + warn!(%method, %url, %status, %client_ip, "Request failed"); } else { - info!(%method, %url, %status, "Request"); + info!(%method, %url, %status, %client_ip, "Request"); + } +} + +pub async fn get_client_ip(req: &Request) -> poem::Result { + let services: Data<&Services> = <_>::from_request_without_body(&req).await?; + let config = services.config.lock().await; + + let remote_ip = req + .remote_addr() + .as_socket_addr() + .map(|x| x.ip().to_string()) + .unwrap_or("".into()); + + match config.store.http.trust_x_forwarded_headers { + true => Ok(req + .header("x-forwarded-for") + .map(|x| x.to_string()) + .unwrap_or(remote_ip)), + false => Ok(remote_ip), } } diff --git a/warpgate-protocol-http/src/proxy.rs b/warpgate-protocol-http/src/proxy.rs index 63d5481..23d8e57 100644 --- a/warpgate-protocol-http/src/proxy.rs +++ b/warpgate-protocol-http/src/proxy.rs @@ -18,7 +18,7 @@ use url::Url; use warpgate_common::{try_block, TargetHTTPOptions, TlsMode, WarpgateError}; use warpgate_web::lookup_built_file; -use crate::logging::log_request_result; +use crate::logging::{get_client_ip, log_request_result}; trait SomeResponse { fn status(&self) -> http::StatusCode; @@ -291,7 +291,12 @@ pub async fn proxy_normal_request( copy_client_response(&client_response, &mut response); copy_client_body(client_response, &mut response).await?; - log_request_result(req.method(), req.original_uri(), &status); + log_request_result( + req.method(), + req.original_uri(), + get_client_ip(req).await?, + &status, + ); rewrite_response(&mut response, options, &uri)?; Ok(response)