Skip to content

humanauction/net-net

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

287 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

net-net

CI/CD Pipeline codecov

Real-Time Network Monitor with Web Dashboard

Overview

A high-performance, modular network monitoring daemon written in C++17 that captures packets, tracks active connections, and aggregates bandwidth and protocol statistics in real-time. Features a modern web-based dashboard with live visualizations, session-based authentication, and a REST API for programmatic access.

Key Features:

  • πŸ“Š Real-time bandwidth visualization (D3.js line charts)
  • πŸ” Secure session-based authentication with bcrypt
  • 🌐 Modern web dashboard with live updates
  • πŸ“ˆ Protocol breakdown pie charts (TCP/UDP/OTHER)
  • πŸ”Œ Active connection tracking and display
  • πŸ›‘οΈ Privilege dropping for security
  • πŸ“¦ SQLite persistence for historical data
  • ⚑ Sub-second latency metrics

πŸš€ Quick Start

Prerequisites

  • macOS/Linux with libpcap installed
  • C++17 compiler (clang++ or g++)
  • CMake 3.16+
  • Python 3.x with pip (for integration tests)
  • Root/sudo access (for packet capture)
  • envsubst (usually included with gettext)

Build & Run

# Clone repository
git clone https://github.com/humanauction/net-net.git
cd net-net

# Build daemon
make clean
make build

# Start daemon with live capture (requires sudo)
make demon

# Or start with environment variables for your interface
NETNET_IFACE=en0 NETNET_BPF_FILTER="" make demon

# Open dashboard in browser
open http://localhost:8082

Using the Makefile

The project includes a comprehensive Makefile with the following targets:

Command Description
make Build all binaries
make build Build the project
make rebuild Clean and rebuild
make demon Run daemon with live capture (requires sudo)
make demon-stop Stop running daemon
make demon-ol Run daemon with PCAP file replay
make test Run ALL tests (C++ + Python)
make test-cpp Run C++ tests only
make test-python Run Python integration tests only
make coverage Generate coverage report
make coverage-html Generate HTML coverage report
make clean Clean all build artifacts
make venv Set up Python virtual environment
make config-ci Generate CI config from template

Environment Variables

Configure capture settings via environment variables:

export NETNET_IFACE=en0          # Network interface (default: en0)
export NETNET_USER=nobody        # User for privilege drop
export NETNET_GROUP=nobody       # Group for privilege drop
export NETNET_BPF_FILTER=""      # BPF filter (empty = capture all)

Default Credentials

  • Username: admin
  • Password: adminpass

⚠️ Change default passwords in production! See Configuration section.


πŸ“Έ Screenshots

Dashboard Overview

Dashboard Dashboard Dashboard Real-time bandwidth monitoring with protocol breakdown and active connections

Login Screen

Login Secure session-based authentication


πŸ—οΈ Architecture

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                  Web Dashboard                      β”‚
β”‚         (HTML/CSS/JavaScript + D3.js)               β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                       β”‚ REST API (HTTP)
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                NetMonDaemon (C++)                   β”‚
β”‚   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”‚
β”‚   β”‚  SessionManager (bcrypt + SQLite)           β”‚   β”‚
β”‚   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β”‚
β”‚   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”‚
β”‚   β”‚  REST API (cpp-httplib)                     β”‚   β”‚
β”‚   β”‚  β€’ /login, /logout, /metrics                β”‚   β”‚
β”‚   β”‚  β€’ /control/{start,stop,reload}             β”‚   β”‚
β”‚   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β”‚
β”‚   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”‚
β”‚   β”‚  StatsAggregator (Metrics)                  β”‚   β”‚
β”‚   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β”‚
β”‚   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”‚
β”‚   β”‚  ConnectionTracker (Flow State)             β”‚   β”‚
β”‚   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β”‚
β”‚   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”‚
β”‚   β”‚  Parser (Ethernet/IPv4/TCP/UDP/ICMP)        β”‚   β”‚
β”‚   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β”‚
β”‚   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”‚
β”‚   β”‚  PcapAdapter (libpcap wrapper)              β”‚   β”‚
β”‚   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                      β”‚
              β”Œβ”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”
              β”‚     Network     β”‚
              β”‚     Interface   β”‚
              β”‚   (en0, eth0)   β”‚
              β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

See docs/design.md for detailed architecture documentation.


πŸ“‹ Project Structure

