feat: config

This commit is contained in:
Patrick 2025-01-01 19:14:45 +01:00
parent 8545e22327
commit 92ac9346cc
Signed by: patrick
GPG key ID: 451F95EFB8BECD0F
4 changed files with 222 additions and 23 deletions

180
Cargo.lock generated
View file

@ -26,6 +26,55 @@ dependencies = [
"memchr", "memchr",
] ]
[[package]]
name = "anstream"
version = "0.6.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8acc5369981196006228e28809f761875c0327210a891e941f4c683b3a99529b"
dependencies = [
"anstyle",
"anstyle-parse",
"anstyle-query",
"anstyle-wincon",
"colorchoice",
"is_terminal_polyfill",
"utf8parse",
]
[[package]]
name = "anstyle"
version = "1.0.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "55cc3b69f167a1ef2e161439aa98aed94e6028e5f9a59be9a6ffb47aef1651f9"
[[package]]
name = "anstyle-parse"
version = "0.2.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3b2d16507662817a6a20a9ea92df6652ee4f94f914589377d69f3b21bc5798a9"
dependencies = [
"utf8parse",
]
[[package]]
name = "anstyle-query"
version = "1.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "79947af37f4177cfead1110013d678905c37501914fba0efea834c3fe9a8d60c"
dependencies = [
"windows-sys 0.59.0",
]
[[package]]
name = "anstyle-wincon"
version = "3.0.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2109dbce0e72be3ec00bed26e6a7479ca384ad226efdd66db8fa2e3a38c83125"
dependencies = [
"anstyle",
"windows-sys 0.59.0",
]
[[package]] [[package]]
name = "autocfg" name = "autocfg"
version = "1.4.0" version = "1.4.0"
@ -74,6 +123,46 @@ version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "clap"
version = "4.5.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3135e7ec2ef7b10c6ed8950f0f792ed96ee093fa088608f1c76e569722700c84"
dependencies = [
"clap_builder",
"clap_derive",
]
[[package]]
name = "clap_builder"
version = "4.5.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "30582fc632330df2bd26877bde0c1f4470d57c582bbc070376afcd04d8cb4838"
dependencies = [
"anstream",
"anstyle",
"clap_lex",
"strsim",
]
[[package]]
name = "clap_derive"
version = "4.5.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4ac6a0c7b1a9e9a5186361f67dfa1b88213572f427fb9ab038efb2bd8c582dab"
dependencies = [
"heck",
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "clap_lex"
version = "0.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f46ad14479a25103f283c0f10005961cf086d8dc42205bb44c46ac563475dca6"
[[package]] [[package]]
name = "color-eyre" name = "color-eyre"
version = "0.6.3" version = "0.6.3"
@ -101,6 +190,12 @@ dependencies = [
"tracing-error", "tracing-error",
] ]
[[package]]
name = "colorchoice"
version = "1.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990"
[[package]] [[package]]
name = "eyre" name = "eyre"
version = "0.6.12" version = "0.6.12"
@ -123,6 +218,12 @@ version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b"
[[package]]
name = "heck"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
[[package]] [[package]]
name = "indenter" name = "indenter"
version = "0.3.3" version = "0.3.3"
@ -138,6 +239,18 @@ dependencies = [
"serde", "serde",
] ]
[[package]]
name = "is_terminal_polyfill"
version = "1.70.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf"
[[package]]
name = "itoa"
version = "1.0.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d75a2a4b1b190afb6f5425f10f6a8f959d2ea0b9c2b1d79553551850539e4674"
[[package]] [[package]]
name = "lazy_static" name = "lazy_static"
version = "1.5.0" version = "1.5.0"
@ -183,7 +296,7 @@ checksum = "2886843bf800fba2e3377cff24abf6379b4c4d5c6681eaf9ea5b0d15090450bd"
dependencies = [ dependencies = [
"libc", "libc",
"wasi", "wasi",
"windows-sys", "windows-sys 0.52.0",
] ]
[[package]] [[package]]
@ -393,9 +506,13 @@ checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c"
name = "rust" name = "rust"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"clap",
"color-eyre", "color-eyre",
"pnet", "pnet",
"regex", "regex",
"serde",
"serde_json",
"serde_regex",
"simple-dns", "simple-dns",
"socket2", "socket2",
"tokio", "tokio",
@ -407,6 +524,12 @@ version = "0.1.24"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f"
[[package]]
name = "ryu"
version = "1.0.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f"
[[package]] [[package]]
name = "scopeguard" name = "scopeguard"
version = "1.2.0" version = "1.2.0"
@ -415,24 +538,46 @@ checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
[[package]] [[package]]
name = "serde" name = "serde"
version = "1.0.216" version = "1.0.217"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0b9781016e935a97e8beecf0c933758c97a5520d32930e460142b4cd80c6338e" checksum = "02fc4265df13d6fa1d00ecff087228cc0a2b5f3c0e87e258d8b94a156e984c70"
dependencies = [ dependencies = [
"serde_derive", "serde_derive",
] ]
[[package]] [[package]]
name = "serde_derive" name = "serde_derive"
version = "1.0.216" version = "1.0.217"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "46f859dbbf73865c6627ed570e78961cd3ac92407a2d117204c49232485da55e" checksum = "5a9bf7cf98d04a2b28aead066b7496853d4779c9cc183c440dbac457641e19a0"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn", "syn",
] ]
[[package]]
name = "serde_json"
version = "1.0.134"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d00f4175c42ee48b15416f6193a959ba3a0d67fc699a0db9ad12df9f83991c7d"
dependencies = [
"itoa",
"memchr",
"ryu",
"serde",
]
[[package]]
name = "serde_regex"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a8136f1a4ea815d7eac4101cfd0b16dc0cb5e1fe1b8609dfd728058656b7badf"
dependencies = [
"regex",
"serde",
]
[[package]] [[package]]
name = "sharded-slab" name = "sharded-slab"
version = "0.1.7" version = "0.1.7"
@ -479,9 +624,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c970269d99b64e60ec3bd6ad27270092a5394c4e309314b18ae3fe575695fbe8" checksum = "c970269d99b64e60ec3bd6ad27270092a5394c4e309314b18ae3fe575695fbe8"
dependencies = [ dependencies = [
"libc", "libc",
"windows-sys", "windows-sys 0.52.0",
] ]
[[package]]
name = "strsim"
version = "0.11.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f"
[[package]] [[package]]
name = "syn" name = "syn"
version = "2.0.91" version = "2.0.91"
@ -518,7 +669,7 @@ dependencies = [
"signal-hook-registry", "signal-hook-registry",
"socket2", "socket2",
"tokio-macros", "tokio-macros",
"windows-sys", "windows-sys 0.52.0",
] ]
[[package]] [[package]]
@ -579,6 +730,12 @@ version = "1.0.14"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83" checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83"
[[package]]
name = "utf8parse"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821"
[[package]] [[package]]
name = "valuable" name = "valuable"
version = "0.1.0" version = "0.1.0"
@ -622,6 +779,15 @@ dependencies = [
"windows-targets", "windows-targets",
] ]
[[package]]
name = "windows-sys"
version = "0.59.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b"
dependencies = [
"windows-targets",
]
[[package]] [[package]]
name = "windows-targets" name = "windows-targets"
version = "0.52.6" version = "0.52.6"

