Skip to content

Commit 11346eb

Browse files
committed
Added support redacting ip addresses
1 parent 0200b4c commit 11346eb

File tree

6 files changed

+90
-7
lines changed

6 files changed

+90
-7
lines changed

README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,9 @@ Compatible with all librespeed clients :
138138
139139
# password for logging into statistics page, fill this to enable stats page
140140
stats_password=""
141+
142+
# redact IP addresses
143+
redact_ip_addresses=false
141144
142145
# database config for : mysql, postgres, sqlite, memory, or disable by write none
143146
# after restarting the service, the in-memory database is reset

configs.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,9 @@ assets_path="./assets" # Write without suffix separator
2020
# password for logging into statistics page, fill this to enable stats page
2121
stats_password=""
2222

23+
# redact IP addresses
24+
redact_ip_addresses=false
25+
2326
# database config for : mysql, postgres, sqlite, memory, or disable by write none
2427
# after restarting the service, the in-memory database is reset
2528
# if none is specified, no telemetry/stats will be recorded, and no result JPG will be generated

src/cmd.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ pub struct Cmd {
1010
pub ipinfo_api_key : Option<String>,
1111
pub assets_path : Option<String>,
1212
pub stats_password : Option<String>,
13+
pub redact_ip_addresses : Option<bool>,
1314
pub database_type : Option<String>,
1415
pub database_hostname : Option<String>,
1516
pub database_name : Option<String>,
@@ -82,6 +83,12 @@ impl Cmd {
8283
.help("Specify the password for logging into statistics page")
8384
.value_parser(value_parser!(String))
8485
)
86+
.arg(
87+
Arg::new("redact-ips")
88+
.long("redact-ips")
89+
.help("Redact IP addresses")
90+
.value_parser(value_parser!(bool))
91+
)
8592
.arg(
8693
Arg::new("database-type")
8794
.long("database-type")
@@ -145,6 +152,7 @@ impl Cmd {
145152
let ipinfo_api_key : Option<String> = args.get_one::<String>("ipinfo-api-key").map(|s| s.to_owned());
146153
let assets_path : Option<String> = args.get_one::<String>("assets-path").map(|s| s.to_owned());
147154
let stats_password : Option<String> = args.get_one::<String>("stats-password").map(|s| s.to_owned());
155+
let redact_ip_addresses : Option<bool> = args.get_one::<bool>("redact-ips").map(|s| s.to_owned());
148156
let database_type : Option<String> = args.get_one::<String>("database-type").map(|s| s.to_owned());
149157
let database_hostname : Option<String> = args.get_one::<String>("database-hostname").map(|s| s.to_owned());
150158
let database_name : Option<String> = args.get_one::<String>("database-name").map(|s| s.to_owned());
@@ -163,6 +171,7 @@ impl Cmd {
163171
ipinfo_api_key,
164172
assets_path,
165173
stats_password,
174+
redact_ip_addresses,
166175
database_type,
167176
database_hostname,
168177
database_name,

src/config/mod.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ pub struct ServerConfig {
4343
pub base_url : String,
4444
pub ipinfo_api_key : String,
4545
pub stats_password : String,
46+
pub redact_ip_addresses : bool,
4647
pub assets_path : String,
4748
pub database_type : String,
4849
pub database_hostname : Option<String>,
@@ -64,6 +65,7 @@ impl Default for ServerConfig {
6465
base_url: "backend".to_string(),
6566
ipinfo_api_key: "".to_string(),
6667
stats_password: "".to_string(),
68+
redact_ip_addresses: false,
6769
assets_path: "".to_string(),
6870
database_type: "none".to_string(),
6971
database_hostname: None,
@@ -191,6 +193,7 @@ fn initialize (mut config: ServerConfig,cmd : Cmd) -> std::io::Result<()> {
191193
config.ipinfo_api_key.set_if_some(cmd.ipinfo_api_key);
192194
config.assets_path.set_if_some(cmd.assets_path);
193195
config.stats_password.set_if_some(cmd.stats_password);
196+
config.redact_ip_addresses.set_if_some(cmd.redact_ip_addresses);
194197
config.database_type.set_if_some(cmd.database_type);
195198
config.database_hostname.set_if_some(cmd.database_hostname);
196199
config.database_name.set_if_some(cmd.database_name);

src/results/mod.rs

Lines changed: 54 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
use std::net::IpAddr;
2+
use std::str::FromStr;
13
use serde::{Deserialize, Serialize};
24

35
pub mod telemetry;
@@ -17,4 +19,55 @@ pub struct TelemetryData {
1719
pub log : String,
1820
pub uuid : String,
1921
pub timestamp : i64,
20-
}
22+
}
23+
24+
pub fn redact_hostname(s: &mut String, replacement: &str) {
25+
let mut result = String::with_capacity(s.len());
26+
let mut idx = 0;
27+
while let Some(start_relative) = s[idx..].find("\"hostname\":\"") {
28+
let start = start_relative + idx;
29+
result.push_str(&s[idx..start]);
30+
result.push_str(replacement);
31+
let value_start = start + "\"hostname\":\"".len();
32+
if let Some(end_relative) = s[value_start..].find('\"') {
33+
let end = value_start + end_relative + 1;
34+
idx = end;
35+
} else {
36+
break;
37+
}
38+
}
39+
result.push_str(&s[idx..]);
40+
*s = result
41+
}
42+
43+
pub fn redact_all_ips(s: &mut String, replacement: &str) {
44+
let mut result = String::with_capacity(s.len());
45+
let chars: Vec<char> = s.chars().collect();
46+
let len = chars.len();
47+
let mut idx = 0;
48+
while idx < len {
49+
let max_ip_length = 39; // IPV6 max len
50+
let remaining = len - idx;
51+
let max_len = if remaining < max_ip_length { remaining } else { max_ip_length };
52+
let mut replaced = false;
53+
for l in (2..=max_len).rev() {
54+
let end = idx + l;
55+
if end > len {
56+
continue;
57+
}
58+
let substr: String = chars[idx..end].iter().collect();
59+
if IpAddr::from_str(&substr).is_ok() {
60+
result.push_str(replacement);
61+
idx += l;
62+
replaced = true;
63+
break;
64+
}
65+
}
66+
if replaced {
67+
continue;
68+
}
69+
result.push(chars[idx]);
70+
idx += 1;
71+
}
72+
*s = result
73+
}

src/results/telemetry.rs

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,28 +9,40 @@ use imageproc::rect::Rect;
99
use log::error;
1010
use tokio::sync::Mutex;
1111

12-
use crate::config::FONT;
12+
use crate::config::{FONT, SERVER_CONFIG};
1313
use crate::config::time::{convert_time_local, get_current_millis};
1414
use crate::database::{Database, generate_uuid};
1515
use crate::http::request::Request;
16+
use crate::results;
1617
use crate::ip::ip_info::IPInfo;
1718
use crate::results::TelemetryData;
1819

1920
pub async fn record_result (request : &Request, database : &mut Arc<Mutex<dyn Database + Send>>) -> std::io::Result<String> {
2021
let default = "".to_string();
21-
let isp_info = request.form_data.get("ispinfo").unwrap_or(&default);
22+
let mut ip_address = request.remote_addr.to_string();
23+
let mut isp_info = request.form_data.get("ispinfo").unwrap_or(&default).clone();
2224
let extra = request.form_data.get("extra").unwrap_or(&default);
2325
let ua = request.headers.get("User-Agent").unwrap_or(&default);
2426
let lang = request.headers.get("Accept-Language").unwrap_or(&default);
2527
let dl = request.form_data.get("dl").unwrap_or(&default);
2628
let ul = request.form_data.get("ul").unwrap_or(&default);
2729
let ping = request.form_data.get("ping").unwrap_or(&default);
2830
let jitter = request.form_data.get("jitter").unwrap_or(&default);
29-
let log = request.form_data.get("log").unwrap_or(&default);
31+
let mut log = request.form_data.get("log").unwrap_or(&default).clone();
3032
let uuid = generate_uuid();
31-
let mut data = database.lock().await;
32-
let insert_db = data.insert(TelemetryData {
33-
ip_address: request.remote_addr.to_string(),
33+
34+
let config = SERVER_CONFIG.get().unwrap();
35+
if config.redact_ip_addresses {
36+
ip_address = "0.0.0.0".to_string();
37+
results::redact_hostname(&mut isp_info,"\"hostname\":\"REDACTED\"");
38+
results::redact_all_ips(&mut isp_info,"0.0.0.0");
39+
results::redact_hostname(&mut log,"\"hostname\":\"REDACTED\"");
40+
results::redact_all_ips(&mut log,"0.0.0.0");
41+
}
42+
43+
let mut database = database.lock().await;
44+
let insert_db = database.insert(TelemetryData {
45+
ip_address,
3446
isp_info: isp_info.to_string(),
3547
extra: extra.to_string(),
3648
user_agent: ua.to_string(),

0 commit comments

Comments
 (0)