See what ASNs your network is talking to by analyzing your flow data.
Single binary that collects NetFlow v5/v9 and IPFIX flows, maps destination and source IPs to ASNs using a BGP-derived database, and serves a live monitoring dashboard.
just setup # install frontend dependencies
just build # build frontend + release binary
./target/release/netraOpen http://localhost:1337 for the dashboard. Point your NetFlow/IPFIX exporter at UDP port 2055.
netra [OPTIONS]
Options:
-f, --flow-port <FLOW_PORT> UDP port for NetFlow/IPFIX packets [default: 2055]
-p, --http-port <HTTP_PORT> TCP port for the HTTP dashboard and SSE API [default: 1337]
-d, --db-path <DB_PATH> Path to the ASN database file [default: asndb.netra next to binary]
--skip-asns <ASN,ASN,...> Exclude ASNs from charts and lists (comma-separated)
-h, --help Print help
| Port | Protocol | Purpose |
|---|---|---|
| 1337 | TCP/HTTP | Web dashboard + SSE API |
| 2055 | UDP | NetFlow v5/v9, IPFIX |
- Multi-core UDP processing with SO_REUSEPORT
- NetFlow v5, v9, and IPFIX with template caching
- ASN database from iptoasn.com (auto-downloaded, refreshed daily)
- 5-second tumbling windows with proportional flow attribution
- Upload (by destination ASN) and download (by source ASN) tracking
- Real-time dashboard with Solarized Dark theme
- Per-session SSE streams with configurable window and top-N
just dev-backend # Rust server on :1337
just dev-frontend # Vite dev server on :5173
just test # run all tests
just lint # clippy + eslint
just check # full CI pipelinedocker build -t netra .
docker run -p 1337:1337 -p 2055:2055/udp netraWhen running netra on against your router, your own ASN will dominate the charts. Use --skip-asns to exclude it:
netra --skip-asns 12345
netra --skip-asns 12345,67890 # exclude multiple ASNsTo configure this in a systemd unit, edit the service with systemctl edit netra and override ExecStart:
# /etc/systemd/system/netra.service.d/override.conf
[Service]
ExecStart=
ExecStart=/usr/bin/netra --skip-asns 12345Then reload and restart:
systemctl daemon-reload
systemctl restart netraNetra exposes a Prometheus-compatible metrics endpoint at /metrics. It uses the same windowed aggregation as the dashboard, returning gauge metrics in the Prometheus text exposition format.
GET /metrics?window=60&top=25
| Parameter | Default | Range | Description |
|---|---|---|---|
window |
60 | 5-300 | Lookback window in seconds |
top |
25 | 1-100 | Number of top ASNs per direction per VLAN |
Malformed query parameters silently fall back to defaults.
Totals per VLAN and direction (labels: vlan, direction):
| Metric | Description |
|---|---|
netra_total_bytes |
Total bytes in the window |
netra_total_packets |
Total packets in the window |
netra_total_flows |
Total flows in the window |
Per-ASN breakdown (labels: vlan, direction, asn, name, country):
| Metric | Description |
|---|---|
netra_asn_bytes |
Bytes attributed to this ASN |
netra_asn_packets |
Packets attributed to this ASN |
netra_asn_flows |
Flows attributed to this ASN |
netra_asn_bytes_percent |
Percentage of total bytes |
netra_asn_packets_percent |
Percentage of total packets |
netra_asn_flows_percent |
Percentage of total flows |
Each VLAN produces its own set of metrics. A vlan="total" series aggregates across all VLANs. The --skip-asns flag applies to Prometheus output the same way it does to the dashboard.
scrape_configs:
- job_name: netra
scrape_interval: 30s
metrics_path: /metrics
params:
window: ['60']
top: ['25']
static_configs:
- targets: ['localhost:1337']UDP :2055 → N listener threads (SO_REUSEPORT)
→ Parse v5/v9/IPFIX → Extract (dst_ip, src_ip, vlan, bytes, timestamps)
→ ASN lookup (ip_network_table trie, ~100ns)
→ DashMap windows (upload by dst, download by src)
→ 5-sec freeze → Arc<FrozenWindow> history (60 windows = 5 min)
→ SSE /api/events (800ms push, per-session config)
→ React dashboard (Recharts, Solarized Dark)
MIT
