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
This commit is contained in:
Néfix Estrada 2024-02-02 12:34:53 +01:00 committed by Eugene
parent 79bfa3c81a
commit 0ddc7979ea
3 changed files with 38 additions and 23 deletions

View file

@ -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)

View file

@ -8,22 +8,8 @@ use crate::session_handle::WarpgateServerHandleFromRequest;
pub async fn span_for_request(req: &Request) -> poem::Result<Span> {
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("<unknown>".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<Span> {
})
}
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<String> {
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("<unknown>".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),
}
}

View file

@ -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)