aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordarkgallium <florian+git@aloneinthedark.xyz>2020-05-22 01:12:53 +0200
committerdarkgallium <florian+git@aloneinthedark.xyz>2020-05-24 18:09:22 +0200
commit1a9199011d6f879ec07051db2164713e17e81b2f (patch)
treec01d7ba4974296cca7e63b5efd10432470d6b5c3
parent5dd4544360906de246de9e33abbfd741681d2fea (diff)
downloaddiplonat-1a9199011d6f879ec07051db2164713e17e81b2f.tar.gz
diplonat-1a9199011d6f879ec07051db2164713e17e81b2f.zip
first basic support for adding nft rules
-rw-r--r--Cargo.lock126
-rw-r--r--Cargo.toml3
-rw-r--r--src/fw.rs101
3 files changed, 228 insertions, 2 deletions
diff --git a/Cargo.lock b/Cargo.lock
index b51fc45..e86e28a 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -127,7 +127,10 @@ dependencies = [
"anyhow",
"futures",
"igd",
+ "libc",
"log",
+ "mnl",
+ "nftnl",
"pretty_env_logger",
"reqwest",
"serde",
@@ -165,6 +168,20 @@ dependencies = [
]
[[package]]
+name = "err-derive"
+version = "0.2.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "22deed3a8124cff5fa835713fa105621e43bbdc46690c3a6b68328a012d350d4"
+dependencies = [
+ "proc-macro-error",
+ "proc-macro2",
+ "quote",
+ "rustversion",
+ "syn",
+ "synstructure",
+]
+
+[[package]]
name = "fnv"
version = "1.0.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -548,9 +565,9 @@ dependencies = [
[[package]]
name = "libc"
-version = "0.2.66"
+version = "0.2.70"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d515b1f41455adea1313a4a2ac8a8a477634fbae63cc6100e3aebb207ce61558"
+checksum = "3baa92041a6fec78c687fa0cc2b3fae8884f743d672cf551bed1d6dac6988d0f"
[[package]]
name = "log"
@@ -621,6 +638,27 @@ dependencies = [
]
[[package]]
+name = "mnl"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e6efb50a48dbacd112e7e847b9847fa530ec4a473ba6322a2f82c42ef333e226"
+dependencies = [
+ "libc",
+ "log",
+ "mnl-sys",
+]
+
+[[package]]
+name = "mnl-sys"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5302035599c722b3a5b92a6502ff73c501dc6d100c53b89f0fae0cb932a37122"
+dependencies = [
+ "libc",
+ "pkg-config",
+]
+
+[[package]]
name = "native-tls"
version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -650,6 +688,30 @@ dependencies = [
]
[[package]]
+name = "nftnl"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f3727d1e8c1c9af88857f46539c3030693158a2a7586056b8cab6ded523bf7aa"
+dependencies = [
+ "bitflags",
+ "err-derive",
+ "libc",
+ "log",
+ "nftnl-sys",
+]
+
+[[package]]
+name = "nftnl-sys"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dba134c9b125b7d7c13d813388aaeb2aeeba60fb1eb702799163fb845086ca33"
+dependencies = [
+ "cfg-if",
+ "libc",
+ "pkg-config",
+]
+
+[[package]]
name = "nom"
version = "4.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -765,6 +827,32 @@ dependencies = [
]
[[package]]
+name = "proc-macro-error"
+version = "1.0.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "98e9e4b82e0ef281812565ea4751049f1bdcdfccda7d3f459f2e138a40c08678"
+dependencies = [
+ "proc-macro-error-attr",
+ "proc-macro2",
+ "quote",
+ "syn",
+ "version_check 0.9.1",
+]
+
+[[package]]
+name = "proc-macro-error-attr"
+version = "1.0.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4f5444ead4e9935abd7f27dc51f7e852a0569ac888096d5ec2499470794e2e53"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+ "syn-mid",
+ "version_check 0.9.1",
+]
+
+[[package]]
name = "proc-macro-hack"
version = "0.5.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -953,6 +1041,17 @@ dependencies = [
]
[[package]]
+name = "rustversion"
+version = "1.0.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b3bba175698996010c4f6dce5e7f173b6eb781fce25d2cfc45e27091ce0b79f6"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
name = "ryu"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1072,6 +1171,29 @@ dependencies = [
]
[[package]]
+name = "syn-mid"
+version = "0.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7be3539f6c128a931cf19dcee741c1af532c7fd387baa739c03dd2e96479338a"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "synstructure"
+version = "0.12.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "67656ea1dc1b41b1451851562ea232ec2e5a80242139f7e679ceccfb5d61f545"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+ "unicode-xid",
+]
+
+[[package]]
name = "tempfile"
version = "3.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
diff --git a/Cargo.toml b/Cargo.toml
index ce0fbc3..2376c52 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -17,3 +17,6 @@ serde = { version = "1.0.107", features = ["derive"] }
serde_json = "1.0.53"
serde-lexpr = "0.1.1"
anyhow = "1.0.28"
+nftnl = "0.3.0"
+mnl = "0.2.0"
+libc = "0.2.70"
diff --git a/src/fw.rs b/src/fw.rs
new file mode 100644
index 0000000..aabc420
--- /dev/null
+++ b/src/fw.rs
@@ -0,0 +1,101 @@
+use nftnl::{nft_expr, Batch, Chain, FinalizedBatch, ProtoFamily, Rule, Table};
+use std::{
+ ffi::{self, CString},
+ io,
+};
+use mnl;
+use libc;
+
+const TABLE_NAME: &str = "diplonat";
+const OUT_CHAIN_NAME: &str = "out";
+const IN_CHAIN_NAME: &str = "in";
+
+#[derive(Debug)]
+struct Error(String);
+
+impl From<io::Error> for Error {
+ fn from(error: io::Error) -> Self {
+ Error(error.to_string())
+ }
+}
+
+impl From<ffi::NulError> for Error {
+ fn from(error: ffi::NulError) -> Self {
+ Error(error.to_string())
+ }
+}
+
+fn send_and_process(batch: &FinalizedBatch) -> Result<(), Error> {
+ let socket = mnl::Socket::new(mnl::Bus::Netfilter)?;
+ socket.send_all(batch)?;
+
+ let portid = socket.portid();
+ let mut buffer = vec![0; nftnl::nft_nlmsg_maxsize() as usize];
+
+ while let Some(message) = socket_recv(&socket, &mut buffer[..])? {
+ match mnl::cb_run(message, 2, portid)? {
+ mnl::CbResult::Stop => {
+ break;
+ }
+ mnl::CbResult::Ok => (),
+ }
+ }
+ Ok(())
+}
+
+fn socket_recv<'a>(socket: &mnl::Socket, buf: &'a mut [u8]) -> Result<Option<&'a [u8]>, Error> {
+ let ret = socket.recv(buf)?;
+ if ret > 0 {
+ Ok(Some(&buf[..ret]))
+ } else {
+ Ok(None)
+ }
+}
+
+fn add_port_allowed(port: u16) -> Result<(), Error> {
+ let mut batch = Batch::new();
+
+ // TODO: at the moment, I haven't found a way to properly separate setup part (create table and
+ // chains) and the add rule part because the add rule part needs a reference on the chains.
+ // apparently creating a table and chains that already exist seems to do nothing so it works
+ // doing the following. To be done properly though
+
+ let table = Table::new(&CString::new(TABLE_NAME).unwrap(), ProtoFamily::Inet);
+
+ batch.add(&table, nftnl::MsgType::Add);
+
+ let mut out_chain = Chain::new(&CString::new(OUT_CHAIN_NAME).unwrap(), &table);
+ let mut in_chain = Chain::new(&CString::new(IN_CHAIN_NAME).unwrap(), &table);
+
+ out_chain.set_hook(nftnl::Hook::Out, 0);
+ in_chain.set_hook(nftnl::Hook::In, 0);
+
+ out_chain.set_policy(nftnl::Policy::Accept);
+ in_chain.set_policy(nftnl::Policy::Drop);
+
+ batch.add(&out_chain, nftnl::MsgType::Add);
+ batch.add(&in_chain, nftnl::MsgType::Add);
+
+ let mut _rule = Rule::new(&in_chain);
+
+ _rule.add_expr(&nft_expr!(meta nfproto));
+ _rule.add_expr(&nft_expr!(cmp == libc::NFPROTO_IPV4 as u8));
+
+ _rule.add_expr(&nft_expr!(meta l4proto));
+ _rule.add_expr(&nft_expr!(cmp == libc::IPPROTO_TCP as u8));
+
+ _rule.add_expr(&nftnl::expr::Payload::Transport(
+ nftnl::expr::TransportHeaderField::Tcp(nftnl::expr::TcpHeaderField::Dport),
+ ));
+ _rule.add_expr(&nft_expr!(cmp == port.to_be()));
+
+ _rule.add_expr(&nft_expr!(verdict accept));
+
+ batch.add(&_rule, nftnl::MsgType::Add);
+
+ let finalized_batch = batch.finalize();
+ send_and_process(&finalized_batch)?;
+
+ Ok(())
+
+}