# NetMon v3 — Setup Guide

Network observatory for MikroTik/RouterOS networks. FastAPI + Chart.js dashboard that
polls the RouterOS API read-only and collects NetFlow v9 for per-client, per-destination
and per-app traffic accounting.

**Who this is for:** an agent (or human) setting NetMon up on a home network with a
MikroTik router. Read the whole thing before starting; step 2 (router side) is the part
people get wrong.

---

## What you get

- **WAN throughput graph** — live up/down, 7 days of samples + daily totals
- **Per-client accounting** — grouped by MAC (so IPv6 privacy addresses don't fragment
  the picture), 32 days retention
- **"Who is the network talking to?"** — per-destination reverse DNS + ASN owner
  (via Team Cymru over DNS — free, no API key)
- **Traffic classification** — port/protocol → app label, rendered as a donut
- **Per-client detail modal** — click any client/talker row for its own throughput
  graph, top destinations and app breakdown
- **New-device watchdog** — optional; new MACs on the LAN land in an event feed
- **Threat-feed tagging** — destinations matched against Feodo Tracker + Spamhaus DROP
- **MAC vendor lookup** — Wireshark `manuf` database, auto-downloaded

Data lives in a local SQLite file. Nothing is sent anywhere except the DNS lookups
for rDNS/ASN enrichment and the public blocklist/manuf downloads.

---

## Requirements

**A machine on the LAN that stays on** — a small Linux box, VM, Raspberry Pi, or an
always-on server. This is *not* meant to run on the router itself.

- Linux (built and tested on Ubuntu 24.04; any modern distro with Python 3.11+ works)
- Python 3.11 or newer, `python3-venv`
- `dnsutils` (provides `dig`, required for the rDNS/ASN enrichment)
- Disk: budget **~1 GB per month** of history on a busy home network. The home instance
  here sits around 100 MB; a datacenter uplink instance grew to 7 GB. Retention is
  capped (7d detailed flows / 32d client totals) so it plateaus rather than grows
  forever.
- A MikroTik router running RouterOS 7.x with the API service available

Install the OS packages:

```bash
sudo apt update
sudo apt install -y python3-venv python3-pip dnsutils
```

---

## Step 1 — Install the app

Unpack the tarball into the home directory of a normal (non-root) user and build a venv:

```bash
tar xzf netmon-v3.tar.gz -C ~/
cd ~/netmon
python3 -m venv venv
./venv/bin/pip install -r requirements.txt
```

That's the whole install. `app.py`, `static/`, and later `netmon.db` + `manuf` all live
in this one directory.

---

## Step 2 — Router configuration (RouterOS)

Two things are needed on the router: a **read-only API user** and **NetFlow export**.

Replace `<MONITOR_IP>` with the LAN IPv4 address of the machine from step 1, and pick a
strong password.

### 2a. Read-only API user, locked to the monitor host

```
/user group add name=netmon-ro policy=read,api,winbox
/user add name=netmon group=netmon-ro address=<MONITOR_IP> password=<STRONG_PASSWORD>
/ip service set api address=<MONITOR_IP> disabled=no
```

`policy=read,api` means the account cannot change anything — it can only read. Keeping
`address=` set on both the user and the API service means only the monitor box can even
attempt to log in.

### 2b. NetFlow v9 export

```
/ip traffic-flow set enabled=yes interfaces=bridge active-flow-timeout=1m
/ip traffic-flow target add dst-address=<MONITOR_IP> port=2055 version=9
```

Use whichever interface carries LAN traffic — usually `bridge`. Set
`active-flow-timeout=1m` or long-running transfers won't be reported until they finish,
which makes the graphs look dead.

### 2c. Firewall

If the router filters traffic to the monitor box, allow:

- monitor → router TCP **8728** (the API)
- LAN → monitor TCP **8088** (the dashboard)

Place these rules **before** any general drop/isolation rules. Order matters in
RouterOS; a rule after the drop does nothing.

### ⚠️ Three gotchas that will waste your afternoon

1. **IPv4 fasttrack hides flows.** If the router has a
   `action=fasttrack-connection` rule, fastracked IPv4 connections bypass the flow
   accounting and per-client IPv4 numbers will be badly incomplete. Disable it for full
   visibility:
   ```
   /ip firewall filter disable [find where action=fasttrack-connection]
   ```
   CPU impact on an RB5009-class router is negligible (~2%). Re-enable with `enable`
   if you'd rather have the offload than the data. IPv6 is unaffected either way.

