docs(readme): rewrite as portfolio-style overview with UI gallery + architecture diagram

- Lead with one-line positioning (inline NIDS+IPS on eBPF, fused 4 detectors,
  SOAR, WORM audit) + tech stack block. Drop the sales pitch and aspirational
  SOC-persona framing — this is a personal project.
- Replace the original 4 screenshots with an 18-tile grid covering the full UI
  surface (monitoring, security, system), placed under .github/images/ui/.
- Add an SVG+PNG architecture diagram (.github/images/architecture.*) showing
  the three-band structure: control plane → user space (detectors →
  orchestrator → SOAR) → kernel-space XDP pipeline, with legend for the five
  arrow semantics.
- Keep the AF_XDP NIC/kernel matrix; collapse getting-started to a three-line
  build block; point deeper architecture details to docs/.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
DaLaw2 2026-04-19 19:46:35 +08:00
parent 48effea826
commit 6794a8ca51
28 changed files with 166 additions and 77 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 71 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 194 KiB

BIN
.github/images/architecture.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 163 KiB

105
.github/images/architecture.svg vendored Normal file
View File

@ -0,0 +1,105 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1200 900" width="1200" height="900">
<defs>
<style>
text { font-family: "Inter", "Segoe UI", "Noto Sans", sans-serif; fill: #e5e7eb; }
.title { font-size: 26px; font-weight: 700; fill: #f9fafb; }
.band-label { font-size: 11px; font-weight: 600; letter-spacing: 1.5px; fill: #9ca3af; }
.box-title { font-size: 14px; font-weight: 600; fill: #f3f4f6; }
.box-title-lg { font-size: 16px; font-weight: 700; fill: #f3f4f6; }
.box-sub { font-size: 12px; fill: #cbd5e1; }
.box-bullet { font-size: 12px; fill: #cbd5e1; }
.arrow-label { font-size: 11px; font-weight: 500; fill: #d1d5db; }
.arrow-label-bg { fill: #0f0f1a; }
.legend-label { font-size: 11px; fill: #9ca3af; }
</style>
<marker id="arrow-blue" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="8" markerHeight="8" orient="auto-start-reverse">
<path d="M0,0 L10,5 L0,10 Z" fill="#60a5fa"/>
</marker>
<marker id="arrow-green" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="8" markerHeight="8" orient="auto-start-reverse">
<path d="M0,0 L10,5 L0,10 Z" fill="#34d399"/>
</marker>
<marker id="arrow-orange" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="8" markerHeight="8" orient="auto-start-reverse">
<path d="M0,0 L10,5 L0,10 Z" fill="#fb923c"/>
</marker>
<marker id="arrow-gray" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="8" markerHeight="8" orient="auto-start-reverse">
<path d="M0,0 L10,5 L0,10 Z" fill="#9ca3af"/>
</marker>
<marker id="arrow-purple" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="8" markerHeight="8" orient="auto-start-reverse">
<path d="M0,0 L10,5 L0,10 Z" fill="#a78bfa"/>
</marker>
</defs>
<rect x="0" y="0" width="1200" height="900" fill="#0f0f1a"/>
<text class="title" x="600" y="46" text-anchor="middle">NetGuardia architecture</text>
<rect x="40" y="70" width="1120" height="80" rx="10" fill="#161627" stroke="#2a2a4a" stroke-width="1"/>
<text class="band-label" x="60" y="92">CONTROL PLANE</text>
<rect x="400" y="100" width="400" height="40" rx="8" fill="#1f1f36" stroke="#60a5fa" stroke-width="1.5"/>
<text class="box-title" x="600" y="126" text-anchor="middle">Web UI + REST / WebSocket API</text>
<rect x="40" y="170" width="1120" height="500" rx="10" fill="#161627" stroke="#2a2a4a" stroke-width="1"/>
<text class="band-label" x="60" y="192">USER SPACE — DETECTION &amp; RESPONSE</text>
<rect x="115" y="210" width="220" height="80" rx="8" fill="#1f1f36" stroke="#a78bfa" stroke-width="1.5"/>
<text class="box-title" x="225" y="244" text-anchor="middle">ML Inference</text>
<text class="box-sub" x="225" y="266" text-anchor="middle">tract-onnx · BYO model</text>
<rect x="365" y="210" width="220" height="80" rx="8" fill="#1f1f36" stroke="#a78bfa" stroke-width="1.5"/>
<text class="box-title" x="475" y="244" text-anchor="middle">Beaconing</text>
<text class="box-sub" x="475" y="266" text-anchor="middle">temporal CV</text>
<rect x="615" y="210" width="220" height="80" rx="8" fill="#1f1f36" stroke="#a78bfa" stroke-width="1.5"/>
<text class="box-title" x="725" y="244" text-anchor="middle">Correlation</text>
<text class="box-sub" x="725" y="266" text-anchor="middle">graph topology</text>
<rect x="865" y="210" width="220" height="80" rx="8" fill="#1f1f36" stroke="#a78bfa" stroke-width="1.5"/>
<text class="box-title" x="975" y="244" text-anchor="middle">Suricata</text>
<text class="box-sub" x="975" y="266" text-anchor="middle">eve.json ingest</text>
<rect x="300" y="350" width="600" height="130" rx="10" fill="#1f1f36" stroke="#60a5fa" stroke-width="2"/>
<text class="box-title-lg" x="600" y="378" text-anchor="middle">Detection Orchestrator</text>
<text class="box-bullet" x="340" y="410">• canonicalize attack type</text>
<text class="box-bullet" x="340" y="432">• fuse: 1 ∏(1 c_i)</text>
<text class="box-bullet" x="340" y="454">• WORM audit (SHA-256 chained)</text>
<rect x="300" y="520" width="600" height="130" rx="10" fill="#1f1f36" stroke="#fb923c" stroke-width="2"/>
<text class="box-title-lg" x="600" y="548" text-anchor="middle">SOAR Engine</text>
<text class="box-bullet" x="340" y="580">• playbook match</text>
<text class="box-bullet" x="340" y="602">• cooldown + dry-run</text>
<text class="box-bullet" x="340" y="624">• actions: block / rate-limit / webhook / email / telegram</text>
<rect x="40" y="690" width="1120" height="140" rx="10" fill="#161627" stroke="#2a2a4a" stroke-width="1"/>
<text class="band-label" x="60" y="712">KERNEL SPACE — eBPF / XDP</text>
<rect x="80" y="750" width="180" height="60" rx="8" fill="#1f1f36" stroke="#34d399" stroke-width="1.5"/>
<text class="box-title" x="170" y="787" text-anchor="middle">ACL</text>
<rect x="295" y="750" width="180" height="60" rx="8" fill="#1f1f36" stroke="#34d399" stroke-width="1.5"/>
<text class="box-title" x="385" y="787" text-anchor="middle">Rate Limit</text>
<rect x="510" y="750" width="180" height="60" rx="8" fill="#1f1f36" stroke="#34d399" stroke-width="1.5"/>
<text class="box-title" x="600" y="787" text-anchor="middle">Protocol Filter</text>
<rect x="725" y="750" width="180" height="60" rx="8" fill="#1f1f36" stroke="#34d399" stroke-width="1.5"/>
<text class="box-title" x="815" y="787" text-anchor="middle">Geo Block</text>
<rect x="940" y="750" width="180" height="60" rx="8" fill="#1f1f36" stroke="#34d399" stroke-width="1.5"/>
<text class="box-title" x="1030" y="787" text-anchor="middle">DNS Filter</text>
<line x1="262" y1="780" x2="293" y2="780" stroke="#34d399" stroke-width="1.8" marker-end="url(#arrow-green)"/>
<line x1="477" y1="780" x2="508" y2="780" stroke="#34d399" stroke-width="1.8" marker-end="url(#arrow-green)"/>
<line x1="692" y1="780" x2="723" y2="780" stroke="#34d399" stroke-width="1.8" marker-end="url(#arrow-green)"/>
<line x1="907" y1="780" x2="938" y2="780" stroke="#34d399" stroke-width="1.8" marker-end="url(#arrow-green)"/>
<line x1="590" y1="140" x2="590" y2="348" stroke="#9ca3af" stroke-width="1.5" stroke-dasharray="4,2" marker-end="url(#arrow-gray)"/>
<line x1="610" y1="348" x2="610" y2="142" stroke="#9ca3af" stroke-width="1.5" stroke-dasharray="4,2" marker-end="url(#arrow-gray)"/>
<rect class="arrow-label-bg" x="535" y="156" width="130" height="18" rx="2"/>
<text class="arrow-label" x="600" y="169" text-anchor="middle">admin &amp; live events</text>
<path d="M 225,290 L 225,320 L 420,340 L 420,350" fill="none" stroke="#60a5fa" stroke-width="1.8" marker-end="url(#arrow-blue)"/>
<path d="M 475,290 L 475,320 L 540,340 L 540,350" fill="none" stroke="#60a5fa" stroke-width="1.8" marker-end="url(#arrow-blue)"/>
<path d="M 725,290 L 725,320 L 660,340 L 660,350" fill="none" stroke="#60a5fa" stroke-width="1.8" marker-end="url(#arrow-blue)"/>
<path d="M 975,290 L 975,320 L 780,340 L 780,350" fill="none" stroke="#60a5fa" stroke-width="1.8" marker-end="url(#arrow-blue)"/>
<line x1="600" y1="480" x2="600" y2="520" stroke="#34d399" stroke-width="2" marker-end="url(#arrow-green)"/>
<rect class="arrow-label-bg" x="612" y="488" width="135" height="18" rx="2"/>
<text class="arrow-label" x="680" y="501" text-anchor="middle">ThreatDetectedEvent</text>
<path d="M 320,650 L 320,680 L 115,680 L 115,745 L 170,745 L 170,750" fill="none" stroke="#fb923c" stroke-width="2" marker-end="url(#arrow-orange)"/>
<rect class="arrow-label-bg" x="130" y="670" width="170" height="18" rx="2"/>
<text class="arrow-label" x="215" y="683" text-anchor="middle">enforce (block / rate-limit)</text>
<path d="M 1095,750 L 1095,310 L 1005,310 L 1005,290" fill="none" stroke="#a78bfa" stroke-width="2" marker-end="url(#arrow-purple)"/>
<rect class="arrow-label-bg" x="1030" y="468" width="100" height="18" rx="2"/>
<text class="arrow-label" x="1080" y="481" text-anchor="middle">AF_XDP mirror</text>
<line x1="60" y1="870" x2="84" y2="870" stroke="#60a5fa" stroke-width="2"/>
<text class="legend-label" x="90" y="874">detection events</text>
<line x1="216" y1="870" x2="240" y2="870" stroke="#34d399" stroke-width="2"/>
<text class="legend-label" x="246" y="874">fused event / kernel pipeline</text>
<line x1="450" y1="870" x2="474" y2="870" stroke="#fb923c" stroke-width="2"/>
<text class="legend-label" x="480" y="874">enforcement action</text>
<line x1="618" y1="870" x2="642" y2="870" stroke="#a78bfa" stroke-width="2"/>
<text class="legend-label" x="648" y="874">AF_XDP mirror</text>
<line x1="756" y1="870" x2="780" y2="870" stroke="#9ca3af" stroke-width="2"/>
<text class="legend-label" x="786" y="874">admin / control</text>
</svg>

After

Width:  |  Height:  |  Size: 8.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 98 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 108 KiB

BIN
.github/images/map.png vendored

Binary file not shown.

Before

Width:  |  Height:  |  Size: 187 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 122 KiB

BIN
.github/images/ui/access-control.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 100 KiB

BIN
.github/images/ui/account-management.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 79 KiB

BIN
.github/images/ui/api-keys.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 70 KiB

BIN
.github/images/ui/audit-log.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 223 KiB

BIN
.github/images/ui/auto-response.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 133 KiB

BIN
.github/images/ui/detection.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 140 KiB

BIN
.github/images/ui/dns-filter.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 71 KiB

BIN
.github/images/ui/drop-monitor.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 68 KiB

BIN
.github/images/ui/flow-trace.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 79 KiB

BIN
.github/images/ui/geoip-block.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 70 KiB

BIN
.github/images/ui/logs.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 267 KiB

BIN
.github/images/ui/map.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 213 KiB

BIN
.github/images/ui/protocol-filter.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 71 KiB

BIN
.github/images/ui/rate-limit.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 87 KiB

BIN
.github/images/ui/security-report.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 122 KiB

BIN
.github/images/ui/statistics.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 182 KiB

BIN
.github/images/ui/system-settings.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 102 KiB

BIN
.github/images/ui/system-status.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 151 KiB

132
README.md
View File

@ -1,86 +1,76 @@
# NetGuardia
## Project Overview
Inline network security platform built on eBPF/XDP. Runs four independent detectors (per-packet ML, temporal beaconing, graph correlation, Suricata) over the same data plane, fuses their verdicts, drives SOAR playbooks, and writes every decision into a WORM audit chain.
**NetGuardia** is a high-performance network security solution that combines eBPF XDP technology with deep learning models to provide advanced network protection. The system operates as a standalone network appliance that can run on any Ubuntu-based system with compatible network hardware.
## Stack
## Core Technologies
- **Data plane** — eBPF / XDP / AF_XDP (aya, xsk-rs)
- **Detection** — Rust + tract-onnx for ML, custom temporal / graph engines, Suricata `eve.json` ingest
- **Control plane** — actix-web REST + WebSocket, SQLite + SQLCipher, argon2 / JWT / CSRF, per-playbook SOAR
- **Frontend** — Vue 3 + Pinia + Vue-i18n (en / zh-TW / zh-CN / ja)
- **Architecture** — hexagonal: `adapter/` · `core/` · `infrastructure/` · `interface/` · `model/`
- **eBPF XDP Technology** - Provides high-performance packet processing directly at the data link layer
- **Deep Learning Models** - Identifies and predicts potential network attacks with intelligent threat detection
- **Hardware Integration** - Designed to work with Intel i350 T2 and similar enterprise-grade network interface cards
## Screens
## Functional Modules
<table>
<tr>
<td><img src=".github/images/ui/statistics.png" alt="Traffic statistics"/><br><sub>Traffic statistics (per-IP bytes/packets)</sub></td>
<td><img src=".github/images/ui/map.png" alt="Geo map"/><br><sub>Live geographic flow map</sub></td>
<td><img src=".github/images/ui/drop-monitor.png" alt="Drop monitor"/><br><sub>Real-time drop monitor</sub></td>
</tr>
<tr>
<td><img src=".github/images/ui/detection.png" alt="Threat detection"/><br><sub>Fused threat detection + ML status</sub></td>
<td><img src=".github/images/ui/access-control.png" alt="Access control"/><br><sub>IPv4/IPv6 allow + block lists</sub></td>
<td><img src=".github/images/ui/geoip-block.png" alt="GeoIP block"/><br><sub>GeoIP country block</sub></td>
</tr>
<tr>
<td><img src=".github/images/ui/dns-filter.png" alt="DNS filter"/><br><sub>DNS blacklist</sub></td>
<td><img src=".github/images/ui/rate-limit.png" alt="Rate limit"/><br><sub>Per-class DDoS rate limits</sub></td>
<td><img src=".github/images/ui/protocol-filter.png" alt="Protocol filter"/><br><sub>HTTP / SSH service rules</sub></td>
</tr>
<tr>
<td><img src=".github/images/ui/auto-response.png" alt="SOAR"/><br><sub>SOAR playbooks + dry-run</sub></td>
<td><img src=".github/images/ui/security-report.png" alt="Security report"/><br><sub>Security report (PDF / email)</sub></td>
<td><img src=".github/images/ui/audit-log.png" alt="Audit log"/><br><sub>WORM-chained audit log</sub></td>
</tr>
<tr>
<td><img src=".github/images/ui/account-management.png" alt="Accounts"/><br><sub>Users + groups + RBAC</sub></td>
<td><img src=".github/images/ui/api-keys.png" alt="API keys"/><br><sub>API keys</sub></td>
<td><img src=".github/images/ui/flow-trace.png" alt="Flow trace"/><br><sub>Rotated flow recording</sub></td>
</tr>
<tr>
<td><img src=".github/images/ui/logs.png" alt="Logs"/><br><sub>Live + archived logs</sub></td>
<td><img src=".github/images/ui/system-status.png" alt="System status"/><br><sub>CPU / memory / NIC counters</sub></td>
<td><img src=".github/images/ui/system-settings.png" alt="System settings"/><br><sub>Mode / theme / HTTP / engine</sub></td>
</tr>
</table>
### Resource Overview
![Home](.github/images/index.png)
- Real-time control system occupancy rate
## Architecture
### Dashboard Overview
![Dashboard](.github/images/dashboard.png)
- Real-time network traffic monitoring and visualization
- Recent traffic statistics and trend analysis
![NetGuardia architecture](.github/images/architecture.png)
### Detailed Traffic Statistics
![Statistics](.github/images/statistics.png)
- Detailed traffic usage information per IP address
## Requirements
### Network Access Control
![accessControl](.github/images/accessControl.png)
- IPv4/IPv6 whitelist and blacklist management
- Precise port-level access control
Linux kernel with eBPF **and** a NIC driver that implements AF_XDP on that kernel. No single "minimum kernel" — it depends on the NIC.
[//]: # (### AI Attack Detection)
| Driver | NIC family | Min kernel for AF_XDP |
|---|---|---|
| `mlx5` | Mellanox ConnectX-4/5/6/7 | 5.x |
| `ixgbe` | Intel 82599, X520, X540, X550 | 5.x |
| `i40e` | Intel X710, XL710, XXV710 | 5.x |
| `ice` | Intel E810 | 5.5+ |
| `igb` | Intel i350 T2 (reference HW) | **6.17** |
| `igc` | Intel I225/I226 | 6.x |
| `virtio_net` | QEMU/KVM | varies |
[//]: # (![AI 攻擊偵測介面]&#40;.github/images/aiDetection.png&#41;)
Check with `ethtool -i <iface>` before deploying. 8 GB RAM minimum, 16 GB+ for high-traffic.
[//]: # (- AI-based attack detection engine)
## Build
## System Features
- **High Performance** - Low-latency packet processing with minimal network performance impact
- **User-Friendly** - Cross-platform web management interface with intuitive operation
- **Reliability** - Hardware-accelerated processing ensures stable operation
- **Scalability** - Modular design supports functional expansion
## System Requirements
NetGuardia requires the combination of a kernel with eBPF support and a NIC driver
that implements **AF_XDP** on that kernel. There is no single "minimum kernel
version" — it depends on which NIC driver you use.
- **Linux** with eBPF + AF_XDP support for your NIC driver. Any modern distribution
(Ubuntu 22.04+, Debian 12+, RHEL 9+, Fedora recent) is fine as long as the driver
matrix below lines up.
- **Dual-port NIC** with an AF_XDP-capable driver (see matrix).
- **Root / sudo** access for eBPF program loading.
### NIC driver / kernel matrix (AF_XDP)
| Driver | NIC family (examples) | Min kernel for AF_XDP |
|--------|-----------------------|------------------------|
| mlx5 | Mellanox ConnectX-4/5/6/7 | 5.x (early) |
| ixgbe | Intel 82599, X520, X540, X550 | 5.x |
| i40e | Intel X710, XL710, XXV710 | 5.x |
| ice | Intel E810 | 5.5+ |
| igb | **Intel i350 T2** (reference hardware) | **6.17** |
| igc | Intel I225/I226 | 6.x |
| virtio_net | QEMU/KVM virtual NICs | varies; AF_XDP is limited |
If you are using the reference Intel i350 T2, you need Linux 6.17 or newer because
igb AF_XDP support landed in that release. On a kernel older than 6.17 the system
will still build, but `ingress`/`egress` setup will fail at runtime when AF_XDP
binding is attempted — check driver support with `ethtool -i <iface>` and confirm
against the matrix above before deploying.
## Hardware Compatibility
- Network Interface: dual-port NIC with an AF_XDP-capable driver on your kernel
(see matrix above). Intel i350 T2 is the reference hardware.
- CPU: multi-core recommended; XDP scales with RX queue count.
- Memory: 8 GB minimum, 16 GB+ for high-traffic environments.
NetGuardia is not limited to embedded platforms — it runs on standard server
hardware, virtual machines, or dedicated appliances as long as the driver/kernel
requirement above is met.
```sh
cargo build --release --package net-guardia
sudo ./target/release/net-guardia
# open http://<host>:8080 — setup wizard issues the admin password on first boot
```
Systemd unit: [`deploy/netguardia.service`](deploy/netguardia.service).

View File

@ -1,6 +0,0 @@
# metric_direction: higher_is_better
iteration commit metric delta guard status description
0 4216906 91.3 0.0 - baseline v4 model — 91.3% accuracy, Normal FPR 29.3%
1 4216906 77.9 -13.4 - keep v5: 10 classes, danger weights, FPR 3.0% (from 29.3%), macro F1 0.804
2 4216906 83.4 +5.5 - keep v6: class_loss=1.0, focal_gamma=2.0, patience=40. Macro F1 0.848, FPR 3.0%
3 4216906 86.4 +3.0 - keep v7: wider model 384→256→128 (638K), Recon+0.104, Crypto collapsed to 0
Can't render this file because it has a wrong number of fields in line 2.