View file

@ -4,9 +4,13 @@ version = "0.1.0"
edition = "2021" edition = "2021"
[dependencies] [dependencies]
clap = { version = "4.5.23", features = ["derive"] }
color-eyre = "0.6.3" color-eyre = "0.6.3"
pnet = "0.35.0" pnet = "0.35.0"
regex = "1.11.1" regex = "1.11.1"
serde = { version = "1.0.217", features = ["derive"] }
serde_json = "1.0.134"
serde_regex = "1.1.0"
simple-dns = "0.9.1" simple-dns = "0.9.1"
socket2 = { version = "0.5.8", features = ["all"] } socket2 = { version = "0.5.8", features = ["all"] }
tokio = { version = "1.42.0", features = ["full"] } tokio = { version = "1.42.0", features = ["full"] }

11
example.json Normal file
View file

@ -0,0 +1,11 @@
{
"interfaces": "lan*",
"rules": [
{
"from": "wan",
"to": "lan",
"allow_questions": "printer",
"allow_answers": ".*"
}
]
}

View file

@ -1,10 +1,16 @@
const ADDR: Ipv4Addr = Ipv4Addr::new(224, 0, 0, 251); const ADDR: Ipv4Addr = Ipv4Addr::new(224, 0, 0, 251);
use clap::{command, Parser};
use color_eyre::{eyre::bail, Result}; use color_eyre::{eyre::bail, Result};
use pnet::datalink::{interfaces, NetworkInterface}; use pnet::datalink::{interfaces, NetworkInterface};
use pnet::ipnetwork::IpNetwork::{V4, V6}; use pnet::ipnetwork::IpNetwork::{V4, V6};
use regex::Regex; use regex::Regex;
use serde::{Deserialize, Deserializer};
use serde_json::from_reader;
use simple_dns::Packet; use simple_dns::Packet;
use socket2::{Domain, Protocol, Socket, Type}; use socket2::{Domain, Protocol, Socket, Type};
use std::borrow::Cow;
use std::fs::File;
use std::io::BufReader;
use std::{ use std::{
collections::HashSet, collections::HashSet,
net::{Ipv4Addr, SocketAddr, SocketAddrV4}, net::{Ipv4Addr, SocketAddr, SocketAddrV4},
@ -33,10 +39,14 @@ fn get_answers(packet: &Packet) -> HashSet<String> {
packet.answers.iter().map(|x| x.name.to_string()).collect() packet.answers.iter().map(|x| x.name.to_string()).collect()
} }
#[derive(Deserialize)]
struct Rule { struct Rule {
#[serde(with = "serde_regex")]
from: Regex, from: Regex,
to: String, to: String,
#[serde(with = "serde_regex")]
allow_questions: Regex, allow_questions: Regex,
#[serde(with = "serde_regex")]
allow_answers: Regex, allow_answers: Regex,
} }
@ -45,22 +55,27 @@ struct Iface {
socket: socket2::Socket, socket: socket2::Socket,
} }
#[derive(Parser)]
#[command(version, about)]
struct Cli {
/// Path to the config file.
#[arg(short, long)]
config: String,
}
#[derive(Deserialize)]
struct Config {
#[serde(with = "serde_regex")]
interfaces: Regex,
rules: Vec<Rule>,
}
#[tokio::main] #[tokio::main]
async fn main() -> Result<()> { async fn main() -> Result<()> {
let mut rules = Vec::new(); let cli = Cli::parse();
rules.push(Rule { let file = File::open(cli.config)?;
from: Regex::new("lan-home")?, let reader = BufReader::new(file);
to: "lan-services".to_string(), let config: Config = from_reader(reader)?;
allow_answers: Regex::new(".*")?,
allow_questions: Regex::new(".*")?,
});
rules.push(Rule {
from: Regex::new("lan-services")?,
to: "lan-home".to_string(),
allow_answers: Regex::new(".*")?,
allow_questions: Regex::new(".*")?,
});
let iface_reg = Regex::new(r"^lan.*$")?;
let socket = Socket::new(Domain::IPV4, Type::DGRAM, Some(Protocol::UDP))?; let socket = Socket::new(Domain::IPV4, Type::DGRAM, Some(Protocol::UDP))?;
socket.set_reuse_address(true)?; socket.set_reuse_address(true)?;
@ -74,7 +89,10 @@ async fn main() -> Result<()> {
let interfaces = interfaces let interfaces = interfaces
.iter() .iter()
.filter(|x| { .filter(|x| {
x.is_up() && !x.is_loopback() && !x.ips.is_empty() && iface_reg.is_match(&x.name) x.is_up()
&& !x.is_loopback()
&& !x.ips.is_empty()
&& config.interfaces.is_match(&x.name)
}) })
.map(|x| -> Result<Iface> { .map(|x| -> Result<Iface> {
let socket = Socket::new(Domain::IPV4, Type::DGRAM, Some(Protocol::UDP))?; let socket = Socket::new(Domain::IPV4, Type::DGRAM, Some(Protocol::UDP))?;
@ -120,7 +138,7 @@ async fn main() -> Result<()> {
iface, from, questions, answers iface, from, questions, answers
); );
let mut out = HashSet::new(); let mut out = HashSet::new();
for r in &rules { for r in &config.rules {
if r.from.is_match(&iface) if r.from.is_match(&iface)
&& (questions.iter().any(|x| r.allow_questions.is_match(x)) && (questions.iter().any(|x| r.allow_questions.is_match(x))
|| answers.iter().any(|x| r.allow_answers.is_match(x))) || answers.iter().any(|x| r.allow_answers.is_match(x)))