diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/fw.rs | 131 | ||||
-rw-r--r-- | src/main.rs | 7 |
2 files changed, 53 insertions, 85 deletions
@@ -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"); } |