4 releases

0.2.2 Jan 19, 2024
0.2.1 Jan 15, 2024
0.2.0 Nov 23, 2023
0.1.0 Nov 9, 2023

#1867 in Network programming

Apache-2.0

175KB
4K SLoC

nullnet-firewall

Crates CI Docs Codecov

Rust-based firewall for network drivers.

Purpose

This library is used to match network packets against a set of constraints (here called firewall rules) with the aim of deciding whether to permit or deny incoming/outgoing traffic.

Given a set of firewall rules and a network packet, the library will inform the user about how to handle the packet.

The library assumes that users are able to manipulate the stream of network packets in a way such it's possible to take proper actions to allow or deny the forwarding of single packets between the network card and the operating system; consequently, this framework is mainly intended to be used at the level of network drivers.

Each of the packets passed to the firewall will be logged both in standard output and in a SQLite database with path ./log.sqlite.

Firewall rules definition

A new Firewall object is defined as a set of rules specified in a textual file.

Each of the rules defined in the file is placed on a new line and has the following structure:

[+] DIRECTION ACTION [OPTIONS]
  • Each rule can optionally be introduced by a + character; this will make the rule have higher priority (quick rule).

  • DIRECTION can be either IN or OUT and represents the traffic directionality.

  • ACTION can be either ACCEPT, DENY, or REJECT and represents the action associated with the rule.

  • For each rule, a list of options can be specified to match the desired traffic:

    • --dest: destination IP addresses; the value is expressed in the form of a comma-separated list of IP addresses, in which each entry can also represent an address range (using the - character).
    • --dport: destination transport ports; the value is expressed in the form of a comma-separated list of port numbers, in which each entry can also represent a port range (using the : character).
    • --icmp-type: ICMP message type; the value is expressed as a number representing a specific message type (see here for more info).
    • --proto: Internet Protocol number; the value is expressed as a number representing a specific protocol number (see here for more info).
    • --source: source IP addresses; the value is expressed in the form of a comma-separated list of IP addresses, in which each entry can also represent an address range (using the - character).
    • --sport: source transport ports; the value is expressed in the form of a comma-separated list of port numbers, in which each entry can also represent a port range (using the : character).

A sample firewall configuration file is reported in the following:

# Firewall rules (this is a comment line)

IN REJECT --source 8.8.8.8
# Rules marked with '+' have higher priority
+ IN ACCEPT --source 8.8.8.0-8.8.8.10 --sport 8
OUT ACCEPT --source 8.8.8.8,7.7.7.7 --dport 900:1000,1,2,3
OUT DENY

In case of invalid firewall configurations, a specific FirewallError will be raised.

Usage

A defined Firewall object can be used to determine which action to take for each of the netwrok packets in transit.

This is done by invoking Firewall::resolve_packet, which will answer with the action to take for the supplied packet.

use nullnet_firewall::{Firewall, FirewallDirection, FirewallAction};

// build the firewall from the rules in a file
let firewall = Firewall::new("./samples/firewall.txt").unwrap();

// here we suppose to have a packet to match against the firewall
let packet = [/* ... */];

// determine action for packet, supposing incoming direction for packet
let action = firewall.resolve_packet(&packet, FirewallDirection::IN);

// act accordingly
match action {
    FirewallAction::ACCEPT => {/* ... */}
    FirewallAction::DENY => {/* ... */}
    FirewallAction::REJECT => {/* ... */}
}

Dependencies

~26MB
~493K SLoC