Contents

SPONSOR VIEW SOURCE
FIREWALL TESTING KERNEL LEVEL FASTAPI + SVELTE SCAPY INJECTOR NETNS ISOLATED

Network Sandbox Engine (NSE)

NSE is a visual, deterministic firewall testing environment for nftables rules. Using ephemeral Linux network namespaces (netns) and Scapy packet injection, it compiles and executes rules inside the real Linux kernel in total isolation. The host firewall is never modified, providing a safe, scriptable, and visual platform for validating complex routing logic, firewall policies, and traffic redirection behaviors.

bash
$ git clone https://github.com/onyks-os/NetworkSandboxEngine.git
$ cd NetworkSandboxEngine && make setup
$ sudo -E make run-rootd
[NSE-ROOTD] Socket server running as root...
[OK] Listening on /var/run/nse-core.sock
PRIVILEGE REQUIREMENT
Managing network namespaces, creating virtual interfaces (veth), and injecting raw packets (Scapy) requires kernel-level administration permissions. The daemon and the CLI runner must be run with root privileges (e.g., using sudo).
0x02

Key Features & Capabilities

STATEFUL SEQUENCES & CONNTRACK
  • Inject sequential list of packets via Scapy (e.g. simulating a TCP 3-way handshake).
  • Dynamic polling of /proc/net/nf_conntrack to capture connection state changes.
MOCK DAEMON LISTENERS
  • Automatically spawns background echo servers on target ports inside namespaces.
  • Generates real kernel-level TCP responses to complete connections and update conntrack.
GATEWAY TOPOLOGY ROUTING
  • Spawn dual-namespace layouts simulating a Host ◄─► Router ◄─► Server topology.
  • Load and test transit forwarding rules on the intermediate Router namespace hook.
WEB UI VISUALIZATION
  • Interactive UI built with Svelte and FastAPI displaying real-time packet traces.
  • Detailed logs of nftables match hook evaluations, verdicts, and connection states.
0x03

Setup & Installation Instructions

Prerequisites

Dependency Purpose
Python 3.10+ Runs the backend FastAPI, pipeline orchestration, and CLI test runner
Node.js 18+ Required to compile the Svelte / Vite web interface (optional for CLI runner)
nftables Required by the kernel to compile rules and trigger monitoring traces
conntrack System utility required to read and poll `/proc/net/nf_conntrack` states

1. Install Host Tools (Debian/Ubuntu)

bash
$ sudo apt update
$ sudo apt install nftables iproute2 python3-venv python3-pip conntrack -y

2. Setup Python Virtual Environment

bash
$ make setup

3. Running the Dashboard (Privilege Separation)

NSE version 1.1.0+ implements a privilege-separated architecture. Start the root execution daemon, the unprivileged API server, and the Vite frontend dev server in three separate terminals:

bash
# Terminal 1 - Start Root Daemon (requires root)
$ sudo -E make run-rootd
# Terminal 2 - Start API Web Server (runs as normal user)
$ make run-web
# Terminal 3 - Start Vite Frontend Dev Server
$ make frontend
0x04

System Architecture

Component Technology Description
Frontend UI Svelte + Vite Web interface containing the rule editor, packet sequence builder, and real-time conntrack/trace animation.
Execution Daemon (`nse-rootd`) Python JSON-RPC Runs as root. Exposes an isolated UNIX socket interface (/var/run/nse-core.sock) to handle low-level network namespace allocations, Scapy packet injections, and trace harvesting.
Web Server (`nse-web`) FastAPI Runs as an unprivileged user. Interacts with the user interface via WebSockets and REST, delegating low-level operations to the root daemon using RootdClient.
Packet Injector Scapy Forges L2/L3 packets matching the requested protocol (TCP, UDP, ICMP, ICMPv6), injecting them directly onto virtual link endpoints.
Trace Harvester `nft monitor trace` Spawns as a background subprocess inside the target network namespace, parsing nftables tracing logs on-the-fly.
CLI Runner Python argparse Headless utility to parse, execute, and assert YAML-based test suites offline for CI/CD environments.
0x05

Test Run Execution Flow

The lifecycle of a single sandbox test request follows a strict synchronous/asynchronous pipeline orchestrated by the daemon:

