Skip to content

Commit 4669a34

Browse files
committed
fix(hosted): use trusted proxy to remove trusted ips in logs, fix errors in operator
1 parent 9e93693 commit 4669a34

File tree

3 files changed

+51
-5
lines changed

3 files changed

+51
-5
lines changed

src/api/ffi.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ pub unsafe extern "C" fn redirectionio_api_create_log_in_json(
4848
let request = &*_request;
4949
let response_headers = header_map_to_http_headers(_response_headers);
5050

51-
let log = Log::from_proxy(request, code, &response_headers, action, proxy, time, client_ip);
51+
let log = Log::from_proxy(request, code, &response_headers, action, proxy, time, client_ip, None);
5252

5353
let log_serialized = match json_encode(&log) {
5454
Err(_) => return null(),

src/api/log.rs

Lines changed: 41 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
use crate::action::Action;
2-
use crate::http::{Header, Request};
2+
use crate::http::{Header, Request, TrustedProxies};
33
use serde::{Deserialize, Serialize};
4+
use std::net::IpAddr;
45
use std::time::{SystemTime, UNIX_EPOCH};
56

67
#[derive(Serialize, Deserialize, Debug, Clone)]
@@ -76,12 +77,20 @@ impl Log {
7677
proxy: &str,
7778
time: u64,
7879
client_ip: &str,
80+
trusted_proxies: Option<&TrustedProxies>,
7981
) -> Log {
8082
let mut location = None;
8183
let mut user_agent = None;
8284
let mut referer = None;
8385
let mut content_type = None;
84-
let mut ips = vec![client_ip.to_string()];
86+
let mut ips = Vec::new();
87+
88+
match client_ip.parse::<IpAddr>() {
89+
Ok(ip) => ips.push(ip),
90+
Err(e) => {
91+
log::error!("cannot parse ip address {}, skipping: {}", client_ip, e);
92+
}
93+
}
8594

8695
for header in &request.headers {
8796
if header.name.to_lowercase() == "user-agent" {
@@ -96,11 +105,39 @@ impl Log {
96105
let forwarded_ips = header.value.split(',');
97106

98107
for forwarded_ip in forwarded_ips {
99-
ips.push(forwarded_ip.trim().to_string());
108+
match forwarded_ip.parse::<IpAddr>() {
109+
Ok(ip) => ips.push(ip),
110+
Err(e) => {
111+
log::error!("cannot parse ip address {}, skipping: {}", forwarded_ip, e);
112+
}
113+
}
114+
}
115+
}
116+
117+
if header.name.to_lowercase() == "forwarded" {
118+
for (name, val) in header.value.split(';').flat_map(|val| val.split(',')).flat_map(|pair| {
119+
let mut items = pair.trim().splitn(2, '=');
120+
Some((items.next()?, items.next()?))
121+
}) {
122+
if name.trim().to_lowercase().as_str() == "for" {
123+
let ip = val.trim().trim_start_matches('"').trim_end_matches('"').to_string();
124+
125+
match ip.parse::<IpAddr>() {
126+
Ok(ip) => ips.push(ip),
127+
Err(e) => {
128+
log::error!("cannot parse ip address {}, skipping: {}", ip, e);
129+
}
130+
}
131+
}
100132
}
101133
}
102134
}
103135

136+
let untrusted_ips = match trusted_proxies {
137+
Some(trusted_proxies) => trusted_proxies.remove_trusted_ips(ips),
138+
None => ips,
139+
};
140+
104141
for header in response_headers {
105142
if header.name.to_lowercase() == "location" {
106143
location = Some(header.value.clone())
@@ -127,7 +164,7 @@ impl Log {
127164
from,
128165
proxy: proxy.to_string(),
129166
time,
130-
ips: Some(ips),
167+
ips: Some(untrusted_ips.iter().map(|ip| ip.to_string()).collect()),
131168
to: location.unwrap_or_default(),
132169
}
133170
}

src/http/trusted_proxies.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,19 @@
11
use cidr::{errors::NetworkParseError, AnyIpCidr};
22
use std::net::IpAddr;
3+
use std::str::FromStr;
34

45
#[derive(Debug, Clone, Default)]
56
pub struct TrustedProxies(Vec<AnyIpCidr>);
67

78
impl TrustedProxies {
9+
pub fn new_local() -> Self {
10+
Self(vec![
11+
AnyIpCidr::from_str("10.0.0.0/8").unwrap(),
12+
AnyIpCidr::from_str("172.16.0.0/12").unwrap(),
13+
AnyIpCidr::from_str("192.168.0.0/16").unwrap(),
14+
])
15+
}
16+
817
pub fn len(&self) -> usize {
918
self.0.len()
1019
}

0 commit comments

Comments
 (0)