net-net/
β”œβ”€β”€ src/                                # C++ source code
β”‚   β”œβ”€β”€ core/                           # Core monitoring logic
β”‚   β”‚   β”œβ”€β”€ Parser.{cpp,h}              # Packet parsing (Ethernetβ†’IPβ†’TCP/UDP)
β”‚   β”‚   β”œβ”€β”€ ConnectionTracker.{cpp,h}   # Flow tracking
β”‚   β”‚   β”œβ”€β”€ StatsAggregator.{cpp,h}     # Metrics aggregation
β”‚   β”‚   β”œβ”€β”€ StatsPersistence.{cpp,h}    # SQLite storage
β”‚   β”‚   β”œβ”€β”€ SessionManager.{cpp,h}      # Authentication
β”‚   β”‚   └── PacketMeta.h                # Packet metadata structures
β”‚   β”œβ”€β”€ net/                            # Network adapters
β”‚   β”‚   └── PcapAdapter.{cpp,h}         # libpcap wrapper
β”‚   └── daemon/                         # Daemon implementation
β”‚       β”œβ”€β”€ Main.cpp                    # Entry point
β”‚       β”œβ”€β”€ NetMonDaemon.{cpp,h}        # Main daemon class
β”‚       └── httplib.h                   # HTTP server (header-only)
β”œβ”€β”€ www/                                # Web dashboard
β”‚   β”œβ”€β”€ index.html                      # Dashboard UI
β”‚   β”œβ”€β”€ style.css                       # Styling
β”‚   └── app.js                          # JavaScript (D3.js + Chart.js)
β”œβ”€β”€ include/net-net/vendor/             # Third-party code
β”‚   β”œβ”€β”€ bcrypt.{cpp,h}                  # Password hashing
β”‚   └── uuid_gen.{cpp,h}                # Session token generation
β”œβ”€β”€ tests/                              # Test suites
β”‚   β”œβ”€β”€ unit/                           # C++ unit tests (GoogleTest)
β”‚   β”œβ”€β”€ integration/                    # Python integration tests
β”‚   └── fixtures/                       # Test PCAP files
β”œβ”€β”€ docs/                               # Documentation
β”‚   β”œβ”€β”€ design.md                       # Architecture overview
β”‚   β”œβ”€β”€ api.md                          # REST API reference
β”‚   β”œβ”€β”€ EntityRelationshipDataModel.md  # Database schema
β”‚   β”œβ”€β”€ packetFlowDiagram.md            # Packet processing flow
β”‚   └── securityChecklistReview.md      # Security audit
β”œβ”€β”€ examples/                           # Configuration templates
β”‚   β”œβ”€β”€ sample-config.yaml              # Template with env vars
β”‚   └── sample-config.ci.yaml           # Generated CI config
β”œβ”€β”€ CMakeLists.txt                      # Build configuration
β”œβ”€β”€ Makefile                            # Build wrapper
└── README.md                           # This file

βš™οΈ Configuration

Configuration uses YAML with environment variable substitution. The Makefile generates sample-config.ci.yaml from sample-config.yaml using envsubst.

Interface Settings

interface:
  name: "${NETNET_IFACE}"         # Network interface (e.g., en0, eth0)
  promiscuous: true               # Capture all packets on segment
  snaplen: 65535                  # Max bytes per packet
  timeout_ms: 1000                # Read timeout
  bpf_filter: "${NETNET_BPF_FILTER}"  # BPF filter (empty = all traffic)

Offline Mode (PCAP Replay)

offline:
  file: "/path/to/capture.pcap"   # Uncomment to replay PCAP file

API Settings

api:
  enabled: true
  host: "0.0.0.0"                 # Listen address
  port: 8082                      # Listen port
  token: "your_secure_token"      # For /control endpoints
  session_expiry: 3600            # Session timeout (seconds)

User Credentials

users:
  - username: "admin"
    password: "$2a$12$..."        # bcrypt hash
  - username: "user"
    password: "$2a$12$..."

Generate bcrypt hashes:

python3 -c "import bcrypt; print(bcrypt.hashpw(b'yourpassword', bcrypt.gensalt()).decode())"

Connection Tracking

tracking:
  idle_timeout: 300               # Remove idle connections after N seconds
  cleanup_interval: 60            # Cleanup check interval

Statistics

stats:
  window_size: 60                 # Aggregation window (seconds)
  history_depth: 24               # Number of windows to retain

Database

database:
  path: "/tmp/netnet.db"          # SQLite file path
  retention_days: 7               # Data retention period

Privilege Drop (Security)

privilege:
  drop: true
  user: "${NETNET_USER}"
  group: "${NETNET_GROUP}"

Logging

logging:
  level: "debug"                  # debug, info, warn, error
  file: ""                        # Empty = stdout
  timestamps: true

πŸ”Œ REST API

Authentication Endpoints

POST /login

Authenticate user and receive session token.

Request:

{
  "username": "admin",
  "password": "adminpass"
}

Response:

{
  "token": "550e8400-e29b-41d4-a716-446655440000",
  "username": "admin",
  "expires_in": 3600
}

POST /logout

Invalidate session token.

Headers:

X-Session-Token: <token>

Metrics Endpoints

GET /metrics

Retrieve current network statistics.

Headers:

X-Session-Token: <token>

Response:

{
  "timestamp": 1732656147000,
  "window_start": 1732656140,
  "total_bytes": 1048576,
  "total_packets": 256,
  "bytes_per_second": 104857,
  "protocol_breakdown": {
    "TCP": 900000,
    "UDP": 148576,
    "OTHER": 0
  },
  "active_flows": [
    {
      "src_ip": "192.168.1.100",
      "src_port": 54321,
      "dst_ip": "142.250.80.46",
      "dst_port": 443,
      "protocol": "TCP",
      "bytes": 15360,
      "packets": 45
    }
  ]
}