Pipeline Lifecycle
1. Setup Topology:Allocates namespaces, hooks virtual ethernet pairs (veth), and sets loopback devices UP.
2. Mock Listeners:Launches lightweight UDP/TCP echo servers on targeted socket ports inside the server namespace.
3. Rule Loading:Compiles and injects rulesets into the namespace kernel environment, appending meta nftrace set 1.
4. Harvester Init:Starts nft monitor trace asynchronously to hook trace logs.
5. Packet Injection:Triggers Scapy to send the forged packets. Outgoing packets re-exec python in the netns context via nsenter.
6. Conntrack Polling:Drains connection tracking statistics and streams them to the UI/runner.
7. Garbage Collector:Gracefully kills listeners, tears down namespace interfaces, and deletes netns descriptors.
0x06

CLI Test Runner & YAML Suites

Automated assertions can be run inside headless environments using the nse-runner CLI:

bash
$ sudo -E .venv/bin/python -m nse.cli.runner --file tests/test_suite.yaml

Example YAML Suite (`test_suite.yaml`)

test_suite.yaml
tests:
  - name: "Simple Topology Allow TCP 80"
    topology: "simple"
    rules: |
      table ip filter {
        chain input {
          type filter hook input priority 0; policy drop;
          tcp dport 80 accept
        }
      }
    packets:
      - protocol: "tcp"
        dst_port: 80
        expected_verdict: "ACCEPT"
      - protocol: "tcp"
        dst_port: 22
        expected_verdict: "DROP"
0x07

TTP (Transparent Tor Proxy) Integration Guide

NSE is officially integrated into TTP's pipeline to enable robust, offline verification of firewall rule behaviors (such as redirection and leak drop prevention) without requiring active Tor network circuits.

BRIDGING RULES & TESTS
TTP runs its ruleset compilation during testing by patching the actual _run_nft_string() function. The resulting ruleset string is fed directly to NSE, verifying that DNS queries are intercepted onto port 9054 and DNS-over-TLS (port 853) is rejected by the killswitch.

Example Pytest Integration

test_nse_integration.py
import json, tempfile, subprocess
from unittest.mock import patch, MagicMock
from ttp.firewall import apply_rules

def test_ttp_redirection_with_nse():
    # 1. Capture compilation string
    with patch("ttp.firewall._run_nft"), \
         patch("ttp.firewall._run_nft_string") as mock_run_string, \
         patch("ttp.firewall.pwd.getpwnam") as mock_pwd:
        mock_pwd.return_value = MagicMock(pw_uid=110)
        apply_rules(tor_user="debian-tor", transport_port=9041, dns_port=9054)
        ruleset = mock_run_string.call_args[0][0]

    # 2. Formulate NSE assertions
    test_suite = {
        "tests": [{
            "name": "Redirect DNS traffic to Tor DNSPort",
            "rules": ruleset,
            "packets": [{"protocol": "udp", "dst_port": 53, "expected_verdict": "ACCEPT"}]
        }]
    }

    # 3. Call NSE CLI test runner
    res = subprocess.run(["python3", "-m", "nse.cli.runner", "--file", tmp_yaml_path])
    assert res.returncode == 0
0x08

Production Deployment & Releases

Release Packaging (`make release`)

Running make release runs linter and unit tests, compiles python distribution package files (wheel and source distribution), copies deployment assets (like the Dockerfile and systemd template), and signs the final release bundle containing the checksums using GPG.

Docker Container Deployment

To run the dashboard inside an isolated container with netns capabilities:

bash
$ docker build -t nse -f release/Dockerfile .
$ docker run --privileged -p 8000:8000 -d --name nse-container nse
0x09

Known Limitations

SOCKET OWNER MATCHING (skuid/skgid)
Because Scapy injectors construct raw L2/L3 packets and inject them at interface level, they lack local process socket associations inside the kernel. As a result, nftables rules that match on local socket owners (such as meta skuid or meta skgid) will not trigger on injected Scapy packets.
KERNEL CAPABILITIES
Traces rely on nft monitor trace support, which requires modern Linux Kernel releases (Kernel 5.4+). Running in restrictive VM or minimal container runtimes that block kernel module loading might cause pipeline errors.