Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions firewall.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
{
"timeout": 1000,
"default_policy": "allow",
"cache": true,
"expressions": [
{
"policy": "deny",
Expand Down
2 changes: 1 addition & 1 deletion libappguard/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion libappguard/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "nullnet-libappguard"
version = "0.1.10"
version = "0.1.11"
edition = "2024"
authors = ["Giuliano Bellini <gyulyvgc99@gmail.com>", "Anton Liashkevich <anton.liashkevich.eng@gmail.com>"]
description = "An application-level firewall designed to secure and control network traffic"
Expand Down
2 changes: 2 additions & 0 deletions libappguard/src/proto/appguard_commands.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,8 @@ pub struct FirewallDefaults {
pub timeout: u32,
#[prost(enumeration = "FirewallPolicy", tag = "2")]
pub policy: i32,
#[prost(bool, tag = "3")]
pub cache: bool,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)]
#[repr(i32)]
Expand Down
1 change: 1 addition & 0 deletions proto/commands.proto
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ message ServerMessage {
message FirewallDefaults {
uint32 timeout = 1;
FirewallPolicy policy = 2;
bool cache = 3;
}

enum FirewallPolicy {
Expand Down
1 change: 1 addition & 0 deletions src/app_guard_impl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -427,6 +427,7 @@ impl AppGuardImpl {
Ok(FirewallDefaults {
timeout: fw.timeout,
policy: fw.default_policy.into(),
cache: fw.cache,
})
}
}
Expand Down
4 changes: 2 additions & 2 deletions src/db/datastore_wrapper.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1328,10 +1328,10 @@ mod tests {

#[test]
fn test_internal_firewall_parse_response_data() {
let data = r#"[{"app_id": "app1", "firewall": "{\"timeout\" : 1000, \"default_policy\": \"allow\", \"expressions\": []}"}, {"app_id": "app2", "firewall": "{\"timeout\" : 2000, \"default_policy\": \"deny\", \"expressions\": [{\"policy\": \"deny\", \"postfix_tokens\": [{\"type\": \"predicate\", \"condition\": \"equal\", \"protocol\": [\"HTTPS\"]}]}]}"}]"#;
let data = r#"[{"app_id": "app1", "firewall": "{\"timeout\" : 1000, \"default_policy\": \"allow\", \"cache\" : true, \"expressions\": []}"}, {"app_id": "app2", "firewall": "{\"timeout\" : 2000, \"default_policy\": \"deny\", \"cache\" : false, \"expressions\": [{\"policy\": \"deny\", \"postfix_tokens\": [{\"type\": \"predicate\", \"condition\": \"equal\", \"protocol\": [\"HTTPS\"]}]}]}"}]"#;
let result = DatastoreWrapper::internal_firewall_parse_response_data(data).unwrap();
assert_eq!(result.len(), 2);
assert_eq!(*result.get("app1").unwrap(), Firewall::default());
assert_eq!(*result.get("app2").unwrap(), Firewall::from_postfix(r#"{"timeout" : 2000, "default_policy": "deny", "expressions": [{"policy": "deny", "postfix_tokens": [{"type": "predicate", "condition": "equal", "protocol": ["HTTPS"]}]}]}"#).unwrap());
assert_eq!(*result.get("app2").unwrap(), Firewall::from_postfix(r#"{"timeout" : 2000, "default_policy": "deny", "cache" : false, "expressions": [{"policy": "deny", "postfix_tokens": [{"type": "predicate", "condition": "equal", "protocol": ["HTTPS"]}]}]}"#).unwrap());
}
}
5 changes: 4 additions & 1 deletion src/firewall/firewall.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ use nullnet_liberror::{location, Error, ErrorHandler, Location};
pub struct Firewall {
pub(crate) timeout: u32,
pub(crate) default_policy: FirewallPolicy,
pub(crate) cache: bool,
pub(super) expressions: Vec<FirewallExpression>,
}

Expand Down Expand Up @@ -68,6 +69,7 @@ impl Default for Firewall {
Self {
timeout: 1000, // default timeout in milliseconds
default_policy: FirewallPolicy::Allow,
cache: true,
expressions: Vec::new(),
}
}
Expand Down Expand Up @@ -110,6 +112,7 @@ mod tests {
std::sync::LazyLock::new(|| Firewall {
timeout: 1000,
default_policy: FirewallPolicy::Allow,
cache: true,
expressions: Vec::from([
FirewallExpression {
policy: FirewallPolicy::Deny,
Expand Down Expand Up @@ -228,7 +231,7 @@ mod tests {
]),
});

const SERIALIZED_SAMPLE_FIREWALL: &str = r#"{"timeout":1000,"default_policy":"allow","expressions":[{"policy":"deny","postfix_tokens":[{"type":"predicate","condition":"equal","protocol":["HTTP","HTTPS"],"direction":"in"},{"type":"predicate","condition":"contains","http_request_url":[".php"]},{"type":"operator","value":"or"},{"type":"predicate","condition":"equal","country":["US"]},{"type":"operator","value":"and"}]},{"policy":"allow","postfix_tokens":[{"type":"predicate","condition":"contains","http_request_body":["Hello"]},{"type":"predicate","condition":"greater_equal","http_request_header":{"From":["foo@bar.com","bar@foo.com","foo@baz.com"]}},{"type":"operator","value":"or"},{"type":"predicate","condition":"equal","http_request_rate_limit":{"limit":5,"period":30,"urls":["/account","/some/other/path"]}},{"type":"operator","value":"or"}]},{"policy":"deny","postfix_tokens":[{"type":"predicate","condition":"lower_than","http_response_code":[205,206]},{"type":"predicate","condition":"not_starts_with","http_request_query":{"Name":["giuliano","giacomo"]}},{"type":"operator","value":"or"},{"type":"predicate","condition":"ends_with","http_response_size":[100,200,300]},{"type":"operator","value":"or"},{"type":"predicate","condition":"contains","source_ip":["alias_name"]},{"type":"operator","value":"or"}]}]}"#;
const SERIALIZED_SAMPLE_FIREWALL: &str = r#"{"timeout":1000,"default_policy":"allow","cache":true,"expressions":[{"policy":"deny","postfix_tokens":[{"type":"predicate","condition":"equal","protocol":["HTTP","HTTPS"],"direction":"in"},{"type":"predicate","condition":"contains","http_request_url":[".php"]},{"type":"operator","value":"or"},{"type":"predicate","condition":"equal","country":["US"]},{"type":"operator","value":"and"}]},{"policy":"allow","postfix_tokens":[{"type":"predicate","condition":"contains","http_request_body":["Hello"]},{"type":"predicate","condition":"greater_equal","http_request_header":{"From":["foo@bar.com","bar@foo.com","foo@baz.com"]}},{"type":"operator","value":"or"},{"type":"predicate","condition":"equal","http_request_rate_limit":{"limit":5,"period":30,"urls":["/account","/some/other/path"]}},{"type":"operator","value":"or"}]},{"policy":"deny","postfix_tokens":[{"type":"predicate","condition":"lower_than","http_response_code":[205,206]},{"type":"predicate","condition":"not_starts_with","http_request_query":{"Name":["giuliano","giacomo"]}},{"type":"operator","value":"or"},{"type":"predicate","condition":"ends_with","http_response_size":[100,200,300]},{"type":"operator","value":"or"},{"type":"predicate","condition":"contains","source_ip":["alias_name"]},{"type":"operator","value":"or"}]}]}"#;

#[test]
fn test_firewall_load_from_infix_json() {
Expand Down
5 changes: 4 additions & 1 deletion src/firewall/infix_firewall.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ use crate::proto::appguard_commands::FirewallPolicy;
pub struct InfixFirewall {
timeout: u32,
default_policy: FirewallPolicy,
cache: bool,
expressions: Vec<InfixFirewallExpression>,
}

Expand All @@ -18,7 +19,8 @@ impl InfixFirewall {
let mut firewall = Firewall {
timeout: self.timeout,
default_policy: self.default_policy,
..Firewall::default()
cache: self.cache,
expressions: Vec::new(),
};
for expr in self.expressions {
firewall.expressions.push(FirewallExpression {
Expand All @@ -41,6 +43,7 @@ impl Default for InfixFirewall {
Self {
timeout: 1000, // default timeout in milliseconds
default_policy: FirewallPolicy::Allow,
cache: true,
expressions: Vec::new(),
}
}
Expand Down
2 changes: 2 additions & 0 deletions src/http_proxy/api/update_client_firewall.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ pub async fn update_client_firewall(
log::info!("Updating firewall for '{device_id}': {firewall:?}",);
let default_policy = firewall.default_policy;
let timeout = firewall.timeout;
let cache = firewall.cache;

if deactivate_old_firewalls(&context, device_id, &jwt)
.await
Expand Down Expand Up @@ -84,6 +85,7 @@ pub async fn update_client_firewall(
let defaults = FirewallDefaults {
timeout,
policy: default_policy.into(),
cache,
};

let Some(instances) = context
Expand Down
2 changes: 2 additions & 0 deletions src/proto/appguard_commands.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,8 @@ pub struct FirewallDefaults {
pub timeout: u32,
#[prost(enumeration = "FirewallPolicy", tag = "2")]
pub policy: i32,
#[prost(bool, tag = "3")]
pub cache: bool,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)]
#[repr(i32)]
Expand Down
2 changes: 1 addition & 1 deletion test_material/firewall/firewall.json
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{"timeout": 1000, "default_policy": "allow", "expressions": [{"policy": "deny", "infix_tokens": [{"type": "parenthesis", "value": "open"}, {"type": "predicate", "condition": "equal", "protocol": ["HTTP", "HTTPS"], "direction": "in"}, {"type": "operator", "value": "or"}, {"type": "predicate", "condition": "contains", "http_request_url": [".php"]}, {"type": "parenthesis", "value": "close"}, {"type": "operator", "value": "and"}, {"type": "predicate", "condition": "equal", "country": ["US"]}]}, {"policy": "allow", "infix_tokens": [{"type": "predicate", "condition": "contains", "smtp_request_body": ["Hello"]}, {"type": "operator", "value": "or"}, {"type": "predicate", "condition": "greater_equal", "smtp_request_header": {"From": ["foo@bar.com", "bar@foo.com", "foo@baz.com"]}}]}, {"policy": "deny", "infix_tokens": [{"type": "predicate", "condition": "lower_than", "smtp_response_code": [205, 206]}, {"type": "operator", "value": "or"}, {"type": "predicate", "condition": "not_starts_with", "http_request_query": {"Name": ["giuliano", "giacomo"]}}, {"type": "operator", "value": "or"}, {"type": "predicate", "condition": "ends_with", "http_response_size": [100, 200, 300]}]}]}
{"timeout": 1000, "default_policy": "allow", "cache": true, "expressions": [{"policy": "deny", "infix_tokens": [{"type": "parenthesis", "value": "open"}, {"type": "predicate", "condition": "equal", "protocol": ["HTTP", "HTTPS"], "direction": "in"}, {"type": "operator", "value": "or"}, {"type": "predicate", "condition": "contains", "http_request_url": [".php"]}, {"type": "parenthesis", "value": "close"}, {"type": "operator", "value": "and"}, {"type": "predicate", "condition": "equal", "country": ["US"]}]}, {"policy": "allow", "infix_tokens": [{"type": "predicate", "condition": "contains", "smtp_request_body": ["Hello"]}, {"type": "operator", "value": "or"}, {"type": "predicate", "condition": "greater_equal", "smtp_request_header": {"From": ["foo@bar.com", "bar@foo.com", "foo@baz.com"]}}]}, {"policy": "deny", "infix_tokens": [{"type": "predicate", "condition": "lower_than", "smtp_response_code": [205, 206]}, {"type": "operator", "value": "or"}, {"type": "predicate", "condition": "not_starts_with", "http_request_query": {"Name": ["giuliano", "giacomo"]}}, {"type": "operator", "value": "or"}, {"type": "predicate", "condition": "ends_with", "http_response_size": [100, 200, 300]}]}]}
1 change: 1 addition & 0 deletions test_material/firewall_test_1.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
{
"timeout": 1000,
"default_policy": "allow",
"cache": true,
"expressions": [
{
"policy": "deny",
Expand Down
1 change: 1 addition & 0 deletions test_material/firewall_test_2.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
{
"timeout": 1000,
"default_policy": "deny",
"cache": true,
"expressions": [
{
"policy": "allow",
Expand Down