diff options
author | Simon THOBY <git@nightmared.fr> | 2022-10-02 16:01:19 +0200 |
---|---|---|
committer | Simon THOBY <git@nightmared.fr> | 2022-10-02 16:01:19 +0200 |
commit | 3371865506cad4a795f07bce4495eb00d199f4a6 (patch) | |
tree | 7f468905fe7673dbb2d966f04ac0a535704c4db5 /examples | |
parent | ac59df84eb292f8e907fdae3436e589df164e826 (diff) |
Add some initial support for tests with the full-rust engine
Diffstat (limited to 'examples')
-rw-r--r-- | examples/add-rules.rs | 277 | ||||
-rw-r--r-- | examples/filter-ethernet.rs | 185 | ||||
-rw-r--r-- | examples/firewall.rs | 236 |
3 files changed, 348 insertions, 350 deletions
diff --git a/examples/add-rules.rs b/examples/add-rules.rs index 0f89601..0dee080 100644 --- a/examples/add-rules.rs +++ b/examples/add-rules.rs @@ -37,147 +37,148 @@ //! ``` use ipnetwork::{IpNetwork, Ipv4Network}; -use rustables::{nft_expr, query::send_batch, sys::libc, Batch, Chain, ProtoFamily, Rule, Table}; +//use rustables::{nft_expr, query::send_batch, sys::libc, Batch, Chain, ProtoFamily, Rule, Table}; use std::{ffi::CString, io, net::Ipv4Addr, rc::Rc}; - -const TABLE_NAME: &str = "example-table"; -const OUT_CHAIN_NAME: &str = "chain-for-outgoing-packets"; -const IN_CHAIN_NAME: &str = "chain-for-incoming-packets"; +// +//const TABLE_NAME: &str = "example-table"; +//const OUT_CHAIN_NAME: &str = "chain-for-outgoing-packets"; +//const IN_CHAIN_NAME: &str = "chain-for-incoming-packets"; fn main() -> Result<(), Error> { - // Create a batch. This is used to store all the netlink messages we will later send. - // Creating a new batch also automatically writes the initial batch begin message needed - // to tell netlink this is a single transaction that might arrive over multiple netlink packets. - let mut batch = Batch::new(); - - // Create a netfilter table operating on both IPv4 and IPv6 (ProtoFamily::Inet) - let table = Rc::new(Table::new(TABLE_NAME, ProtoFamily::Inet)); - // Add the table to the batch with the `MsgType::Add` type, thus instructing netfilter to add - // this table under its `ProtoFamily::Inet` ruleset. - batch.add(&Rc::clone(&table), rustables::MsgType::Add); - - // Create input and output chains under the table we created above. - // Hook the chains to the input and output event hooks, with highest priority (priority zero). - // See the `Chain::set_hook` documentation for details. - let mut out_chain = Chain::new(OUT_CHAIN_NAME, Rc::clone(&table)); - let mut in_chain = Chain::new(IN_CHAIN_NAME, Rc::clone(&table)); - - out_chain.set_hook(rustables::Hook::Out, 0); - in_chain.set_hook(rustables::Hook::In, 0); - - // Set the default policies on the chains. If no rule matches a packet processed by the - // `out_chain` or the `in_chain` it will accept the packet. - out_chain.set_policy(rustables::Policy::Accept); - in_chain.set_policy(rustables::Policy::Accept); - - let out_chain = Rc::new(out_chain); - let in_chain = Rc::new(in_chain); - - // Add the two chains to the batch with the `MsgType` to tell netfilter to create the chains - // under the table. - batch.add(&Rc::clone(&out_chain), rustables::MsgType::Add); - batch.add(&Rc::clone(&in_chain), rustables::MsgType::Add); - - // === ADD RULE ALLOWING ALL TRAFFIC TO THE LOOPBACK DEVICE === - - // Create a new rule object under the input chain. - let mut allow_loopback_in_rule = Rule::new(Rc::clone(&in_chain)); - // Lookup the interface index of the loopback interface. - let lo_iface_index = iface_index("lo")?; - - // First expression to be evaluated in this rule is load the meta information "iif" - // (incoming interface index) into the comparison register of netfilter. - // When an incoming network packet is processed by this rule it will first be processed by this - // expression, which will load the interface index of the interface the packet came from into - // a special "register" in netfilter. - allow_loopback_in_rule.add_expr(&nft_expr!(meta iif)); - // Next expression in the rule is to compare the value loaded into the register with our desired - // interface index, and succeed only if it's equal. For any packet processed where the equality - // does not hold the packet is said to not match this rule, and the packet moves on to be - // processed by the next rule in the chain instead. - allow_loopback_in_rule.add_expr(&nft_expr!(cmp == lo_iface_index)); - - // Add a verdict expression to the rule. Any packet getting this far in the expression - // processing without failing any expression will be given the verdict added here. - allow_loopback_in_rule.add_expr(&nft_expr!(verdict accept)); - - // Add the rule to the batch. - batch.add(&allow_loopback_in_rule, rustables::MsgType::Add); - - // === ADD A RULE ALLOWING (AND COUNTING) ALL PACKETS TO THE 10.1.0.0/24 NETWORK === - - let mut block_out_to_private_net_rule = Rule::new(Rc::clone(&out_chain)); - let private_net_ip = Ipv4Addr::new(10, 1, 0, 0); - let private_net_prefix = 24; - let private_net = IpNetwork::V4(Ipv4Network::new(private_net_ip, private_net_prefix)?); - - // Load the `nfproto` metadata into the netfilter register. This metadata denotes which layer3 - // protocol the packet being processed is using. - block_out_to_private_net_rule.add_expr(&nft_expr!(meta nfproto)); - // Check if the currently processed packet is an IPv4 packet. This must be done before payload - // data assuming the packet uses IPv4 can be loaded in the next expression. - block_out_to_private_net_rule.add_expr(&nft_expr!(cmp == libc::NFPROTO_IPV4 as u8)); - - // Load the IPv4 destination address into the netfilter register. - block_out_to_private_net_rule.add_expr(&nft_expr!(payload ipv4 daddr)); - // Mask out the part of the destination address that is not part of the network bits. The result - // of this bitwise masking is stored back into the same netfilter register. - block_out_to_private_net_rule.add_expr(&nft_expr!(bitwise mask private_net.mask(), xor 0)); - // Compare the result of the masking with the IP of the network we are interested in. - block_out_to_private_net_rule.add_expr(&nft_expr!(cmp == private_net.ip())); - - // Add a packet counter to the rule. Shows how many packets have been evaluated against this - // expression. Since expressions are evaluated from first to last, putting this counter before - // the above IP net check would make the counter increment on all packets also *not* matching - // those expressions. Because the counter would then be evaluated before it fails a check. - // Similarly, if the counter was added after the verdict it would always remain at zero. Since - // when the packet hits the verdict expression any further processing of expressions stop. - block_out_to_private_net_rule.add_expr(&nft_expr!(counter)); - - // Accept all the packets matching the rule so far. - block_out_to_private_net_rule.add_expr(&nft_expr!(verdict accept)); - - // Add the rule to the batch. Without this nothing would be sent over netlink and netfilter, - // and all the work on `block_out_to_private_net_rule` so far would go to waste. - batch.add(&block_out_to_private_net_rule, rustables::MsgType::Add); - - // === ADD A RULE ALLOWING ALL OUTGOING ICMPv6 PACKETS WITH TYPE 133 AND CODE 0 === - - let mut allow_router_solicitation = Rule::new(Rc::clone(&out_chain)); - - // Check that the packet is IPv6 and ICMPv6 - allow_router_solicitation.add_expr(&nft_expr!(meta nfproto)); - allow_router_solicitation.add_expr(&nft_expr!(cmp == libc::NFPROTO_IPV6 as u8)); - allow_router_solicitation.add_expr(&nft_expr!(meta l4proto)); - allow_router_solicitation.add_expr(&nft_expr!(cmp == libc::IPPROTO_ICMPV6 as u8)); - - allow_router_solicitation.add_expr(&rustables::expr::Payload::Transport( - rustables::expr::TransportHeaderField::Icmpv6(rustables::expr::Icmpv6HeaderField::Type), - )); - allow_router_solicitation.add_expr(&nft_expr!(cmp == 133u8)); - allow_router_solicitation.add_expr(&rustables::expr::Payload::Transport( - rustables::expr::TransportHeaderField::Icmpv6(rustables::expr::Icmpv6HeaderField::Code), - )); - allow_router_solicitation.add_expr(&nft_expr!(cmp == 0u8)); - - allow_router_solicitation.add_expr(&nft_expr!(verdict accept)); - - batch.add(&allow_router_solicitation, rustables::MsgType::Add); - - // === FINALIZE THE TRANSACTION AND SEND THE DATA TO NETFILTER === - - // Finalize the batch. This means the batch end message is written into the batch, telling - // netfilter the we reached the end of the transaction message. It's also converted to a type - // that implements `IntoIterator<Item = &'a [u8]>`, thus allowing us to get the raw netlink data - // out so it can be sent over a netlink socket to netfilter. - match batch.finalize() { - Some(mut finalized_batch) => { - // Send the entire batch and process any returned messages. - send_batch(&mut finalized_batch)?; - Ok(()) - } - None => todo!(), - } + // // Create a batch. This is used to store all the netlink messages we will later send. + // // Creating a new batch also automatically writes the initial batch begin message needed + // // to tell netlink this is a single transaction that might arrive over multiple netlink packets. + // let mut batch = Batch::new(); + // + // // Create a netfilter table operating on both IPv4 and IPv6 (ProtoFamily::Inet) + // let table = Rc::new(Table::new(TABLE_NAME, ProtoFamily::Inet)); + // // Add the table to the batch with the `MsgType::Add` type, thus instructing netfilter to add + // // this table under its `ProtoFamily::Inet` ruleset. + // batch.add(&Rc::clone(&table), rustables::MsgType::Add); + // + // // Create input and output chains under the table we created above. + // // Hook the chains to the input and output event hooks, with highest priority (priority zero). + // // See the `Chain::set_hook` documentation for details. + // let mut out_chain = Chain::new(OUT_CHAIN_NAME, Rc::clone(&table)); + // let mut in_chain = Chain::new(IN_CHAIN_NAME, Rc::clone(&table)); + // + // out_chain.set_hook(rustables::Hook::Out, 0); + // in_chain.set_hook(rustables::Hook::In, 0); + // + // // Set the default policies on the chains. If no rule matches a packet processed by the + // // `out_chain` or the `in_chain` it will accept the packet. + // out_chain.set_policy(rustables::Policy::Accept); + // in_chain.set_policy(rustables::Policy::Accept); + // + // let out_chain = Rc::new(out_chain); + // let in_chain = Rc::new(in_chain); + // + // // Add the two chains to the batch with the `MsgType` to tell netfilter to create the chains + // // under the table. + // batch.add(&Rc::clone(&out_chain), rustables::MsgType::Add); + // batch.add(&Rc::clone(&in_chain), rustables::MsgType::Add); + // + // // === ADD RULE ALLOWING ALL TRAFFIC TO THE LOOPBACK DEVICE === + // + // // Create a new rule object under the input chain. + // let mut allow_loopback_in_rule = Rule::new(Rc::clone(&in_chain)); + // // Lookup the interface index of the loopback interface. + // let lo_iface_index = iface_index("lo")?; + // + // // First expression to be evaluated in this rule is load the meta information "iif" + // // (incoming interface index) into the comparison register of netfilter. + // // When an incoming network packet is processed by this rule it will first be processed by this + // // expression, which will load the interface index of the interface the packet came from into + // // a special "register" in netfilter. + // allow_loopback_in_rule.add_expr(&nft_expr!(meta iif)); + // // Next expression in the rule is to compare the value loaded into the register with our desired + // // interface index, and succeed only if it's equal. For any packet processed where the equality + // // does not hold the packet is said to not match this rule, and the packet moves on to be + // // processed by the next rule in the chain instead. + // allow_loopback_in_rule.add_expr(&nft_expr!(cmp == lo_iface_index)); + // + // // Add a verdict expression to the rule. Any packet getting this far in the expression + // // processing without failing any expression will be given the verdict added here. + // allow_loopback_in_rule.add_expr(&nft_expr!(verdict accept)); + // + // // Add the rule to the batch. + // batch.add(&allow_loopback_in_rule, rustables::MsgType::Add); + // + // // === ADD A RULE ALLOWING (AND COUNTING) ALL PACKETS TO THE 10.1.0.0/24 NETWORK === + // + // let mut block_out_to_private_net_rule = Rule::new(Rc::clone(&out_chain)); + // let private_net_ip = Ipv4Addr::new(10, 1, 0, 0); + // let private_net_prefix = 24; + // let private_net = IpNetwork::V4(Ipv4Network::new(private_net_ip, private_net_prefix)?); + // + // // Load the `nfproto` metadata into the netfilter register. This metadata denotes which layer3 + // // protocol the packet being processed is using. + // block_out_to_private_net_rule.add_expr(&nft_expr!(meta nfproto)); + // // Check if the currently processed packet is an IPv4 packet. This must be done before payload + // // data assuming the packet uses IPv4 can be loaded in the next expression. + // block_out_to_private_net_rule.add_expr(&nft_expr!(cmp == libc::NFPROTO_IPV4 as u8)); + // + // // Load the IPv4 destination address into the netfilter register. + // block_out_to_private_net_rule.add_expr(&nft_expr!(payload ipv4 daddr)); + // // Mask out the part of the destination address that is not part of the network bits. The result + // // of this bitwise masking is stored back into the same netfilter register. + // block_out_to_private_net_rule.add_expr(&nft_expr!(bitwise mask private_net.mask(), xor 0)); + // // Compare the result of the masking with the IP of the network we are interested in. + // block_out_to_private_net_rule.add_expr(&nft_expr!(cmp == private_net.ip())); + // + // // Add a packet counter to the rule. Shows how many packets have been evaluated against this + // // expression. Since expressions are evaluated from first to last, putting this counter before + // // the above IP net check would make the counter increment on all packets also *not* matching + // // those expressions. Because the counter would then be evaluated before it fails a check. + // // Similarly, if the counter was added after the verdict it would always remain at zero. Since + // // when the packet hits the verdict expression any further processing of expressions stop. + // block_out_to_private_net_rule.add_expr(&nft_expr!(counter)); + // + // // Accept all the packets matching the rule so far. + // block_out_to_private_net_rule.add_expr(&nft_expr!(verdict accept)); + // + // // Add the rule to the batch. Without this nothing would be sent over netlink and netfilter, + // // and all the work on `block_out_to_private_net_rule` so far would go to waste. + // batch.add(&block_out_to_private_net_rule, rustables::MsgType::Add); + // + // // === ADD A RULE ALLOWING ALL OUTGOING ICMPv6 PACKETS WITH TYPE 133 AND CODE 0 === + // + // let mut allow_router_solicitation = Rule::new(Rc::clone(&out_chain)); + // + // // Check that the packet is IPv6 and ICMPv6 + // allow_router_solicitation.add_expr(&nft_expr!(meta nfproto)); + // allow_router_solicitation.add_expr(&nft_expr!(cmp == libc::NFPROTO_IPV6 as u8)); + // allow_router_solicitation.add_expr(&nft_expr!(meta l4proto)); + // allow_router_solicitation.add_expr(&nft_expr!(cmp == libc::IPPROTO_ICMPV6 as u8)); + // + // allow_router_solicitation.add_expr(&rustables::expr::Payload::Transport( + // rustables::expr::TransportHeaderField::Icmpv6(rustables::expr::Icmpv6HeaderField::Type), + // )); + // allow_router_solicitation.add_expr(&nft_expr!(cmp == 133u8)); + // allow_router_solicitation.add_expr(&rustables::expr::Payload::Transport( + // rustables::expr::TransportHeaderField::Icmpv6(rustables::expr::Icmpv6HeaderField::Code), + // )); + // allow_router_solicitation.add_expr(&nft_expr!(cmp == 0u8)); + // + // allow_router_solicitation.add_expr(&nft_expr!(verdict accept)); + // + // batch.add(&allow_router_solicitation, rustables::MsgType::Add); + // + // // === FINALIZE THE TRANSACTION AND SEND THE DATA TO NETFILTER === + // + // // Finalize the batch. This means the batch end message is written into the batch, telling + // // netfilter the we reached the end of the transaction message. It's also converted to a type + // // that implements `IntoIterator<Item = &'a [u8]>`, thus allowing us to get the raw netlink data + // // out so it can be sent over a netlink socket to netfilter. + // match batch.finalize() { + // Some(mut finalized_batch) => { + // // Send the entire batch and process any returned messages. + // send_batch(&mut finalized_batch)?; + // Ok(()) + // } + // None => todo!(), + // } + Ok(()) } // Look up the interface index for a given interface name. diff --git a/examples/filter-ethernet.rs b/examples/filter-ethernet.rs index 41454c9..732c8cb 100644 --- a/examples/filter-ethernet.rs +++ b/examples/filter-ethernet.rs @@ -1,96 +1,95 @@ -//! Adds a table, chain and a rule that blocks all traffic to a given MAC address -//! -//! Run the following to print out current active tables, chains and rules in netfilter. Must be -//! executed as root: -//! ```bash -//! # nft list ruleset -//! ``` -//! After running this example, the output should be the following: -//! ```ignore -//! table inet example-filter-ethernet { -//! chain chain-for-outgoing-packets { -//! type filter hook output priority 3; policy accept; -//! ether daddr 00:00:00:00:00:00 drop -//! counter packets 0 bytes 0 meta random > 2147483647 counter packets 0 bytes 0 -//! } -//! } -//! ``` -//! -//! -//! Everything created by this example can be removed by running -//! ```bash -//! # nft delete table inet example-filter-ethernet -//! ``` - -use rustables::{nft_expr, query::send_batch, sys::libc, Batch, Chain, ProtoFamily, Rule, Table}; +///! Adds a table, chain and a rule that blocks all traffic to a given MAC address +///! +///! Run the following to print out current active tables, chains and rules in netfilter. Must be +///! executed as root: +///! ```bash +///! # nft list ruleset +///! ``` +///! After running this example, the output should be the following: +///! ```ignore +///! table inet example-filter-ethernet { +///! chain chain-for-outgoing-packets { +///! type filter hook output priority 3; policy accept; +///! ether daddr 00:00:00:00:00:00 drop +///! counter packets 0 bytes 0 meta random > 2147483647 counter packets 0 bytes 0 +///! } +///! } +///! ``` +///! +///! +///! Everything created by this example can be removed by running +///! ```bash +///! # nft delete table inet example-filter-ethernet +///! ``` +//use rustables::{nft_expr, query::send_batch, sys::libc, Batch, Chain, ProtoFamily, Rule, Table}; use std::{ffi::CString, rc::Rc}; - -const TABLE_NAME: &str = "example-filter-ethernet"; -const OUT_CHAIN_NAME: &str = "chain-for-outgoing-packets"; - -const BLOCK_THIS_MAC: &[u8] = &[0, 0, 0, 0, 0, 0]; - +// +//const TABLE_NAME: &str = "example-filter-ethernet"; +//const OUT_CHAIN_NAME: &str = "chain-for-outgoing-packets"; +// +//const BLOCK_THIS_MAC: &[u8] = &[0, 0, 0, 0, 0, 0]; +// fn main() { - // For verbose explanations of what all these lines up until the rule creation does, see the - // `add-rules` example. - let mut batch = Batch::new(); - let table = Rc::new(Table::new( - &CString::new(TABLE_NAME).unwrap(), - ProtoFamily::Inet, - )); - batch.add(&Rc::clone(&table), rustables::MsgType::Add); - - let mut out_chain = Chain::new(&CString::new(OUT_CHAIN_NAME).unwrap(), Rc::clone(&table)); - out_chain.set_hook(rustables::Hook::Out, 3); - out_chain.set_policy(rustables::Policy::Accept); - let out_chain = Rc::new(out_chain); - batch.add(&Rc::clone(&out_chain), rustables::MsgType::Add); - - // === ADD RULE DROPPING ALL TRAFFIC TO THE MAC ADDRESS IN `BLOCK_THIS_MAC` === - - let mut block_ethernet_rule = Rule::new(Rc::clone(&out_chain)); - - // Check that the interface type is an ethernet interface. Must be done before we can check - // payload values in the ethernet header. - block_ethernet_rule.add_expr(&nft_expr!(meta iiftype)); - block_ethernet_rule.add_expr(&nft_expr!(cmp == libc::ARPHRD_ETHER)); - - // Compare the ethernet destination address against the MAC address we want to drop - block_ethernet_rule.add_expr(&nft_expr!(payload ethernet daddr)); - block_ethernet_rule.add_expr(&nft_expr!(cmp == BLOCK_THIS_MAC)); - - // Drop the matching packets. - block_ethernet_rule.add_expr(&nft_expr!(verdict drop)); - - batch.add(&block_ethernet_rule, rustables::MsgType::Add); - - // === FOR FUN, ADD A PACKET THAT MATCHES 50% OF ALL PACKETS === - - // This packet has a counter before and after the check that has 50% chance of matching. - // So after a number of packets has passed through this rule, the first counter should have a - // value approximately double that of the second counter. This rule has no verdict, so it never - // does anything with the matching packets. - let mut random_rule = Rule::new(Rc::clone(&out_chain)); - // This counter expression will be evaluated (and increment the counter) for all packets coming - // through. - random_rule.add_expr(&nft_expr!(counter)); - - // Load a pseudo-random 32 bit unsigned integer into the netfilter register. - random_rule.add_expr(&nft_expr!(meta random)); - // Check if the random integer is larger than `u32::MAX/2`, thus having 50% chance of success. - random_rule.add_expr(&nft_expr!(cmp > (::std::u32::MAX / 2).to_be())); - - // Add a second counter. This will only be incremented for the packets passing the random check. - random_rule.add_expr(&nft_expr!(counter)); - - batch.add(&random_rule, rustables::MsgType::Add); - - // === FINALIZE THE TRANSACTION AND SEND THE DATA TO NETFILTER === - - match batch.finalize() { - Some(mut finalized_batch) => { - send_batch(&mut finalized_batch).expect("Couldn't process the batch"); - } - None => todo!(), - } + // // For verbose explanations of what all these lines up until the rule creation does, see the + // // `add-rules` example. + // let mut batch = Batch::new(); + // let table = Rc::new(Table::new( + // &CString::new(TABLE_NAME).unwrap(), + // ProtoFamily::Inet, + // )); + // batch.add(&Rc::clone(&table), rustables::MsgType::Add); + // + // let mut out_chain = Chain::new(&CString::new(OUT_CHAIN_NAME).unwrap(), Rc::clone(&table)); + // out_chain.set_hook(rustables::Hook::Out, 3); + // out_chain.set_policy(rustables::Policy::Accept); + // let out_chain = Rc::new(out_chain); + // batch.add(&Rc::clone(&out_chain), rustables::MsgType::Add); + // + // // === ADD RULE DROPPING ALL TRAFFIC TO THE MAC ADDRESS IN `BLOCK_THIS_MAC` === + // + // let mut block_ethernet_rule = Rule::new(Rc::clone(&out_chain)); + // + // // Check that the interface type is an ethernet interface. Must be done before we can check + // // payload values in the ethernet header. + // block_ethernet_rule.add_expr(&nft_expr!(meta iiftype)); + // block_ethernet_rule.add_expr(&nft_expr!(cmp == libc::ARPHRD_ETHER)); + // + // // Compare the ethernet destination address against the MAC address we want to drop + // block_ethernet_rule.add_expr(&nft_expr!(payload ethernet daddr)); + // block_ethernet_rule.add_expr(&nft_expr!(cmp == BLOCK_THIS_MAC)); + // + // // Drop the matching packets. + // block_ethernet_rule.add_expr(&nft_expr!(verdict drop)); + // + // batch.add(&block_ethernet_rule, rustables::MsgType::Add); + // + // // === FOR FUN, ADD A PACKET THAT MATCHES 50% OF ALL PACKETS === + // + // // This packet has a counter before and after the check that has 50% chance of matching. + // // So after a number of packets has passed through this rule, the first counter should have a + // // value approximately double that of the second counter. This rule has no verdict, so it never + // // does anything with the matching packets. + // let mut random_rule = Rule::new(Rc::clone(&out_chain)); + // // This counter expression will be evaluated (and increment the counter) for all packets coming + // // through. + // random_rule.add_expr(&nft_expr!(counter)); + // + // // Load a pseudo-random 32 bit unsigned integer into the netfilter register. + // random_rule.add_expr(&nft_expr!(meta random)); + // // Check if the random integer is larger than `u32::MAX/2`, thus having 50% chance of success. + // random_rule.add_expr(&nft_expr!(cmp > (::std::u32::MAX / 2).to_be())); + // + // // Add a second counter. This will only be incremented for the packets passing the random check. + // random_rule.add_expr(&nft_expr!(counter)); + // + // batch.add(&random_rule, rustables::MsgType::Add); + // + // // === FINALIZE THE TRANSACTION AND SEND THE DATA TO NETFILTER === + // + // match batch.finalize() { + // Some(mut finalized_batch) => { + // send_batch(&mut finalized_batch).expect("Couldn't process the batch"); + // } + // None => todo!(), + // } } diff --git a/examples/firewall.rs b/examples/firewall.rs index 46a0a4d..fc25010 100644 --- a/examples/firewall.rs +++ b/examples/firewall.rs @@ -1,12 +1,11 @@ -use rustables::{Batch, Chain, ChainMethods, Hook, MatchError, ProtoFamily, - Protocol, Rule, RuleMethods, Table, MsgType, Policy}; -use rustables::query::{send_batch, Error as QueryError}; -use rustables::expr::{LogGroup, LogPrefix, LogPrefixError}; +//use rustables::{Batch, Chain, ChainMethods, Hook, MatchError, ProtoFamily, +// Protocol, Rule, RuleMethods, Table, MsgType, Policy}; +//use rustables::query::{send_batch, Error as QueryError}; +//use rustables::expr::{LogGroup, LogPrefix, LogPrefixError}; use ipnetwork::IpNetwork; use std::ffi::{CString, NulError}; -use std::str::Utf8Error; use std::rc::Rc; - +use std::str::Utf8Error; #[derive(thiserror::Error, Debug)] pub enum Error { @@ -16,127 +15,126 @@ pub enum Error { AlreadyDone, #[error("Error converting from a C String")] NulError(#[from] NulError), - #[error("Error creating match")] - MatchError(#[from] MatchError), + //#[error("Error creating match")] + //MatchError(#[from] MatchError), #[error("Error converting to utf-8 string")] Utf8Error(#[from] Utf8Error), #[error("Error applying batch")] BatchError(#[from] std::io::Error), - #[error("Error applying batch")] - QueryError(#[from] QueryError), - #[error("Error encoding the prefix")] - LogPrefixError(#[from] LogPrefixError), + //#[error("Error applying batch")] + //QueryError(#[from] QueryError), + //#[error("Error encoding the prefix")] + //LogPrefixError(#[from] LogPrefixError), } const TABLE_NAME: &str = "main-table"; - fn main() -> Result<(), Error> { - let fw = Firewall::new()?; - fw.start()?; + // let fw = Firewall::new()?; + // fw.start()?; Ok(()) } - - -/// An example firewall. See the source of its `start()` method. -pub struct Firewall { - batch: Batch, - inbound: Rc<Chain>, - _outbound: Rc<Chain>, - _forward: Rc<Chain>, - table: Rc<Table>, -} - -impl Firewall { - pub fn new() -> Result<Self, Error> { - let mut batch = Batch::new(); - let table = Rc::new( - Table::new(&CString::new(TABLE_NAME)?, ProtoFamily::Inet) - ); - batch.add(&table, MsgType::Add); - - // Create base chains. Base chains are hooked into a Direction/Hook. - let inbound = Rc::new( - Chain::from_hook(Hook::In, Rc::clone(&table)) - .verdict(Policy::Drop) - .add_to_batch(&mut batch) - ); - let _outbound = Rc::new( - Chain::from_hook(Hook::Out, Rc::clone(&table)) - .verdict(Policy::Accept) - .add_to_batch(&mut batch) - ); - let _forward = Rc::new( - Chain::from_hook(Hook::Forward, Rc::clone(&table)) - .verdict(Policy::Accept) - .add_to_batch(&mut batch) - ); - - Ok(Firewall { - table, - batch, - inbound, - _outbound, - _forward - }) - } - /// Allow some common-sense exceptions to inbound drop, and accept outbound and forward. - pub fn start(mut self) -> Result<(), Error> { - // Allow all established connections to get in. - Rule::new(Rc::clone(&self.inbound)) - .established() - .accept() - .add_to_batch(&mut self.batch); - // Allow all traffic on the loopback interface. - Rule::new(Rc::clone(&self.inbound)) - .iface("lo")? - .accept() - .add_to_batch(&mut self.batch); - // Allow ssh from anywhere, and log to dmesg with a prefix. - Rule::new(Rc::clone(&self.inbound)) - .dport("22", &Protocol::TCP)? - .accept() - .log(None, Some(LogPrefix::new("allow ssh connection:")?)) - .add_to_batch(&mut self.batch); - - // Allow http from all IPs in 192.168.1.255/24 . - let local_net = IpNetwork::new([192, 168, 1, 0].into(), 24).unwrap(); - Rule::new(Rc::clone(&self.inbound)) - .dport("80", &Protocol::TCP)? - .snetwork(local_net) - .accept() - .add_to_batch(&mut self.batch); - - // Allow ICMP traffic, drop IGMP. - Rule::new(Rc::clone(&self.inbound)) - .icmp() - .accept() - .add_to_batch(&mut self.batch); - Rule::new(Rc::clone(&self.inbound)) - .igmp() - .drop() - .add_to_batch(&mut self.batch); - - // Log all traffic not accepted to NF_LOG group 1, accessible with ulogd. - Rule::new(Rc::clone(&self.inbound)) - .log(Some(LogGroup(1)), None) - .add_to_batch(&mut self.batch); - - let mut finalized_batch = self.batch.finalize().unwrap(); - send_batch(&mut finalized_batch)?; - println!("table {} commited", TABLE_NAME); - Ok(()) - } - /// If there is any table with name TABLE_NAME, remove it. - pub fn stop(mut self) -> Result<(), Error> { - self.batch.add(&self.table, MsgType::Add); - self.batch.add(&self.table, MsgType::Del); - - let mut finalized_batch = self.batch.finalize().unwrap(); - send_batch(&mut finalized_batch)?; - println!("table {} destroyed", TABLE_NAME); - Ok(()) - } -} - - +// +// +///// An example firewall. See the source of its `start()` method. +//pub struct Firewall { +// batch: Batch, +// inbound: Rc<Chain>, +// _outbound: Rc<Chain>, +// _forward: Rc<Chain>, +// table: Rc<Table>, +//} +// +//impl Firewall { +// pub fn new() -> Result<Self, Error> { +// let mut batch = Batch::new(); +// let table = Rc::new( +// Table::new(&CString::new(TABLE_NAME)?, ProtoFamily::Inet) +// ); +// batch.add(&table, MsgType::Add); +// +// // Create base chains. Base chains are hooked into a Direction/Hook. +// let inbound = Rc::new( +// Chain::from_hook(Hook::In, Rc::clone(&table)) +// .verdict(Policy::Drop) +// .add_to_batch(&mut batch) +// ); +// let _outbound = Rc::new( +// Chain::from_hook(Hook::Out, Rc::clone(&table)) +// .verdict(Policy::Accept) +// .add_to_batch(&mut batch) +// ); +// let _forward = Rc::new( +// Chain::from_hook(Hook::Forward, Rc::clone(&table)) +// .verdict(Policy::Accept) +// .add_to_batch(&mut batch) +// ); +// +// Ok(Firewall { +// table, +// batch, +// inbound, +// _outbound, +// _forward +// }) +// } +// /// Allow some common-sense exceptions to inbound drop, and accept outbound and forward. +// pub fn start(mut self) -> Result<(), Error> { +// // Allow all established connections to get in. +// Rule::new(Rc::clone(&self.inbound)) +// .established() +// .accept() +// .add_to_batch(&mut self.batch); +// // Allow all traffic on the loopback interface. +// Rule::new(Rc::clone(&self.inbound)) +// .iface("lo")? +// .accept() +// .add_to_batch(&mut self.batch); +// // Allow ssh from anywhere, and log to dmesg with a prefix. +// Rule::new(Rc::clone(&self.inbound)) +// .dport("22", &Protocol::TCP)? +// .accept() +// .log(None, Some(LogPrefix::new("allow ssh connection:")?)) +// .add_to_batch(&mut self.batch); +// +// // Allow http from all IPs in 192.168.1.255/24 . +// let local_net = IpNetwork::new([192, 168, 1, 0].into(), 24).unwrap(); +// Rule::new(Rc::clone(&self.inbound)) +// .dport("80", &Protocol::TCP)? +// .snetwork(local_net) +// .accept() +// .add_to_batch(&mut self.batch); +// +// // Allow ICMP traffic, drop IGMP. +// Rule::new(Rc::clone(&self.inbound)) +// .icmp() +// .accept() +// .add_to_batch(&mut self.batch); +// Rule::new(Rc::clone(&self.inbound)) +// .igmp() +// .drop() +// .add_to_batch(&mut self.batch); +// +// // Log all traffic not accepted to NF_LOG group 1, accessible with ulogd. +// Rule::new(Rc::clone(&self.inbound)) +// .log(Some(LogGroup(1)), None) +// .add_to_batch(&mut self.batch); +// +// let mut finalized_batch = self.batch.finalize().unwrap(); +// send_batch(&mut finalized_batch)?; +// println!("table {} commited", TABLE_NAME); +// Ok(()) +// } +// /// If there is any table with name TABLE_NAME, remove it. +// pub fn stop(mut self) -> Result<(), Error> { +// self.batch.add(&self.table, MsgType::Add); +// self.batch.add(&self.table, MsgType::Del); +// +// let mut finalized_batch = self.batch.finalize().unwrap(); +// send_batch(&mut finalized_batch)?; +// println!("table {} destroyed", TABLE_NAME); +// Ok(()) +// } +//} +// +// |