zunft/src/main.rs

234 lines
7.6 KiB
Rust

#[allow(unused_imports)]
use lazy_static::lazy_static;
use nfq::{Queue, Verdict};
use pdu::{Gre, GrePdu, Icmp, IcmpPdu, Ip, Ipv4, Ipv4Pdu, Ipv6Pdu, Tcp, TcpPdu, Udp, UdpPdu};
#[allow(unused_imports)]
use regex::bytes::Regex;
fn main() {
let mut queue = Queue::open().expect("Could not open queue!");
queue.bind(0).expect("Could not bind to queue 0!");
loop {
let mut msg = queue.recv().expect("Could not receive message from queue!");
let packet = msg.get_payload();
let verdict = match Ip::new(packet) {
Ok(Ip::Ipv4(ipv4_pdu)) => {
print!("IPv4 -> ");
//print_ipv4(ipv4_pdu);
match ipv4_pdu.inner() {
#[allow(unused_variables)]
Ok(Ipv4::Raw(raw)) => {
print!("RAW");
Verdict::Accept
}
Ok(Ipv4::Tcp(tcp_pdu)) => {
print!("TCP -> ");
//print_tcp(tcp_pdu);
match tcp_pdu.inner() {
Ok(Tcp::Raw(raw)) => {
print!("RAW");
filter_ipv4_tcp_raw(ipv4_pdu, tcp_pdu, raw)
}
Err(e) => panic!("Could not get inner payload of TCP PDU: {}", e),
}
}
Ok(Ipv4::Udp(udp_pdu)) => {
print!("UDP -> ");
//print_udp(udp_pdu);
match udp_pdu.inner() {
#[allow(unused_variables)]
Ok(Udp::Raw(raw)) => {
print!("RAW");
}
Err(e) => panic!("Could not get inner payload of UDP PDU: {}", e),
}
Verdict::Accept
}
Ok(Ipv4::Icmp(icmp_pdu)) => {
print!("ICMP -> ");
//print_icmp(icmp_pdu);
match icmp_pdu.inner() {
#[allow(unused_variables)]
Ok(Icmp::Raw(raw)) => {
print!("RAW");
}
Err(e) => panic!("Could not get inner payload of ICMP PDU: {}", e),
}
Verdict::Accept
}
Ok(Ipv4::Gre(gre_pdu)) => {
print!("GRE -> ");
//print_gre(gre_pdu);
match gre_pdu.inner() {
#[allow(unused_variables)]
Ok(Gre::Raw(raw)) => {
print!("RAW");
}
Ok(_) => print!("Eth/Ipv4/Ipv6"),
Err(e) => panic!("Could not get inner payload of GRE PDU: {}", e),
}
Verdict::Accept
}
Err(e) => panic!("Could not decode inner packet: {}", e),
}
}
#[allow(unused_variables)]
Ok(Ip::Ipv6(ipv6_pdu)) => {
println!("IPv6!");
// TODO same as above
Verdict::Accept
}
Err(e) => panic!("Could not decode IP packet: {}", e),
};
println!();
msg.set_verdict(verdict);
queue
.verdict(msg)
.expect("Could not set verdict for message!");
}
}
#[allow(dead_code)]
fn print_gre(gre_pdu: GrePdu) {
print!(
"GRE {:10} {:3} {:5} {:5} {:5} {:5} {:?} {:?} {:?} {:?} ",
gre_pdu.computed_ihl(),
gre_pdu.version(),
gre_pdu.ethertype(),
gre_pdu.has_checksum(),
gre_pdu.has_key(),
gre_pdu.has_sequence_number(),
gre_pdu.checksum(),
gre_pdu.computed_checksum(),
gre_pdu.key(),
gre_pdu.sequence_number()
);
}
#[allow(dead_code)]
fn print_icmp(icmp_pdu: IcmpPdu) {
print!(
"ICMP {:3} {:3} {:5} {:10}",
icmp_pdu.message_type(),
icmp_pdu.message_code(),
icmp_pdu.checksum(),
//icmp_pdu.computed_checksum(ip: &crate::Ip)
icmp_pdu.computed_data_offset()
);
}
#[allow(dead_code)]
fn print_ipv4(ipv4_pdu: Ipv4Pdu) {
let sa = ipv4_pdu.source_address();
let da = ipv4_pdu.destination_address();
print!(
"IPv4 {} {} {} {:2} {} {:4} {:5} {:5} {:5} {} {} {:3} {:2} {:5} {:5} {:03}:{:03}:{:03}:{:03} {:03}:{:03}:{:03}:{:03} ",
ipv4_pdu.version(),
ipv4_pdu.ihl(),
ipv4_pdu.computed_ihl(),
ipv4_pdu.dscp(),
ipv4_pdu.ecn(),
ipv4_pdu.total_length(),
ipv4_pdu.identification(),
ipv4_pdu.dont_fragment(),
ipv4_pdu.more_fragments(),
ipv4_pdu.fragment_offset(),
ipv4_pdu.computed_fragment_offset(),
ipv4_pdu.ttl(),
ipv4_pdu.protocol(),
ipv4_pdu.checksum(),
ipv4_pdu.computed_checksum(),
//ipv4_pdu.source_address(),
sa[0],
sa[1],
sa[2],
sa[3],
//ipv4_pdu.destination_address(),
da[0],
da[1],
da[2],
da[3]
//ipv4_pdu.options()
);
}
#[allow(dead_code)]
fn print_ipv6(ipv6_pdu: Ipv6Pdu) {
print!(
"IPv {:3} {:3} {:3} {:10} {:5} {:3} {:10} {:3} {:?} {:?} {:?} {:3} {:?} {:?}",
// the {:10} could maybe be shorter
// {:?} should be replaced with "proper" hexdecoding, aka a lib to do the displaying
ipv6_pdu.version(),
ipv6_pdu.dscp(),
ipv6_pdu.ecn(),
ipv6_pdu.flow_label(),
ipv6_pdu.payload_length(),
ipv6_pdu.next_header(),
ipv6_pdu.computed_ihl(),
ipv6_pdu.computed_protocol(),
ipv6_pdu.computed_identification(),
ipv6_pdu.computed_more_fragments(),
ipv6_pdu.computed_fragment_offset(),
ipv6_pdu.hop_limit(),
ipv6_pdu.source_address(),
ipv6_pdu.destination_address(),
//ipv6_pdu.extension_headers()
);
}
#[allow(dead_code)]
fn print_tcp(tcp_pdu: TcpPdu) {
print!(
"TCP {:5} {:5} {:10} {:10} {:2} {:2} {:2} {:5} {:5} {:5} {:5} {:5} {:5} {:5} {:5} {:5} {} {} ",
tcp_pdu.source_port(),
tcp_pdu.destination_port(),
tcp_pdu.sequence_number(),
tcp_pdu.acknowledgement_number(),
tcp_pdu.data_offset(),
tcp_pdu.computed_data_offset(),
tcp_pdu.flags(),
tcp_pdu.fin(),
tcp_pdu.syn(),
tcp_pdu.rst(),
tcp_pdu.psh(),
tcp_pdu.ack(),
tcp_pdu.urg(),
tcp_pdu.ecn(),
tcp_pdu.cwr(),
tcp_pdu.window_size(),
//tcp_pdu.computed_window_size(shift: u8),
tcp_pdu.checksum(),
//tcp_pdu.computed_checksum(ip: &crate::Ip),
tcp_pdu.urgent_pointer(),
//tcp_pdu.options(),
);
}
#[allow(dead_code)]
fn print_udp(udp_pdu: UdpPdu) {
print!(
"UDP {:5} {:5} {:5} {:5} {} ",
udp_pdu.source_port(),
udp_pdu.destination_port(),
udp_pdu.length(),
udp_pdu.checksum(),
//udp_pdu.computed_checksum(ip: &crate::Ip),
udp_pdu.computed_data_offset()
);
}
#[allow(unused_variables)]
fn filter_ipv4_tcp_raw(ipv4_pdu: Ipv4Pdu, tcp_pdu: TcpPdu, raw: &[u8]) -> Verdict {
// example filter that drops GET requests to /secret
lazy_static! {
static ref RE: Regex = Regex::new("^GET /secret ").expect("Could not compile Regex!");
}
if RE.is_match(raw) {
Verdict::Drop
} else {
Verdict::Accept
}
}