2. **The flow target must be an IPv4 address.** RouterOS accepts an IPv6 target in
   `/ip traffic-flow target` without complaint and then **silently never sends
   anything**. If flows aren't arriving, this is why.

3. **Hardware offload can hide traffic from the CPU** on switch-chip-backed ports.
   If a port's traffic seems invisible, `hw=no` on that bridge port forces it through
   the CPU.

---

## Step 3 — Configure NetMon

Create `~/netmon/.env`:

```ini
NM_ROUTER=192.168.1.1
NM_USER=netmon
NM_PASS=<STRONG_PASSWORD>
NM_WAN=ether1
NM_POLL=10
NM_TITLE=Home
NM_WATCH=1
NM_PREFIX=2001:db8:1234::/48
NM_LOCAL_V4=192.168.0.0/16
NM_LOCAL_V6=2001:db8:1234::/48
```

| Variable | Meaning |
|---|---|
| `NM_ROUTER` | Router IP reachable from the monitor box |
| `NM_PORT` | RouterOS API port (default `8728`) |
| `NM_USER` / `NM_PASS` | The read-only API credentials from step 2a |
| `NM_WAN` | WAN interface name as the router calls it (`ether1`, `sfp-sfpplus1`, …) |
| `NM_POLL` | Router poll interval in seconds (default `10`) |
| `NM_FLOW_PORT` | UDP port to receive NetFlow on (default `2055`) |
| `NM_TITLE` | Label shown in the dashboard header |
| `NM_PREFIX` | Your IPv6 prefix, displayed in the header — cosmetic |
| `NM_WATCH` | `1` enables the new-device watchdog, `0` disables |
| `NM_LOCAL_V4` / `NM_LOCAL_V6` | **Important:** your own networks, comma-separated. This is how NetMon tells "local" from "remote". Wrong values here and the destination/talker views will be nonsense. |

Then lock the file down, since it holds the router password:

```bash
chmod 600 ~/netmon/.env
```

---

## Step 4 — Run it as a service

Create `/etc/systemd/system/netmon.service` (adjust the user and paths):

```ini
[Unit]
Description=NetMon dashboard
After=network-online.target
Wants=network-online.target

[Service]
User=<YOUR_USER>
WorkingDirectory=/home/<YOUR_USER>/netmon
EnvironmentFile=/home/<YOUR_USER>/netmon/.env
ExecStart=/home/<YOUR_USER>/netmon/venv/bin/uvicorn app:app --host 0.0.0.0 --port 8088
Restart=always
RestartSec=5

[Install]
WantedBy=multi-user.target
```

```bash
sudo systemctl daemon-reload
sudo systemctl enable --now netmon
systemctl status netmon
journalctl -u netmon -f
```

Dashboard: **http://<MONITOR_IP>:8088**

---

## Step 5 — Verify

Work through these in order; each one isolates a different failure.

```bash
# 1. Service alive, no tracebacks
journalctl -u netmon -n 50

# 2. Router API reachable
nc -zv <ROUTER_IP> 8728

# 3. NetFlow packets actually arriving (should print packets within ~1 min)
sudo tcpdump -ni any udp port 2055

# 4. Enrichment prerequisite
dig +short -x 1.1.1.1
```

**Symptom → cause:**

- Dashboard loads but WAN graph is flat → `NM_WAN` is the wrong interface name
- Clients listed but no traffic numbers → NetFlow not arriving (step 3 above): check
  the flow target, the IPv4-only gotcha, and fasttrack
- IPv4 traffic much lower than reality → fasttrack still enabled
- No destination names or ASN owners → `dnsutils` missing, or outbound DNS blocked
- `login failure` in the log → API user password, or the `address=` lock doesn't match
  the monitor box's actual source IP

---

## Notes on running more than one instance

Each instance needs its own directory, its own `.env`, its own port, its own
`NM_FLOW_PORT`, and its own systemd unit. The venv can be shared. That's how the home
and datacenter routers are monitored side by side here (`:8088` and `:8089`).

---

## Security

- The dashboard has **no authentication**. Keep it on the LAN. Do not port-forward it to
  the internet — if remote access is needed, use WireGuard or a VPN, or restrict by
  source IP at the firewall.
- The API account is read-only and host-locked; keep it that way.
- `.env` contains the router password → `chmod 600`, and don't commit it anywhere.
- Monitoring a network means recording who talks to what. Everyone on that network
  should know it's running.