Control Endpoints

POST /control/start

Start packet capture.

POST /control/stop

Stop packet capture.

POST /control/reload

Reload configuration file.

Headers (all control endpoints):

Authorization: Bearer <api_token>

See docs/api.md for complete API documentation.


πŸ§ͺ Testing

Run All Tests

make test

C++ Unit Tests Only

make test-cpp

Python Integration Tests Only

make test-python

Coverage Reports

# Terminal summary
make coverage

# HTML report (opens in browser)
make coverage-html

Test Suites:

  • test_parser - Packet parsing logic
  • test_pcap_adapter - Capture adapter
  • test_connection_tracker - Flow tracking
  • test_stats_aggregator - Metrics aggregation
  • test_session_manager - Authentication

πŸ”’ Security

Implemented Safeguards

  • βœ… Privilege Dropping: Daemon drops to configured user/group after opening capture device
  • βœ… bcrypt Password Hashing: All passwords hashed with salt
  • βœ… Session Tokens: UUID-based tokens, SQLite-backed, configurable expiry
  • βœ… Rate Limiting: Control endpoints limited to 1 request per 2 seconds per IP
  • βœ… Input Validation: BPF filter sanitization, JSON schema validation
  • βœ… No Credential Logging: Passwords never logged or displayed
  • βœ… HTTPS Ready: Designed for reverse proxy (nginx/Caddy) with TLS

Production Checklist

  • Change default passwords
  • Use strong API tokens (32+ characters)
  • Enable HTTPS via reverse proxy
  • Restrict API access by IP/firewall
  • Run daemon as dedicated user
  • Enable audit logging
  • Review docs/securityChecklistReview.md

πŸ› Troubleshooting

No Metrics/Data Showing

# Check you're capturing on the right interface
ifconfig | grep -B1 "inet "

# Run with empty BPF filter to capture ALL traffic
NETNET_IFACE=en0 NETNET_BPF_FILTER="" make demon

Permission Denied

# Packet capture requires root
sudo ./build/netnet-daemon --config examples/sample-config.ci.yaml

# Or use make target (includes sudo)
make demon

Port Already in Use

# Kill existing daemon
sudo pkill netnet-daemon

# Check what's using the port
lsof -i :8082

Interface Not Found

# List available interfaces (macOS)
ifconfig | grep -E "^[a-z]" | cut -d: -f1

# Common interfaces:
# macOS WiFi: en0
# macOS Ethernet: en1
# Linux: eth0, wlan0
# Loopback: lo0 (macOS), lo (Linux)

Dashboard Shows "Connection Refused"

  1. Check daemon is running: ps aux | grep netnet-daemon
  2. Check port: lsof -i :8082
  3. Verify config has host: "0.0.0.0" not "localhost"

Session Token Invalid

# Clear browser localStorage (F12 console)
localStorage.clear()

πŸ“š Documentation


πŸ› οΈ Development Roadmap

βœ… Stage 0: Planning & Design (Complete)

  • Architecture design
  • Entity-relationship diagram
  • Packet flow diagram
  • Config schema definition

βœ… Stage 1: Core Capture Layer (Complete)

  • PcapAdapter implementation
  • BPF filter validation
  • Unit tests with mocked adapter
  • Integration tests with PCAP files

βœ… Stage 2: Parser & Connection Tracker (Complete)

  • Multi-protocol parser (Ethernet/IPv4/IPv6/TCP/UDP/ICMP)
  • 5-tuple flow tracking
  • Connection state machine
  • Per-flow throughput counters

βœ… Stage 3: Stats Aggregation & Persistence (Complete)

  • Rolling-window metrics
  • In-memory ring buffer
  • SQLite persistence
  • Configurable aggregation windows

βœ… Stage 4: CLI Daemon & REST API (Complete)

  • NetMonDaemon headless mode
  • REST API with cpp-httplib
  • Session-based authentication
  • Rate limiting
  • Privilege dropping
  • Configurable logging

βœ… Stage 5: Web Dashboard & UI (Complete)

  • HTML/CSS/JavaScript frontend
  • Real-time bandwidth chart (D3.js)
  • Protocol breakdown pie chart (Chart.js)
  • Active connections table
  • Login/logout UI
  • Session token management

βœ… Stage 6: Hardening, CI, Docs (Complete)

  • CI/CD pipeline (GitHub Actions)
  • Code coverage reporting (gcov/gcovr)
  • Comprehensive Makefile
  • Environment variable configuration
  • Documentation updates

🀝 Contributing

Contributions welcome! Please:

  1. Fork the repository
  2. Create a feature branch (git checkout -b feature/amazing-feature)
  3. Commit changes (git commit -m 'Add amazing feature')
  4. Push to branch (git push origin feature/amazing-feature)
  5. Open a Pull Request

Before submitting:

  • Run tests: make test
  • Check formatting: clang-format -i src/**/*.cpp src/**/*.h
  • Update documentation if needed

πŸ“ License

This project is licensed under the MIT License - see LICENSE file for details.


πŸ™ Acknowledgments


πŸ“§ Contact

About

Real-Time Network Monitor (C++)

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors