mod sandbox;
mod scenario;
use microsandbox::{NetworkPolicy, Sandbox};
use microsandbox_network::builder::NetworkBuilder;
use test_utils::msb_test;
use crate::sandbox::{deny_resolver, setup_sandbox};
use crate::scenario::{Expect, assert_scenario, dig};
const BLOCKED_EXACT: &str = "blocked.example.com";
const BLOCKED_SUFFIX: &str = ".blocked.test";
const DENIED_RESOLVER: &str = "8.8.8.8";
const GUEST_TLS_CA: &str = "+tls-ca=/.msb/tls/ca.pem";
#[msb_test]
async fn dns_matrix_plain() {
let name = "net-dns-matrix-plain";
let deny_policy = deny_resolver(DENIED_RESOLVER).expect("policy");
let blocked_suffix = format!("test{BLOCKED_SUFFIX}");
let denied = format!("@{DENIED_RESOLVER}");
let configure = |n| with_policy_and_block_list(n, deny_policy.clone());
let (sb, _) = setup_sandbox(name, configure).await.expect("setup");
#[rustfmt::skip]
let scenarios: Vec<(&str, String, Expect)> = vec![
("udp/53 gateway: allowed", dig("example.com", &[]), Expect::Resolves),
("udp/53 gateway: blocked exact", dig(BLOCKED_EXACT, &[]), Expect::Refused),
("udp/53 gateway: blocked suffix", dig(&blocked_suffix, &[]), Expect::Refused),
("udp/53 @1.1.1.1: allowed", dig("example.com", &["@1.1.1.1"]), Expect::Resolves),
("udp/53 @1.1.1.1: blocked exact", dig(BLOCKED_EXACT, &["@1.1.1.1"]), Expect::Refused),
("udp/53 @8.8.8.8 (denied)", dig("example.com", &[&denied]), Expect::Refused),
("tcp/53 gateway: allowed", dig("example.com", &["+tcp"]), Expect::Resolves),
("tcp/53 gateway: blocked exact", dig(BLOCKED_EXACT, &["+tcp"]), Expect::Refused),
("tcp/53 gateway: blocked suffix", dig(&blocked_suffix, &["+tcp"]), Expect::Refused),
("tcp/53 @1.1.1.1: allowed", dig("example.com", &["+tcp", "@1.1.1.1"]), Expect::Resolves),
("tcp/53 @1.1.1.1: blocked exact", dig(BLOCKED_EXACT, &["+tcp", "@1.1.1.1"]), Expect::Refused),
("tcp/53 @8.8.8.8 (denied)", dig("example.com", &["+tcp", &denied]), Expect::Refused),
("dot/853 @1.1.1.1 without MITM", dig("example.com", &["+tls", "@1.1.1.1"]), Expect::NoAnswer),
];
for (scenario, cmd, want) in &scenarios {
assert_scenario(&sb, scenario, cmd, *want).await;
}
sb.stop_and_wait().await.expect("stop");
let _ = Sandbox::remove(name).await;
}
#[msb_test]
async fn dns_matrix_dot() {
let name = "net-dns-matrix-dot";
let deny_policy = deny_resolver(DENIED_RESOLVER).expect("policy");
let blocked_suffix = format!("test{BLOCKED_SUFFIX}");
let denied = format!("@{DENIED_RESOLVER}");
let configure = |n| with_policy_and_block_list(n, deny_policy.clone()).tls(|t| t);
let (sb, gateway_ip) = setup_sandbox(name, configure).await.expect("setup");
let ca = GUEST_TLS_CA;
let gateway = format!("@{gateway_ip}");
let gateway_hostname = format!("+tls-hostname={gateway_ip}");
#[rustfmt::skip]
let scenarios: Vec<(&str, String, Expect)> = vec![
("dot/853 @<gateway>: allowed", dig("example.com", &["+tls", ca, &gateway_hostname, &gateway]), Expect::Resolves),
("dot/853 @<gateway>: blocked exact", dig(BLOCKED_EXACT, &["+tls", ca, &gateway_hostname, &gateway]), Expect::Refused),
("dot/853 @<gateway>: blocked suffix", dig(&blocked_suffix, &["+tls", ca, &gateway_hostname, &gateway]), Expect::Refused),
("dot/853 @1.1.1.1: allowed", dig("example.com", &["+tls", ca, "+tls-hostname=1.1.1.1", "@1.1.1.1"]), Expect::Resolves),
("dot/853 @1.1.1.1: blocked exact", dig(BLOCKED_EXACT, &["+tls", ca, "+tls-hostname=1.1.1.1", "@1.1.1.1"]), Expect::Refused),
("dot/853 @8.8.8.8 (denied)", dig("example.com", &["+tls", ca, "+tls-hostname=8.8.8.8", &denied]), Expect::Refused),
];
for (scenario, cmd, want) in &scenarios {
assert_scenario(&sb, scenario, cmd, *want).await;
}
sb.stop_and_wait().await.expect("stop");
let _ = Sandbox::remove(name).await;
}
fn with_policy_and_block_list(n: NetworkBuilder, policy: NetworkPolicy) -> NetworkBuilder {
let policy = policy
.deny_domain(BLOCKED_EXACT)
.expect("BLOCKED_EXACT parses")
.deny_domain_suffix(BLOCKED_SUFFIX)
.expect("BLOCKED_SUFFIX parses");
n.policy(policy)
}