59 lines
2.2 KiB
Diff
59 lines
2.2 KiB
Diff
--- a/lib/virtual-net/src/ruleset.rs
|
|
+++ b/lib/virtual-net/src/ruleset.rs
|
|
@@ -666,7 +666,14 @@ pub enum Rule {
|
|
/// control the inbound and outbound traffic of a network.
|
|
#[derive(Debug, Clone)]
|
|
pub struct Ruleset {
|
|
- rules: Arc<RwLock<Vec<Rule>>>,
|
|
+ /// All rules — kept for iteration order and serialization.
|
|
+ rules: Arc<RwLock<Vec<Rule>>>,
|
|
+ /// Pre-partitioned views for O(1) dispatch:
|
|
+ /// IP rules (IPV4/IPV6/Neg(IP)) — consulted by allows_socket/blocks_socket.
|
|
+ ip_rules: Arc<RwLock<Vec<Rule>>>,
|
|
+ /// DNS rules (DNS/Neg(DNS)) — consulted by allows_domain/blocks_domain.
|
|
+ dns_rules: Arc<RwLock<Vec<Rule>>>,
|
|
}
|
|
|
|
+impl Ruleset {
|
|
+ fn add_rule_internal(
|
|
+ rules: &mut Vec<Rule>,
|
|
+ ip_rules: &mut Vec<Rule>,
|
|
+ dns_rules: &mut Vec<Rule>,
|
|
+ rule: Rule,
|
|
+ ) {
|
|
+ match &rule {
|
|
+ Rule::DNS(_) => dns_rules.push(rule.clone()),
|
|
+ Rule::Neg(inner) => match inner.as_ref() {
|
|
+ Rule::DNS(_) => dns_rules.push(rule.clone()),
|
|
+ _ => ip_rules.push(rule.clone()),
|
|
+ },
|
|
+ _ => ip_rules.push(rule.clone()),
|
|
+ }
|
|
+ rules.push(rule);
|
|
+ }
|
|
+}
|
|
+
|
|
impl Ruleset {
|
|
/// Returns `true` if at least one rule allows accessing `socket_addr` in the specific `direction`
|
|
/// and no rule blocks it
|
|
pub fn allows_socket(&self, addr: impl Into<SocketAddr>, dir: Direction) -> bool {
|
|
let addr = addr.into();
|
|
|
|
{
|
|
- let ruleset = self.rules.read().unwrap();
|
|
+ // Only IP rules are relevant for socket checks — skip DNS rules entirely.
|
|
+ let ruleset = self.ip_rules.read().unwrap();
|
|
|
|
let is_blacklisted = ruleset.iter().any(|r| r.blocks_socket(addr, dir));
|
|
if is_blacklisted {
|
|
@@ -695,7 +702,8 @@ impl Ruleset {
|
|
pub fn allows_domain(&self, domain: impl AsRef<str>) -> bool {
|
|
let domain = domain.as_ref();
|
|
|
|
{
|
|
- let ruleset = self.rules.read().unwrap();
|
|
+ // Only DNS rules are relevant for domain checks — skip IP rules entirely.
|
|
+ let ruleset = self.dns_rules.read().unwrap();
|
|
|
|
let is_blacklisted = ruleset.iter().any(|r| r.blocks_domain(domain));
|
|
if is_blacklisted {
|