Files
TrustTunnel/tools/setup_wizard/rules_settings.rs
Andrey Yakushin 783908b315 Pull request 121: Clippy and github actions
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
2025-12-26 12:45:09 +03:00

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,
}
}