#networking #nf-tables #manager #firewall #netlink #linux

bin+lib rust-network-mgr

Linux based network management, packet routing and LAN peers IP monitoring service

7 releases

Uses new Rust 2024

0.1.8 Apr 4, 2025
0.1.7 Apr 4, 2025

#258 in Unix APIs

Download history 331/week @ 2025-03-29 269/week @ 2025-04-05

600 downloads per month

Custom license

82KB
1K SLoC

Packet Router, Network Manager and IP monitor

This document outlines a unified network management service written in Rust. It monitors network interface IP address changes and dynamically updates nftables sets accordingly. Optionally, it can also monitor Docker container lifecycle events and track their IP addresses. It is designed for Linux systems (Ubuntu/Debian) using nftables.

Prerequisites

  • Rust Toolchain: Install Rust (https://rustup.rs/).
  • nftables: Ensure nftables is installed and running.
    sudo apt update && sudo apt install nftables
    sudo systemctl enable nftables
    sudo systemctl start nftables
    
  • Build Essentials: Required for compiling dependencies.
    sudo apt install build-essential pkg-config libmnl-dev
  • (Optional) Docker Socket Access: For Docker container monitoring, the user running the service needs read access to the Docker daemon socket (typically /var/run/docker.sock). This might involve adding the user to the docker group.

Overview and Rationale

The network manager service is responsible for:

  • Dynamic Monitoring: Detecting real-time changes to network interfaces and IP addresses using Netlink.
  • Firewall Coordination: Automatically updating predefined nftables IP sets based on the nftables_zone configured for each monitored interface.
  • Configuration: Loading interface monitoring configurations from a YAML file.
  • Control: Accepting basic commands via a Unix domain socket.
  • (Optional) Docker Event Monitoring: Tracking container start/stop events and their associated IP addresses.

This Rust implementation provides memory safety, improved concurrency handling, and maintainability.

Implementation Details

Core Components

  1. Main Daemon (src/main.rs): Central process coordinating all activities, handling signals, and managing the main event loop.
  2. Configuration Parser (src/config.rs): Handles loading and validating network configuration from /etc/rust-network-mgr/config.yaml or a path specified by RUST_NETWORK_MGR_CONFIG.
  3. Network Monitor (src/network.rs): Uses rtnetlink to detect IP address and interface changes, emitting events.
  4. NFTables Manager (src/nftables.rs): Interacts with nftables via the rustables crate to update IP sets based on network state. Assumes base nftables ruleset (specifically table inet filter) and the relevant sets (e.g., wan_ips, lan_ips) are already defined.
  5. Control Socket (src/socket.rs): Listens on /run/rust-network-mgr.sock for commands (reload, status, ping).
  6. Docker Monitor (src/docker.rs): (Optional) Connects to the Docker daemon socket using the bollard crate. Listens for container start, stop, and die events. Inspects started containers to retrieve their IP addresses and updates the application's internal state. Fails gracefully if the Docker socket is inaccessible.
graph TD
    A[Main Daemon] --> B(Configuration Parser)
    A --> C(Network Monitor)
    A --> D(NFTables Manager)
    A --> E(Control Socket)
    A --> J(Docker Monitor)

    subgraph "Input/Output"
        F[YAML Config] --> B
        G[System Netlink] <--> C
        H[nftables API] <--> D
        I[Unix Socket Commands] <--> E
        K[Docker Daemon Socket] <--> J
    end

    C -- IP/Interface Events --> A
    J -- Docker Events --> A
    A -- Update Sets --> D
    E -- Control Commands --> A

Core Functional Requirements

  1. IP Address Monitoring: Detect interface IP additions/removals via Netlink.
  2. Atomic NFTables Set Updates: Reliably update configured nftables sets (e.g., inet filter/wan_ips) when corresponding interface IPs change. Uses rustables for atomic updates.
  3. Configuration Parsing: Load interface configurations specifying DHCP status, static addresses (optional), and the target nftables_zone.
  4. Socket Control: Accept reload, status, ping commands.
  5. (Optional) Docker IP Tracking: Maintain an internal map of running container IDs to their discovered IP addresses.

Example Configuration (/etc/rust-network-mgr/config.yaml)

 ```yaml
 interfaces:
  • name: eth0 # Interface name dhcp: true # Monitor DHCP addresses for this interface nftables_zone: wan # Maps to nftables set 'wan_ips' in table 'inet filter'
    • name: eth1 address: 192.168.1.1/24 # Optional static address info (not currently used for monitoring logic) nftables_zone: lan # Maps to nftables set 'lan_ips' in table 'inet filter'

... other interfaces


### NFTables Setup Example

This service *expects* a base `nftables` configuration to exist. It only manages the *elements* within predefined sets.

Example base `/etc/nftables.conf` snippet:

```nftables
table inet filter {
    set wan_ips {
        type ipv4_addr
        flags dynamic
    }
    set lan_ips {
        type ipv4_addr
        flags dynamic
    }

    chain input {
        type filter hook input priority 0; policy accept;

        # Example rule using the set
        ip saddr @wan_ips counter drop
    }

    # ... other chains and rules
}

Directory Structure

rust-network-mgr/
├── Cargo.toml
├── src/
│   ├── main.rs
│   ├── network.rs
│   ├── nftables.rs
│   ├── config.rs
│   ├── socket.rs
│   ├── docker.rs  # Docker monitoring module
│   └── types.rs
├── tests/
│   ├── basic_tests.rs
│   └── nftables_manager_tests.rs # Requires root/nftables access
├── pkg-files/
│   ├── systemd/
│   │   └── rust-network-mgr.service # Example systemd unit
│   └── config/
│       └── default.yaml             # Example config
└── README.md

Key Rust Dependencies (Current)

[dependencies]
# Core Async/Runtime
tokio = { version = "1", features = ["full"] }
futures = "0.3"

# Network Monitoring
rtnetlink = "0.16.0"
netlink-packet-route = "0.22.0"

# NFTables Interaction
rustables = "0.8.6"

# Docker Interaction (Optional Feature)
bollard = "0.15"

# Configuration
serde = { version = "1.0", features = ["derive"] }
serde_yaml = "0.9"
directories = "5.0" # For finding config dirs

# Error Handling & Logging
anyhow = "1.0"
thiserror = "1.0"
log = "0.4"
env_logger = "0.10" # Or tracing/tracing-subscriber

# Utilities
nix = "0.27.1" # For Unix socket permissions

(See Cargo.toml for the definitive list)

Build, Test, and Run

  • Build: cargo build --release (Binary at target/release/rust-network-mgr)
  • Test: cargo test (Some tests require sudo and nftables)
    • Run ignored tests: sudo cargo test -- --ignored
  • Lint: cargo clippy
  • Format: cargo fmt
  • Run:
    • Ensure /etc/rust-network-mgr/config.yaml exists or set RUST_NETWORK_MGR_CONFIG.
    • (Docker) Ensure the service user has permissions for /var/run/docker.sock if Docker monitoring is desired.
    • Run directly (requires privileges for Netlink/nftables/Docker): sudo target/release/rust-network-mgr
    • Use the example systemd service: Copy pkg-files/systemd/rust-network-mgr.service to /etc/systemd/system/, then sudo systemctl daemon-reload, sudo systemctl start rust-network-mgr. Check status with sudo systemctl status rust-network-mgr and logs with sudo journalctl -u rust-network-mgr -f.

Control Socket Usage

# Send commands using socat (install if needed: sudo apt install socat)
echo "status" | sudo socat - UNIX-CONNECT:/run/rust-network-mgr.sock
echo "reload" | sudo socat - UNIX-CONNECT:/run/rust-network-mgr.sock
echo "ping"   | sudo socat - UNIX-CONNECT:/run/rust-network-mgr.sock

Development Priorities & Scope

  1. Reliability: Ensure correct behavior under various network conditions.
  2. Correctness: Accurately update nftables sets based on monitored IPs.
  3. Simplicity: Maintain a focused scope on coordinating Netlink events with nftables set updates. Optional features like Docker monitoring should be self-contained and fail gracefully.
  4. Testability: Design components for unit and integration testing.

Current Scope: This tool focuses primarily on monitoring interface IPs via Netlink and updating pre-existing nftables sets based on a simple configuration map (nftables_zone). It does not manage nftables rules, tables, or chains beyond adding/removing IPs from sets. The optional Docker monitoring currently tracks container IPs internally but does not yet integrate them into nftables rules.

Potential Future Features / Roadmap

While the core focus is narrow, future enhancements could include:

  • More sophisticated nftables interaction (e.g., managing rules directly).
  • IPv6 support in nftables sets.
  • Docker Integration Enhancements:
    • Using discovered container IPs in nftables rules/sets (e.g., based on container labels or predefined mappings).
    • Monitoring Docker network attach/detach events for more granular IP tracking.
  • More detailed status reporting via the control socket (e.g., listing tracked container IPs).

(These are ideas, not commitments. Development follows the priorities above.)

Dependencies

~26–41MB
~668K SLoC