mirror of
https://github.com/cirruslabs/softnet.git
synced 2026-09-30 20:11:16 +02:00
Compare commits
8
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c377206064 | ||
|
|
7623d698ce | ||
|
|
1ccb0ee4b4 | ||
|
|
50b5e2af2d | ||
|
|
c1ddb2afc6 | ||
|
|
401dea6612 | ||
|
|
1dcb0755df | ||
|
|
1706062004 |
Generated
+30
-30
@@ -363,9 +363,9 @@ checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724"
|
||||
|
||||
[[package]]
|
||||
name = "clap"
|
||||
version = "4.5.50"
|
||||
version = "4.5.53"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0c2cfd7bf8a6017ddaa4e32ffe7403d547790db06bd171c1c53926faab501623"
|
||||
checksum = "c9e340e012a1bf4935f5282ed1436d1489548e8f72308207ea5df0e23d2d03f8"
|
||||
dependencies = [
|
||||
"clap_builder",
|
||||
"clap_derive",
|
||||
@@ -373,9 +373,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "clap_builder"
|
||||
version = "4.5.50"
|
||||
version = "4.5.53"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0a4c05b9e80c5ccd3a7ef080ad7b6ba7d6fc00a985b8b157197075677c82c7a0"
|
||||
checksum = "d76b5d13eaa18c901fd2f7fca939fefe3a0727a953561fefdf3b2922b8569d00"
|
||||
dependencies = [
|
||||
"anstream",
|
||||
"anstyle",
|
||||
@@ -1291,9 +1291,9 @@ checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe"
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.177"
|
||||
version = "0.2.178"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2874a2af47a2325c2001a6e6fad9b16a53b802102b528163885171cf92b15976"
|
||||
checksum = "37c93d8daa9d8a012fd8ab92f088405fb202ea0b6ab73ee2482ae66af4f42091"
|
||||
|
||||
[[package]]
|
||||
name = "linux-raw-sys"
|
||||
@@ -1342,9 +1342,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "log"
|
||||
version = "0.4.28"
|
||||
version = "0.4.29"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "34080505efa8e45a4b816c349525ebe327ceaa8559756f0356cba97ef3bf7432"
|
||||
checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897"
|
||||
|
||||
[[package]]
|
||||
name = "mac_address"
|
||||
@@ -2015,9 +2015,9 @@ checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b"
|
||||
|
||||
[[package]]
|
||||
name = "sentry"
|
||||
version = "0.45.0"
|
||||
version = "0.46.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "48b85e25e8a1fc13928885e8bf13abe8a09e15c46993aed05d6405f7755d6e20"
|
||||
checksum = "d9794f69ad475e76c057e326175d3088509649e3aed98473106b9fe94ba59424"
|
||||
dependencies = [
|
||||
"httpdate",
|
||||
"native-tls",
|
||||
@@ -2035,9 +2035,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "sentry-actix"
|
||||
version = "0.45.0"
|
||||
version = "0.46.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cc694e6ffc8d5d7fdb2a33923b0358f6ad41c0b428ced034b349b9e2b08260bc"
|
||||
checksum = "e0fee202934063ace4f1d1d063113b8982293762628e563a2d2fba08fb20b110"
|
||||
dependencies = [
|
||||
"actix-http",
|
||||
"actix-web",
|
||||
@@ -2048,9 +2048,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "sentry-anyhow"
|
||||
version = "0.45.0"
|
||||
version = "0.46.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cfd12302213b0f449a065a68164e30dc02f5a4bc84843c2c5939b2c46b1513e8"
|
||||
checksum = "d1832cd051f3198af8ebc5222da5fd213e49976d758b7defa7accbff3aed1909"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"sentry-backtrace",
|
||||
@@ -2059,9 +2059,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "sentry-backtrace"
|
||||
version = "0.45.0"
|
||||
version = "0.46.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f3253a495ab536f6de1746a58d5d7824b77d75e08e1a4b8ca6fb356839077ae0"
|
||||
checksum = "e81137ad53b8592bd0935459ad74c0376053c40084aa170451e74eeea8dbc6c3"
|
||||
dependencies = [
|
||||
"backtrace",
|
||||
"regex",
|
||||
@@ -2070,9 +2070,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "sentry-contexts"
|
||||
version = "0.45.0"
|
||||
version = "0.46.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "027f81a728836e66b88c07666a10f5ed5a35e2695b04eb7aa0fcbed93f814900"
|
||||
checksum = "cfb403c66cc2651a01b9bacda2e7c22cd51f7e8f56f206aa4310147eb3259282"
|
||||
dependencies = [
|
||||
"hostname",
|
||||
"libc",
|
||||
@@ -2084,9 +2084,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "sentry-core"
|
||||
version = "0.45.0"
|
||||
version = "0.46.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d3b6729c8e71ac968edbe9bf2dd4109c162e552b52bacd2b07e24ede1aba84a5"
|
||||
checksum = "cfc409727ae90765ca8ea76fe6c949d6f159a11d02e130b357fa652ee9efcada"
|
||||
dependencies = [
|
||||
"rand",
|
||||
"sentry-types",
|
||||
@@ -2097,9 +2097,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "sentry-debug-images"
|
||||
version = "0.45.0"
|
||||
version = "0.46.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dc85b59c1dfb19912bfba1af73a592e2e5548cae241a79ecb805afab3333d04c"
|
||||
checksum = "06a2778a222fd90ebb01027c341a72f8e24b0c604c6126504a4fe34e5500e646"
|
||||
dependencies = [
|
||||
"findshlibs",
|
||||
"sentry-core",
|
||||
@@ -2107,9 +2107,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "sentry-panic"
|
||||
version = "0.45.0"
|
||||
version = "0.46.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1ac0471f04f8f97af0c17eeca2c516e23faa1c0271a55bc64371d9ce488c2d40"
|
||||
checksum = "3df79f4e1e72b2a8b75a0ebf49e78709ceb9b3f0b451f13adc92a0361b0aaabe"
|
||||
dependencies = [
|
||||
"sentry-backtrace",
|
||||
"sentry-core",
|
||||
@@ -2117,9 +2117,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "sentry-tracing"
|
||||
version = "0.45.0"
|
||||
version = "0.46.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "428f780866a613142dcc81b7f8551ae4d1c056f4df22b6d7ddd9154a9974eb03"
|
||||
checksum = "ff2046f527fd4b75e0b6ab3bd656c67dce42072f828dc4d03c206d15dca74a93"
|
||||
dependencies = [
|
||||
"bitflags 2.9.4",
|
||||
"sentry-backtrace",
|
||||
@@ -2130,9 +2130,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "sentry-types"
|
||||
version = "0.45.0"
|
||||
version = "0.46.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2c19d1d1967b55659c358886d0f1aa3076488d445f84c7d727d384c675adaec1"
|
||||
checksum = "c7b9b4e4c03a4d3643c18c78b8aa91d2cbee5da047d2fa0ca4bb29bc67e6c55c"
|
||||
dependencies = [
|
||||
"debugid",
|
||||
"hex",
|
||||
@@ -2370,9 +2370,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "system-configuration"
|
||||
version = "0.6.1"
|
||||
version = "0.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3c879d448e9d986b661742763247d3693ed13609438cf3d006f51f5368a5ba6b"
|
||||
checksum = "a13f3d0daba03132c0aa9767f98351b3488edc2c100cda2d2ec2b04f3d8d3c8b"
|
||||
dependencies = [
|
||||
"bitflags 2.9.4",
|
||||
"core-foundation",
|
||||
|
||||
+1
-1
@@ -31,7 +31,7 @@ nix = { version = "0", features = ["signal", "socket"] }
|
||||
prefix-trie = "0"
|
||||
ipnet = "2"
|
||||
oslog = "0.2.0"
|
||||
log = "0.4.28"
|
||||
log = "0.4.29"
|
||||
serial_test = "3"
|
||||
|
||||
[profile.release]
|
||||
|
||||
+101
-12
@@ -1,4 +1,4 @@
|
||||
use anyhow::{Context, anyhow};
|
||||
use anyhow::{Context, Error, anyhow};
|
||||
use clap::Parser;
|
||||
use ipnet::Ipv4Net;
|
||||
use log::LevelFilter;
|
||||
@@ -11,10 +11,12 @@ use softnet::proxy::ExposedPort;
|
||||
use softnet::proxy::Proxy;
|
||||
use std::borrow::Cow;
|
||||
use std::env;
|
||||
use std::net::{Ipv4Addr, SocketAddr, ToSocketAddrs};
|
||||
use std::os::raw::c_int;
|
||||
use std::os::unix::io::RawFd;
|
||||
use std::os::unix::process::CommandExt;
|
||||
use std::process::{Command, ExitCode};
|
||||
use std::str::FromStr;
|
||||
use system_configuration::core_foundation::base::TCFType;
|
||||
use system_configuration::core_foundation::dictionary::CFDictionary;
|
||||
use system_configuration::core_foundation::number::CFNumber;
|
||||
@@ -23,6 +25,67 @@ use system_configuration::preferences::SCPreferences;
|
||||
use system_configuration::sys::preferences::{SCPreferencesCommitChanges, SCPreferencesSetValue};
|
||||
use uzers::{get_current_groupname, get_current_username, get_effective_uid};
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
enum AllowBlockEntry {
|
||||
Net(Ipv4Net),
|
||||
Domain(String),
|
||||
}
|
||||
|
||||
impl FromStr for AllowBlockEntry {
|
||||
type Err = Error;
|
||||
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
let trimmed = s.trim();
|
||||
if trimmed.is_empty() {
|
||||
return Err(anyhow!("empty allow/block entry"));
|
||||
}
|
||||
|
||||
if let Ok(net) = trimmed.parse::<Ipv4Net>() {
|
||||
return Ok(AllowBlockEntry::Net(net));
|
||||
}
|
||||
|
||||
if let Ok(addr) = trimmed.parse::<Ipv4Addr>() {
|
||||
return Ok(AllowBlockEntry::Net(Ipv4Net::from(addr)));
|
||||
}
|
||||
|
||||
Ok(AllowBlockEntry::Domain(trimmed.to_string()))
|
||||
}
|
||||
}
|
||||
|
||||
fn resolve_allow_block_entries(
|
||||
kind: &str,
|
||||
entries: Vec<AllowBlockEntry>,
|
||||
) -> anyhow::Result<Vec<Ipv4Net>> {
|
||||
let mut nets = Vec::new();
|
||||
|
||||
for entry in entries {
|
||||
match entry {
|
||||
AllowBlockEntry::Net(net) => nets.push(net),
|
||||
AllowBlockEntry::Domain(domain) => {
|
||||
// A-record resolution happens here via ToSocketAddrs, then we keep only IPv4s.
|
||||
let resolved: Vec<Ipv4Net> = (domain.as_str(), 0)
|
||||
.to_socket_addrs()
|
||||
.with_context(|| format!("failed to resolve {kind} entry {domain}"))?
|
||||
.filter_map(|addr| match addr {
|
||||
SocketAddr::V4(v4) => Some(Ipv4Net::from(*v4.ip())),
|
||||
SocketAddr::V6(_) => None,
|
||||
})
|
||||
.collect();
|
||||
|
||||
if resolved.is_empty() {
|
||||
return Err(anyhow!(
|
||||
"no IPv4 addresses found for {kind} entry {domain}"
|
||||
));
|
||||
}
|
||||
|
||||
nets.extend(resolved);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(nets)
|
||||
}
|
||||
|
||||
#[derive(Parser, Debug)]
|
||||
struct Args {
|
||||
#[clap(
|
||||
@@ -52,30 +115,32 @@ struct Args {
|
||||
|
||||
#[clap(
|
||||
long,
|
||||
help = "Comma-separated list of CIDRs to allow the traffic to \
|
||||
(e.g. --allow=192.168.0.0/24 may be used to allow a LAN access for a VM). \
|
||||
help = "Comma-separated list of CIDRs, IPs, or domains to allow the traffic to \
|
||||
(e.g. --allow=192.168.0.0/24 or --allow=example.com). Domains are resolved to A records \
|
||||
at startup. \
|
||||
When used with --block, the longest prefix match always wins. \
|
||||
In case an identical prefix is both --allow'ed and --block'ed, \
|
||||
blocking will take precedence. --allow=0.0.0.0/0 is a special case, \
|
||||
it additionally disables bridge isolation (even when --block=0.0.0.0/0 is specified).",
|
||||
value_name = "comma-separated CIDRs",
|
||||
value_name = "comma-separated CIDRs/IPs/domains",
|
||||
use_value_delimiter = true,
|
||||
action = clap::ArgAction::Set
|
||||
)]
|
||||
allow: Vec<Ipv4Net>,
|
||||
allow: Vec<AllowBlockEntry>,
|
||||
|
||||
#[clap(
|
||||
long,
|
||||
help = "Comma-separated list of CIDRs to block the traffic to \
|
||||
help = "Comma-separated list of CIDRs, IPs, or domains to block the traffic to \
|
||||
(e.g. --block=0.0.0.0/0 may be used to establish a default deny policy \
|
||||
that is further relaxed with --allow). When used with --allow, \
|
||||
that is further relaxed with --allow). Domains are resolved to A records at startup. \
|
||||
When used with --allow, \
|
||||
the longest prefix match always wins. In case the same prefix is both \
|
||||
--allow'ed and --block'ed, blocking takes precedence.",
|
||||
value_name = "comma-separated CIDRs",
|
||||
value_name = "comma-separated CIDRs/IPs/domains",
|
||||
use_value_delimiter = true,
|
||||
action = clap::ArgAction::Set
|
||||
)]
|
||||
block: Vec<Ipv4Net>,
|
||||
block: Vec<AllowBlockEntry>,
|
||||
|
||||
#[clap(
|
||||
long,
|
||||
@@ -145,7 +210,7 @@ fn try_main() -> anyhow::Result<()> {
|
||||
// [2]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/kqueue.2.html
|
||||
unsafe { signal(Signal::SIGINT, SigHandler::SigIgn) }?;
|
||||
|
||||
let args: Args = Args::parse();
|
||||
let mut args: Args = Args::parse();
|
||||
|
||||
// No need to run anything, just return
|
||||
// so that the invoker process knows we
|
||||
@@ -188,6 +253,9 @@ fn try_main() -> anyhow::Result<()> {
|
||||
));
|
||||
}
|
||||
|
||||
let allow = resolve_allow_block_entries("allow", std::mem::take(&mut args.allow))?;
|
||||
let block = resolve_allow_block_entries("block", std::mem::take(&mut args.block))?;
|
||||
|
||||
// Set bootpd(8) min/max lease time while still having the root privileges
|
||||
set_bootpd_lease_time(args.bootpd_lease_time);
|
||||
|
||||
@@ -196,8 +264,8 @@ fn try_main() -> anyhow::Result<()> {
|
||||
args.vm_fd as RawFd,
|
||||
args.vm_mac_address,
|
||||
args.vm_net_type,
|
||||
PrefixSet::from_iter(args.allow),
|
||||
PrefixSet::from_iter(args.block),
|
||||
PrefixSet::from_iter(allow),
|
||||
PrefixSet::from_iter(block),
|
||||
args.expose,
|
||||
)
|
||||
.context("failed to initialize proxy")?;
|
||||
@@ -249,3 +317,24 @@ fn set_bootpd_lease_time(lease_time: u32) {
|
||||
SCPreferencesCommitChanges(prefs.as_concrete_TypeRef());
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::{AllowBlockEntry, resolve_allow_block_entries};
|
||||
use ipnet::Ipv4Net;
|
||||
use std::net::Ipv4Addr;
|
||||
|
||||
#[test]
|
||||
fn resolve_domain_to_ipv4_nets_dns_google() {
|
||||
let nets = resolve_allow_block_entries(
|
||||
"allow",
|
||||
vec![AllowBlockEntry::Domain("dns.google".to_string())],
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
assert!(
|
||||
nets.contains(&Ipv4Net::from(Ipv4Addr::new(8, 8, 8, 8)))
|
||||
|| nets.contains(&Ipv4Net::from(Ipv4Addr::new(8, 8, 4, 4)))
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user