Network Traffic Visualization with Submarine Cable Overlay
NetTrace Map is a web-based animated map that shows your network traffic flowing across the world in real time. It collects NetFlow data from OPNsense (or any NetFlow v5/v9 exporter), geolocates the endpoints, and renders animated packets traveling along great-circle arcs over a dark-themed world map with submarine cable overlays.
- Real-time NetFlow collection — UDP listener for NetFlow v5 and v9 (IPFIX) packets
- Animated packet visualization — Dots travel along great-circle arcs between source and destination
- Submarine cable overlay — TeleGeography submarine cable routes displayed on the map
- Pre-configured infrastructure — Your OVH BHS/YYZ servers, home network, and internal VMs are pre-mapped
- MaxMind GeoLite2 geolocation — Unknown IPs are geolocated using the free GeoLite2-City database
- Protocol color-coding — BGP (purple), HTTP/HTTPS (green), SSH (orange), game traffic (blue), DNS (yellow)
- BGP visualization — Persistent peering lines and animated BGP UPDATE messages (configure once you have an ASN)
- Live stats panel — Total flows, bandwidth, protocol breakdown, top destinations
- Dark theme — Clean, professional dark UI using CartoDB Dark Matter tiles
- Fully self-hosted — No cloud dependencies, runs entirely on your infrastructure
┌──────────────┐ NetFlow v5/v9 ┌──────────────────┐ WebSocket ┌────────────────┐
│ OPNsense │ ──────────────────────► │ FastAPI Backend │ ─────────────────► │ Web Frontend │
│ (Router) │ UDP :2055 │ (NetFlow + WS) │ JSON flows │ (Leaflet Map) │
└──────────────┘ └──────────────────┘ └────────────────┘
│ │
┌───────┴───────┐ ┌───────┴───────┐
│ MaxMind │ │ Submarine │
│ GeoLite2 │ │ Cable Data │
│ (local mmdb) │ │ (GeoJSON) │
└───────────────┘ └───────────────┘
git clone https://github.com/Dabblecraft2DevTeam/nettrace-map.git
cd nettrace-map
# Create virtual environment
python3 -m venv venv
source venv/bin/activate
# Install backend dependencies
pip install -r backend/requirements.txtYou need a free MaxMind license key:
- Sign up at maxmind.com
- Get your license key from your account
- Run the download script:
export MAXMIND_LICENSE_KEY="your_key_here"
./download_geolite2.shThe database will be saved to data/GeoLite2-City.mmdb.
Note: Without the GeoLite2 database, only pre-configured IPs will be accurately geolocated. Unknown IPs will default to the OVH BHS area.
cd backend
python server.pyOr with uvicorn directly:
uvicorn backend.server:app --host 0.0.0.0 --port 8000 --reloadNavigate to http://localhost:8000 in your browser.
The server starts in demo mode by default, generating simulated traffic between your pre-configured machines so you can see the visualization immediately.
Edit backend/config.py to update your machine IPs and locations:
MACHINES = [
Machine(
name="OVH BHS Datacenter",
hostname="ovh-bhs",
ip="YOUR.BHS.PUBLIC.IP", # ← Replace with actual IP
lat=45.31,
lon=-73.87,
role="XCP-NG Host / Factions / DB / Proxy / Router / XOCE",
location="Beauharnois, Quebec, Canada",
),
# ... add more machines
]| Variable | Default | Description |
|---|---|---|
NETTRACE_NF_HOST |
0.0.0.0 |
NetFlow collector listen address |
NETTRACE_NF_PORT |
2055 |
NetFlow collector UDP port |
NETTRACE_DEMO |
1 |
Enable demo mode (simulated flows) — set to 0 for production |
Once you have NetFlow data flowing from OPNsense:
export NETTRACE_DEMO=0
python backend/server.pySee opnsense-netflow-guide.md for step-by-step instructions on configuring OPNsense to export NetFlow data to NetTrace Map.
To enable BGP visualization:
- Obtain an ASN from ARIN
- Edit
backend/config.py:MY_ASN = 12345 # Your ARIN ASN MY_ASN_LAT = 45.31 MY_ASN_LON = -73.87 BGP_PEERS = [ BGPPeer(asn=16276, name="OVH AS", lat=45.31, lon=-73.87, location="OVH BHS"), BGPPeer(asn=14061, name="DigitalOcean", lat=40.71, lon=-74.00, location="New York, USA"), ]
- Restart the server — BGP peering lines will appear on the map
nettrace-map/
├── backend/
│ ├── server.py # FastAPI + WebSocket + NetFlow collector
│ ├── geo.py # MaxMind GeoLite2 geolocation
│ ├── config.py # Pre-configured machines, IPs, BGP peers
│ └── requirements.txt # Python dependencies
├── frontend/
│ ├── index.html # Main page with Leaflet map
│ ├── style.css # Dark theme styling
│ └── app.js # WebSocket client, animation logic, map rendering
├── data/
│ ├── cables.geojson # Submarine cable routes (TeleGeography data)
│ ├── landing_points.geojson # Submarine cable landing points
│ └── GeoLite2-City.mmdb # MaxMind database (download separately)
├── download_geolite2.sh # Script to fetch GeoLite2 database
├── opnsense-netflow-guide.md # OPNsense configuration guide
├── README.md
└── .gitignore
- Submarine cables: TeleGeography Submarine Cable Map data via lintaojlu/submarine_cable_information and shimizu's gist
- Geolocation: MaxMind GeoLite2 (free, requires license key)
- Map tiles: CartoDB Dark Matter (free, OSM-based)
| Component | Technology |
|---|---|
| Backend | Python 3.11+, FastAPI, uvicorn |
| NetFlow | Built-in v5/v9 parser (NetFlow UDP collector) |
| Geolocation | MaxMind GeoLite2 + geoip2 Python library |
| Frontend | HTML5, vanilla JavaScript, Leaflet.js |
| Map tiles | CartoDB Dark Matter (OSM) |
| Real-time | WebSocket (FastAPI native) |
- Check that demo mode is enabled (
NETTRACE_DEMO=1) - Check WebSocket connection in browser console
- Verify the backend is running and accessible
- Run
./download_geolite2.shwith a valid license key - Check that
data/GeoLite2-City.mmdbexists - Verify
geoip2is installed:pip install geoip2
- Verify OPNsense NetFlow export points to this server's IP and port 2055
- Check firewall rules allow UDP 2055 inbound
- Test with
nc -ul 2055on the server to verify packets arrive
MIT — See LICENSE file for details.
- TeleGeography for submarine cable data
- MaxMind for GeoLite2 geolocation database
- CartoDB for dark theme map tiles
- Leaflet for the mapping library