aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/fw.rs131
-rw-r--r--src/main.rs7
2 files changed, 53 insertions, 85 deletions
diff --git a/src/fw.rs b/src/fw.rs
index aabc420..07282af 100644
--- a/src/fw.rs
+++ b/src/fw.rs
@@ -1,101 +1,64 @@
-use nftnl::{nft_expr, Batch, Chain, FinalizedBatch, ProtoFamily, Rule, Table};
-use std::{
- ffi::{self, CString},
- io,
-};
-use mnl;
-use libc;
+use iptables;
+use regex::Regex;
+use std::collections::HashSet;
+
+#[derive(PartialEq,Eq,Debug,Hash)]
+pub struct Port {
+ proto: String,
+ number: u16,
+}
-const TABLE_NAME: &str = "diplonat";
-const OUT_CHAIN_NAME: &str = "out";
-const IN_CHAIN_NAME: &str = "in";
+pub fn setup(ipt: &iptables::IPTables) {
+ ipt.new_chain("filter", "DIPLONAT").unwrap();
+ ipt.insert("filter", "INPUT", "-j DIPLONAT", 1).unwrap();
+}
-#[derive(Debug)]
-struct Error(String);
+pub fn open_ports(ipt: &iptables::IPTables, ports: Vec<Port>) {
-impl From<io::Error> for Error {
- fn from(error: io::Error) -> Self {
- Error(error.to_string())
+ for p in ports {
+ ipt.append("filter", "DIPLONAT", &format!("-p {} --dport {} -j ACCEPT", p.proto, p.number)).unwrap();
}
}
-impl From<ffi::NulError> for Error {
- fn from(error: ffi::NulError) -> Self {
- Error(error.to_string())
- }
-}
+pub fn get_opened_ports(ipt: &iptables::IPTables) -> HashSet<Port> {
+ let mut opened_ports: HashSet<Port> = HashSet::new();
-fn send_and_process(batch: &FinalizedBatch) -> Result<(), Error> {
- let socket = mnl::Socket::new(mnl::Bus::Netfilter)?;
- socket.send_all(batch)?;
+ let list = ipt.list("filter", "DIPLONAT").unwrap();
+ let re = Regex::new(r"\-A.*? \-p (\w+).*\-\-dport (\d+).*?\-j ACCEPT").unwrap();
+ for i in list {
+ let caps = re.captures(&i);
+ match caps {
+ Some(c) => {
+ let raw_proto = c.get(1).unwrap();
+ let raw_port = c.get(2).unwrap();
- let portid = socket.portid();
- let mut buffer = vec![0; nftnl::nft_nlmsg_maxsize() as usize];
+ let proto = String::from(raw_proto.as_str());
+ let number = String::from(raw_port.as_str()).parse::<u16>().unwrap();
- while let Some(message) = socket_recv(&socket, &mut buffer[..])? {
- match mnl::cb_run(message, 2, portid)? {
- mnl::CbResult::Stop => {
- break;
- }
- mnl::CbResult::Ok => (),
+ opened_ports.insert( Port { proto, number } );
+ },
+ _ => {}
}
}
- 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)
- }
+ opened_ports
}
-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));
+pub fn cleanup(ipt: &iptables::IPTables) {
+ ipt.flush_chain("filter", "DIPLONAT").unwrap();
+ ipt.delete("filter", "INPUT", "-j DIPLONAT").unwrap();
+ ipt.delete_chain("filter", "DIPLONAT").unwrap();
+}
- batch.add(&_rule, nftnl::MsgType::Add);
+/*
+fn main() {
+ let ipt = iptables::new(false).unwrap();
+ setup(&ipt);
- let finalized_batch = batch.finalize();
- send_and_process(&finalized_batch)?;
-
- Ok(())
-
+ let mut test: HashSet<Port> = HashSet::new();
+ test.insert(Port { proto: String::from("tcp"), number: 443 });
+ let a = get_opened_ports(&ipt);
+ let l = test.difference(&a).collect::<Vec<&Port>>();
+ println!("{:?}", l);
}
+*/
diff --git a/src/main.rs b/src/main.rs
index a35916a..bf8248d 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -4,7 +4,9 @@ mod consul;
mod consul_actor;
mod igd_actor;
mod diplonat;
+mod fw;
+use iptables;
use log::*;
use diplonat::Diplonat;
@@ -12,7 +14,10 @@ use diplonat::Diplonat;
async fn main() {
pretty_env_logger::init();
info!("Starting Diplonat");
-
+
+ let ipt = iptables::new(false).unwrap();
+ fw::setup(&ipt).expect("iptables setup failed");
+
let mut diplo = Diplonat::new().await.expect("Setup failed");
diplo.listen().await.expect("A runtime error occured");
}