mirror of
https://github.com/TrustTunnel/TrustTunnel.git
synced 2026-04-12 14:24:23 +00:00
Squashed commit of the following:
commit 6eae1e962a27b2c3bcb6362f53bb1d7d92a66983
Author: Andrey Yakushin <a.yakushin@adguard.com>
Date: Fri Dec 26 11:46:12 2025 +0400
Run lint on both macos and linux
commit 94254caec3ea166db80c6b3f4004b4126605a1b7
Author: Andrey Yakushin <a.yakushin@adguard.com>
Date: Thu Dec 25 22:44:10 2025 +0400
Fix note again by adding lint hint
commit 5a67ae358a5676a22e85798683674607d2788a51
Author: Andrey Yakushin <a.yakushin@adguard.com>
Date: Thu Dec 25 22:42:02 2025 +0400
Fix note
commit 937b178302244fe237d06b6f38ba0f29db6e0d7e
Author: Andrey Yakushin <a.yakushin@adguard.com>
Date: Thu Dec 25 22:39:45 2025 +0400
Fix README
commit 769c5d9ebdc03e8500f9fc00d7f2b6f316924557
Author: Andrey Yakushin <a.yakushin@adguard.com>
Date: Thu Dec 25 22:39:15 2025 +0400
Cargo update
commit 1e932e4037c2b9ffc4b12f398f1ef14c32b5481e
Merge: dcf6a53 2041edc
Author: Andrey Yakushin <a.yakushin@adguard.com>
Date: Thu Dec 25 22:37:24 2025 +0400
Merge remote-tracking branch 'origin/master' into feature/TRUST-235
commit dcf6a53410e59411a3e05f798ed4be7f7c9994ce
Author: Andrey Yakushin <a.yakushin@adguard.com>
Date: Thu Dec 25 22:24:56 2025 +0400
Get rid of rustls-pemfile and update sentry
commit cb2e26e47d4612d65ae990ec887875bb1ac94456
Author: Andrey Yakushin <a.yakushin@adguard.com>
Date: Thu Dec 25 19:08:23 2025 +0400
Fix tests
commit a3cde3fdf16edfe2e2a574b8d729c2b9d59daf84
Author: Andrey Yakushin <a.yakushin@adguard.com>
Date: Thu Dec 25 18:33:46 2025 +0400
Fix vulnerabilities
commit 35cb9c699a0ddf2eb344c7c475be3c36a26dbf83
Author: Andrey Yakushin <a.yakushin@adguard.com>
Date: Thu Dec 25 17:13:18 2025 +0400
Don't install cargo-audit manually
commit 71a5411ac4fe31fc08c3bacb83d327bf6b7ab8c3
Author: Andrey Yakushin <a.yakushin@adguard.com>
Date: Thu Dec 25 17:07:30 2025 +0400
Install stable rust for cargo-audit
commit b7f38a90054cda39d72760b0ebc3ce295fba95d2
Author: Andrey Yakushin <a.yakushin@adguard.com>
Date: Thu Dec 25 16:54:13 2025 +0400
Fix yaml
commit fbbe78f68b2987280874f23d4ed05ef75ed42f46
Author: Andrey Yakushin <a.yakushin@adguard.com>
Date: Thu Dec 25 16:53:15 2025 +0400
Try to lock cargo-audit version
commit 08f31734b49c70d9dc03c7977ac6182198d1cbde
Author: Andrey Yakushin <a.yakushin@adguard.com>
Date: Thu Dec 25 16:46:06 2025 +0400
Update audit workflow
commit c202f186cd1610439a13928fc1fabac88e83097b
Author: Andrey Yakushin <a.yakushin@adguard.com>
Date: Thu Dec 25 16:30:55 2025 +0400
Install rust tools and better rust cache
commit eccf2fa91efcc4c6e5684960e368892bc68e67cd
Author: Andrey Yakushin <a.yakushin@adguard.com>
Date: Thu Dec 25 16:30:25 2025 +0400
Name for job
commit dccc19f13180e767b8390c8ea32fde4285c0cab8
Author: Andrey Yakushin <a.yakushin@adguard.com>
Date: Thu Dec 25 16:30:17 2025 +0400
Update checkout step version
commit edbb4404bf6fc1927f0184433df9982767a9c762
Author: Andrey Yakushin <a.yakushin@adguard.com>
Date: Thu Dec 25 16:30:02 2025 +0400
Run lint only on linux
commit b59ed893fa55edf030f9ffee2e442c8b947fa28f
Author: Andrey Yakushin <a.yakushin@adguard.com>
Date: Thu Dec 25 16:09:43 2025 +0400
Lint in the same workflow as testing to avoid rebuilds
commit 8d8ecd51859c825d0437361f8c51bde6b46994bc
Author: Andrey Yakushin <a.yakushin@adguard.com>
Date: Thu Dec 25 15:27:23 2025 +0400
More clippy fixes
... and 6 more commits
198 lines
5.7 KiB
Rust
198 lines
5.7 KiB
Rust
use crate::get_mode;
|
|
use crate::user_interaction::{ask_for_agreement, ask_for_input};
|
|
use log::{info, warn};
|
|
use trusttunnel::rules::{Rule, RuleAction, RulesConfig};
|
|
|
|
pub fn build() -> RulesConfig {
|
|
match get_mode() {
|
|
crate::Mode::NonInteractive => build_non_interactive(),
|
|
crate::Mode::Interactive => build_interactive(),
|
|
}
|
|
}
|
|
|
|
fn build_non_interactive() -> RulesConfig {
|
|
// In non-interactive mode, generate empty rules
|
|
// The actual examples will be in the serialized TOML comments
|
|
RulesConfig { rule: vec![] }
|
|
}
|
|
|
|
fn build_interactive() -> RulesConfig {
|
|
info!("Setting up connection filtering rules...");
|
|
|
|
let mut rules = Vec::new();
|
|
|
|
// Ask if user wants to configure rules
|
|
if !ask_for_agreement("Do you want to configure connection filtering rules? (if not, all connections will be allowed)") {
|
|
info!("Skipping rules configuration - all connections will be allowed.");
|
|
return RulesConfig { rule: vec![] };
|
|
}
|
|
|
|
println!();
|
|
println!("You can configure rules to allow/deny connections based on:");
|
|
println!(" - Client IP address (CIDR notation, e.g., 192.168.1.0/24)");
|
|
println!(" - TLS client random prefix (hex-encoded, e.g., aabbcc)");
|
|
println!(" - TLS client random with mask for bitwise matching");
|
|
println!(" - Both conditions together");
|
|
println!();
|
|
|
|
add_custom_rules(&mut rules);
|
|
|
|
RulesConfig { rule: rules }
|
|
}
|
|
|
|
fn add_custom_rules(rules: &mut Vec<Rule>) {
|
|
println!();
|
|
while ask_for_agreement("Add a custom rule?") {
|
|
let rule_type = ask_for_input::<String>(
|
|
"Rule type (1=IP range, 2=client random prefix, 3=both)",
|
|
Some("1".to_string()),
|
|
);
|
|
|
|
match rule_type.as_str() {
|
|
"1" => add_ip_rule(rules),
|
|
"2" => add_client_random_rule(rules),
|
|
"3" => add_combined_rule(rules),
|
|
_ => {
|
|
warn!("Invalid choice. Skipping rule.");
|
|
continue;
|
|
}
|
|
}
|
|
println!();
|
|
}
|
|
}
|
|
|
|
fn add_ip_rule(rules: &mut Vec<Rule>) {
|
|
let cidr = ask_for_input::<String>(
|
|
"Enter IP range in CIDR notation (e.g., 203.0.113.0/24)",
|
|
None,
|
|
);
|
|
|
|
// Validate CIDR format
|
|
if cidr.parse::<ipnet::IpNet>().is_err() {
|
|
warn!("Invalid CIDR format. Skipping rule.");
|
|
return;
|
|
}
|
|
|
|
let action = ask_for_rule_action();
|
|
|
|
rules.push(Rule {
|
|
cidr: Some(cidr),
|
|
client_random_prefix: None,
|
|
action,
|
|
});
|
|
|
|
info!("Rule added successfully.");
|
|
}
|
|
|
|
fn add_client_random_rule(rules: &mut Vec<Rule>) {
|
|
let client_random_value = ask_for_input::<String>(
|
|
"Enter client random prefix (hex, format: prefix[/mask], e.g., aabbcc/ffff0000)",
|
|
None,
|
|
);
|
|
|
|
// Validate format
|
|
if let Some(slash_pos) = client_random_value.find('/') {
|
|
// Format: prefix/mask
|
|
let (prefix_part, mask_part) = client_random_value.split_at(slash_pos);
|
|
let mask_part = &mask_part[1..]; // Skip the '/'
|
|
|
|
if mask_part.is_empty() {
|
|
warn!("Invalid format: mask is empty after '/'. Skipping rule.");
|
|
return;
|
|
}
|
|
|
|
// Validate both prefix and mask are valid hex
|
|
if hex::decode(prefix_part).is_err() {
|
|
warn!("Invalid hex format in prefix part. Skipping rule.");
|
|
return;
|
|
}
|
|
|
|
if hex::decode(mask_part).is_err() {
|
|
warn!("Invalid hex format in mask part. Skipping rule.");
|
|
return;
|
|
}
|
|
} else {
|
|
// Format: just prefix
|
|
if hex::decode(&client_random_value).is_err() {
|
|
warn!("Invalid hex format. Skipping rule.");
|
|
return;
|
|
}
|
|
}
|
|
|
|
let action = ask_for_rule_action();
|
|
|
|
rules.push(Rule {
|
|
cidr: None,
|
|
client_random_prefix: Some(client_random_value),
|
|
action,
|
|
});
|
|
|
|
info!("Rule added successfully.");
|
|
}
|
|
|
|
fn add_combined_rule(rules: &mut Vec<Rule>) {
|
|
let cidr = ask_for_input::<String>(
|
|
"Enter IP range in CIDR notation (e.g., 172.16.0.0/12)",
|
|
None,
|
|
);
|
|
|
|
// Validate CIDR format
|
|
if cidr.parse::<ipnet::IpNet>().is_err() {
|
|
warn!("Invalid CIDR format. Skipping rule.");
|
|
return;
|
|
}
|
|
|
|
let client_random_value = ask_for_input::<String>(
|
|
"Enter client random prefix (hex, format: prefix or prefix/mask, e.g., 001122 or 001122/ffff00)",
|
|
None,
|
|
);
|
|
|
|
// Validate format
|
|
if let Some(slash_pos) = client_random_value.find('/') {
|
|
// Format: prefix/mask
|
|
let (prefix_part, mask_part) = client_random_value.split_at(slash_pos);
|
|
let mask_part = &mask_part[1..]; // Skip the '/'
|
|
|
|
if mask_part.is_empty() {
|
|
warn!("Invalid format: mask is empty after '/'. Skipping rule.");
|
|
return;
|
|
}
|
|
|
|
// Validate both prefix and mask are valid hex
|
|
if hex::decode(prefix_part).is_err() {
|
|
warn!("Invalid hex format in prefix part. Skipping rule.");
|
|
return;
|
|
}
|
|
|
|
if hex::decode(mask_part).is_err() {
|
|
warn!("Invalid hex format in mask part. Skipping rule.");
|
|
return;
|
|
}
|
|
} else {
|
|
// Format: just prefix
|
|
if hex::decode(&client_random_value).is_err() {
|
|
warn!("Invalid hex format. Skipping rule.");
|
|
return;
|
|
}
|
|
}
|
|
|
|
let action = ask_for_rule_action();
|
|
|
|
rules.push(Rule {
|
|
cidr: Some(cidr),
|
|
client_random_prefix: Some(client_random_value),
|
|
action,
|
|
});
|
|
|
|
info!("Rule added successfully.");
|
|
}
|
|
|
|
fn ask_for_rule_action() -> RuleAction {
|
|
let action_str = ask_for_input::<String>("Action (allow/deny)", Some("allow".to_string()));
|
|
|
|
match action_str.to_lowercase().as_str() {
|
|
"deny" => RuleAction::Deny,
|
|
_ => RuleAction::Allow,
|
|
}
|
|
}
|