Skip to content

Commit

Permalink
no regex match for protocol inspect policy rules
Browse files Browse the repository at this point in the history
  • Loading branch information
zh-jq-b committed Oct 11, 2024
1 parent 113c3ee commit 25fb869
Show file tree
Hide file tree
Showing 4 changed files with 154 additions and 76 deletions.
70 changes: 63 additions & 7 deletions lib/g3-dpi/src/config/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,11 @@ use std::fmt;
use std::str::FromStr;
use std::time::Duration;

use g3_types::acl::ActionContract;
use g3_types::acl_set::{AclDstHostRuleSet, AclDstHostRuleSetBuilder};
use g3_types::acl::{
AclChildDomainRule, AclChildDomainRuleBuilder, AclExactHostRule, AclNetworkRule,
AclNetworkRuleBuilder, ActionContract,
};
use g3_types::net::Host;

mod size_limit;

Expand All @@ -37,7 +40,9 @@ pub use imap::ImapInterceptionConfig;
#[derive(Clone)]
pub struct ProtocolInspectPolicyBuilder {
missed_action: ProtocolInspectAction,
pub rule_set: AclDstHostRuleSetBuilder<ProtocolInspectAction>,
pub exact: Option<AclExactHostRule<ProtocolInspectAction>>,
pub child: Option<AclChildDomainRuleBuilder<ProtocolInspectAction>>,
pub subnet: Option<AclNetworkRuleBuilder<ProtocolInspectAction>>,
}

