nostr-rs-relay

My dev fork of nostr-rs-relay
git clone git://jb55.com/nostr-rs-relay
Log | Files | Refs | README | LICENSE

commit ae5bf98d87aec405f39a54299466dfa122293f91
parent 1cf9d719f0b8e27dc964ab61f277d322d1685a83
Author: Greg Heartsfield <scsibug@imap.cc>
Date:   Fri,  4 Nov 2022 18:05:01 -0500

feat: retrieve client IP from header in config.toml

If the config.toml has defined a HTTP header to look for a remote IP,
that will be logged.  Otherwise, the socket address IP will be used.

closes: https://todo.sr.ht/~gheartsfield/nostr-rs-relay/47

Diffstat:
Mconfig.toml | 5+++++
Msrc/config.rs | 3++-
Msrc/server.rs | 31++++++++++++++-----------------
3 files changed, 21 insertions(+), 18 deletions(-)

diff --git a/config.toml b/config.toml @@ -46,6 +46,11 @@ address = "0.0.0.0" # Listen on this port port = 8080 +# If present, read this HTTP header for logging client IP addresses. +# Examples for common proxies, cloudflare: +#remote_ip_header = "x-forwarded-for" +#remote_ip_header = "cf-connecting-ip" + [options] # Reject events that have timestamps greater than this many seconds in # the future. Recommended to reject anything greater than 30 minutes diff --git a/src/config.rs b/src/config.rs @@ -28,9 +28,9 @@ pub struct Database { pub struct Network { pub port: u16, pub address: String, + pub remote_ip_header: Option<String>, // retrieve client IP from this HTTP header if present } -// #[derive(Debug, Clone, Serialize, Deserialize)] #[allow(unused)] pub struct Options { @@ -208,6 +208,7 @@ impl Default for Settings { network: Network { port: 8080, address: "0.0.0.0".to_owned(), + remote_ip_header: None, }, limits: Limits { messages_per_sec: None, diff --git a/src/server.rs b/src/server.rs @@ -85,9 +85,17 @@ async fn handle_web_request( Some(config), ) .await; - // spawn server with info... but include IP here. + + // determine the remote IP from headers if the exist + let header_ip = settings + .network + .remote_ip_header + .as_ref() + .and_then(|x| get_header_remote_ip(x, request.headers())); + // use the socket addr as a backup let remote_ip = - get_remote_ip_string(&remote_addr, request.headers()); + header_ip.unwrap_or_else(|| remote_addr.ip().to_string()); + // spawn a nostr server with our websocket tokio::spawn(nostr_server( pool, remote_ip, settings, ws_stream, broadcast, event_tx, shutdown, @@ -153,21 +161,10 @@ async fn handle_web_request( } } -fn get_remote_ip_string(remote_addr: &SocketAddr, headers: &HeaderMap) -> String { - if let Some(ip) = get_cloudflare_remote_ip(headers) { - return ip; - } - - return remote_addr.ip().to_string(); -} - -fn get_cloudflare_remote_ip(headers: &HeaderMap) -> Option<String> { - if let Some(val) = headers.get("CF-Connecting-IP") { - if let Ok(s) = val.to_str() { - return Some(s.to_string()); - } - } - return None; +fn get_header_remote_ip(header: &str, headers: &HeaderMap) -> Option<String> { + headers + .get(header) + .and_then(|x| x.to_str().ok().map(|x| x.to_string())) } // return on a control-c or internally requested shutdown signal