impl Default for ProtocolInspectPolicyBuilder {
Expand All @@ -50,20 +55,71 @@ impl ProtocolInspectPolicyBuilder {
pub fn new(missed_action: ProtocolInspectAction) -> Self {
ProtocolInspectPolicyBuilder {
missed_action,
rule_set: AclDstHostRuleSetBuilder::default(),
exact: None,
child: None,
subnet: None,
}
}

pub fn set_missed_action(&mut self, missed_action: ProtocolInspectAction) {
self.missed_action = missed_action;
}

pub fn build(&self) -> AclDstHostRuleSet<ProtocolInspectAction> {
self.rule_set.build_with_missed_action(self.missed_action)
pub fn build(&self) -> ProtocolInspectPolicy {
ProtocolInspectPolicy {
exact: self.exact.clone(),
child: self.child.as_ref().map(|b| b.build()),
subnet: self.subnet.as_ref().map(|b| b.build()),
missed_action: self.missed_action,
}
}
}

pub type ProtocolInspectPolicy = AclDstHostRuleSet<ProtocolInspectAction>;
pub struct ProtocolInspectPolicy {
exact: Option<AclExactHostRule<ProtocolInspectAction>>,
child: Option<AclChildDomainRule<ProtocolInspectAction>>,
subnet: Option<AclNetworkRule<ProtocolInspectAction>>,
missed_action: ProtocolInspectAction,
}

impl ProtocolInspectPolicy {
pub fn check(&self, upstream: &Host) -> (bool, ProtocolInspectAction) {
match upstream {
Host::Ip(ip) => {
if let Some(rule) = &self.exact {
let (found, action) = rule.check_ip(ip);
if found {
return (true, action);
}
}

if let Some(rule) = &self.subnet {
let (found, action) = rule.check(*ip);
if found {
return (true, action);
}
}
}
Host::Domain(domain) => {
if let Some(rule) = &self.exact {
let (found, action) = rule.check_domain(domain);
if found {
return (true, action);
}
}

if let Some(rule) = &self.child {
let (found, action) = rule.check(domain);
if found {
return (true, action);
}
}
}
}

(false, self.missed_action)
}
}

#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)]
pub enum ProtocolInspectAction {
Expand Down
97 changes: 71 additions & 26 deletions lib/g3-types/src/acl/regex_set.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,69 +14,114 @@
* limitations under the License.
*/

use std::collections::HashMap;

use regex::{Regex, RegexSet};
use rustc_hash::FxHashMap;

use super::{AclAction, ActionContract};
use super::AclAction;

#[derive(Clone, Debug, Eq, PartialEq)]
pub struct AclRegexSetRuleBuilder<Action = AclAction> {
inner: FxHashMap<String, Action>,
missed_action: Action,
pub struct AclRegexSetRuleBuilder {
inner: HashMap<String, AclAction>,
missed_action: AclAction,
}

impl<Action: ActionContract> AclRegexSetRuleBuilder<Action> {
pub fn new(missed_action: Action) -> Self {
impl Default for AclRegexSetRuleBuilder {
fn default() -> Self {
Self::new(AclAction::Forbid)
}
}

impl AclRegexSetRuleBuilder {
pub fn new(missed_action: AclAction) -> Self {
AclRegexSetRuleBuilder {
inner: FxHashMap::default(),
inner: HashMap::new(),
missed_action,
}
}

#[inline]
pub fn add_regex(&mut self, regex: &Regex, action: Action) {
pub fn add_regex(&mut self, regex: &Regex, action: AclAction) {
self.inner.insert(regex.as_str().to_string(), action);
}

#[inline]
pub fn set_missed_action(&mut self, action: Action) {
pub fn set_missed_action(&mut self, action: AclAction) {
self.missed_action = action;
}

#[inline]
pub fn missed_action(&self) -> Action {
pub fn missed_action(&self) -> AclAction {
self.missed_action
}

pub fn build(&self) -> AclRegexSetRule<Action> {
let mut set_map: FxHashMap<Action, Vec<_>> = FxHashMap::default();
pub fn build(&self) -> AclRegexSetRule {
let mut forbid_log_v = Vec::new();
let mut forbid_v = Vec::new();
let mut permit_log_v = Vec::new();
let mut permit_v = Vec::new();

for (r, action) in &self.inner {
set_map.entry(*action).or_default().push(r.as_str());
match action {
AclAction::ForbidAndLog => forbid_log_v.push(r.as_str()),
AclAction::Forbid => forbid_v.push(r.as_str()),
AclAction::PermitAndLog => permit_log_v.push(r.as_str()),
AclAction::Permit => permit_v.push(r.as_str()),
}
}

fn build_rs_from_vec(v: &[&str]) -> Option<RegexSet> {
if v.is_empty() {
None
} else {
Some(RegexSet::new(v).unwrap())
}
}

AclRegexSetRule {
set_map: set_map
.into_iter()
.map(|(k, v)| (k, RegexSet::new(v).unwrap()))
.collect(),
forbid_log: build_rs_from_vec(&forbid_log_v),
forbid: build_rs_from_vec(&forbid_v),
permit_log: build_rs_from_vec(&permit_log_v),
permit: build_rs_from_vec(&permit_v),
missed_action: self.missed_action,
}
}
}

pub struct AclRegexSetRule<Action = AclAction> {
set_map: FxHashMap<Action, RegexSet>,
missed_action: Action,
pub struct AclRegexSetRule {
forbid_log: Option<RegexSet>,
forbid: Option<RegexSet>,
permit_log: Option<RegexSet>,
permit: Option<RegexSet>,
missed_action: AclAction,
}

impl<Action: ActionContract> AclRegexSetRule<Action> {
pub fn check(&self, text: &str) -> (bool, Action) {
for (action, set) in &self.set_map {
if set.is_match(text) {
return (true, *action);
impl AclRegexSetRule {
pub fn check(&self, text: &str) -> (bool, AclAction) {
if let Some(rs) = &self.forbid_log {
if rs.is_match(text) {
return (true, AclAction::ForbidAndLog);
}
}

if let Some(rs) = &self.forbid {
if rs.is_match(text) {
return (true, AclAction::Forbid);
}
}

if let Some(rs) = &self.permit_log {
if rs.is_match(text) {
return (true, AclAction::PermitAndLog);
}
}

if let Some(rs) = &self.permit {
if rs.is_match(text) {
return (true, AclAction::Permit);
}
}

(false, self.missed_action)
}
}
Expand Down
57 changes: 17 additions & 40 deletions lib/g3-types/src/acl_set/dst_host.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,43 +16,20 @@

use crate::acl::{
AclAction, AclChildDomainRule, AclChildDomainRuleBuilder, AclExactHostRule, AclNetworkRule,
AclNetworkRuleBuilder, AclRegexSetRule, AclRegexSetRuleBuilder, ActionContract,
AclNetworkRuleBuilder, AclRegexSetRule, AclRegexSetRuleBuilder,
};
use crate::net::Host;

#[derive(Clone, Debug, Eq, PartialEq)]
pub struct AclDstHostRuleSetBuilder<Action = AclAction> {
pub exact: Option<AclExactHostRule<Action>>,
pub child: Option<AclChildDomainRuleBuilder<Action>>,
pub regex: Option<AclRegexSetRuleBuilder<Action>>,
pub subnet: Option<AclNetworkRuleBuilder<Action>>,
#[derive(Clone, Debug, Default, Eq, PartialEq)]
pub struct AclDstHostRuleSetBuilder {
pub exact: Option<AclExactHostRule>,
pub child: Option<AclChildDomainRuleBuilder>,
pub regex: Option<AclRegexSetRuleBuilder>,
pub subnet: Option<AclNetworkRuleBuilder>,
}

impl<Action> Default for AclDstHostRuleSetBuilder<Action> {
fn default() -> Self {
Self {
exact: None,
child: None,
regex: None,
subnet: None,
}
}
}

impl<Action: ActionContract> AclDstHostRuleSetBuilder<Action> {
pub fn build_with_missed_action(&self, missed_action: Action) -> AclDstHostRuleSet<Action> {
AclDstHostRuleSet {
exact: self.exact.as_ref().cloned(),
child: self.child.as_ref().map(|builder| builder.build()),
regex: self.regex.as_ref().map(|builder| builder.build()),
subnet: self.subnet.as_ref().map(|builder| builder.build()),
missed_action,
}
}
}

impl AclDstHostRuleSetBuilder<AclAction> {
pub fn build(&self) -> AclDstHostRuleSet<AclAction> {
impl AclDstHostRuleSetBuilder {
pub fn build(&self) -> AclDstHostRuleSet {
let mut missed_action = AclAction::Permit;

let exact_rule = self.exact.as_ref().map(|rule| {
Expand Down Expand Up @@ -85,16 +62,16 @@ impl AclDstHostRuleSetBuilder<AclAction> {
}
}

pub struct AclDstHostRuleSet<Action: ActionContract = AclAction> {
exact: Option<AclExactHostRule<Action>>,
child: Option<AclChildDomainRule<Action>>,
regex: Option<AclRegexSetRule<Action>>,
subnet: Option<AclNetworkRule<Action>>,
missed_action: Action,
pub struct AclDstHostRuleSet {
exact: Option<AclExactHostRule>,
child: Option<AclChildDomainRule>,
regex: Option<AclRegexSetRule>,
subnet: Option<AclNetworkRule>,
missed_action: AclAction,
}

impl<Action: ActionContract> AclDstHostRuleSet<Action> {
pub fn check(&self, upstream: &Host) -> (bool, Action) {
impl AclDstHostRuleSet {
pub fn check(&self, upstream: &Host) -> (bool, AclAction) {
match upstream {
Host::Ip(ip) => {
if let Some(rule) = &self.exact {
Expand Down
6 changes: 3 additions & 3 deletions lib/g3-yaml/src/value/dpi/policy/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -79,20 +79,20 @@ pub fn as_protocol_inspect_policy_builder(
"exact_match" | "exact" => {
let exact_rule = exact_host::as_exact_host_rule(v)
.context(format!("invalid exact host inspect rule value for key {k}"))?;
builder.rule_set.exact = Some(exact_rule);
builder.exact = Some(exact_rule);
Ok(())
}
"child_match" | "child" => {
let child_builder = child_domain::as_child_domain_rule_builder(v).context(
format!("invalid child domain inspect rule value for key {k}"),
)?;
builder.rule_set.child = Some(child_builder);
builder.child = Some(child_builder);
Ok(())
}
"subnet_match" | "subnet" => {
let subnet_builder = network::as_dst_subnet_rule_builder(v)
.context(format!("invalid subnet inspect rule value for key {k}"))?;
builder.rule_set.subnet = Some(subnet_builder);
builder.subnet = Some(subnet_builder);
Ok(())
}
_ => Err(anyhow!("invalid key {k}")),
Expand Down

0 comments on commit 25fb869

Please sign in to comment.