NetFlows von OpenWRT-Routern mit ntopng auswerten

Allgemein Linux

Nachdem ich meine ARM64-VM unter Proxmox zum Laufen gebracht hatte, konnte ich mich mit dem Thema NetFlows von OpenWRT in ntopng beschäftigen.

OpenWRT verwendet softflowd um NetFLows zu generieren, daher muss softflowd nur installiert und konfiguriert werden. Aus Performancegründen ist es jedoch nicht empfehlenswert, diese NetFlows direkt an ntopng zu senden. Die typische Konfiguration für ntopng verwendet nprobe als Zwischenschritt zwischen softflowd und ntopng. nprobe fungiert als NetFlow-Kollektor, der die Daten von softflowd empfängt und dann über das ZeroMQ-Protokoll an ntopng weiterleitet.

Ohne nprobe kann es zu Problemen bei der Darstellung und Aktualisierung der Flows in ntopng kommen. Durch Recherchen habe ich herausgefunden, dass Benutzer (von pfsense) berichteten, dass bei der direkten Verwendung von softflowd mit ntopng die Flows nicht korrekt aktualisiert wurden und nur für kurze Zeit sichtbar waren. nprobe bietet wichtige Funktionen zur Verarbeitung und Aufbereitung der NetFlow-Daten, bevor sie an ntopng weitergeleitet werden. Dies verbessert die Qualität und Nutzbarkeit der Daten in ntopng. Für den Einsatz von nprobe ist in der Regel eine Lizenz erforderlich, die nur für Universitäten und gemeinnützige Organisationen kostenlos ist. Diese kostet für Embedded Systeme wie Raspberry Pi knapp 100€, für X86 oder AMD64 CPUs das Dreifache – lebenslang (aber nur mit 1 Jahr Updateservice)! Deshalb habe ich mich entschlossen, die ARM-Architektur unter Intel-Proxmox zum Laufen zu bringen und die embedded nProbe dort zu installieren. Leider musste ich dann feststellen, das die nProbe-Paketquellen auf die Debian-Quellen für Raspberry Pi aufsetzen, also habe ich kurzer Hand eine neue ARM64-VM für Raspberry Pi OS aufgesetzt.

Vorbereitung

Öffne als erstes deine Proxmox-Shell, installiere die ARM64-Unterstützung und lade dir das Raspberry-Pi-OS herunter.

apt update
apt install pve-edk2-firmware-aarch64 qemu-utils
wget https://downloads.raspberrypi.com/raspios_lite_arm64/images/raspios_lite_arm64-2024-11-19/2024-11-19-raspios-bookworm-arm64-lite.img.xz

Leider gibt es das nicht direkt als ISO-Image, wie wir es für Proxmox benötigen, aber das wandeln wir uns einfach um:

xz -d 2024-11-19-raspios-bookworm-arm64-lite.img.xz
qemu-img convert -f raw 2024-11-19-raspios-bookworm-arm64-lite.img -O qcow2 2024-11-19-raspios-bookworm-arm64-lite.qcow2
qemu-img resize 2024-11-19-raspios-bookworm-arm64-lite.qcow2 30G

Da RaspberryOS UEFI voraussetzt, aber in dieser Form (noch) nicht lauffähig ist, müssen wir einen Workaround anwenden. Wir nutzen wie in meinem o.a. Tutorial für ARM-VM unter Proxmox das Debian-ARM64-ISO, um die VM initial zu booten und einige Dinge zu „verbiegen“. Dazu gehst du als erstes in deine Proxmox-ISO-Bibliothek und klickst auf „Download from URL“ (überspringe den Schritt, wenn du bereits ein DebianARM64-ISO heruntergeladen hast)

In das folgende Dialogfeld fügst du unter URL folgenden Link ein: https://cdimage.debian.org/debian-cd/current/arm64/iso-cd/debian-12.10.0-arm64-netinst.iso und klickst auf Query URL.

Und schon kann der Download beginnen:

Erstellen der ARM64-VM

Klicke auf „Create VM“ und vergib einen aussagekräftigen Namen:

Im OS-Tab wählst du „Do not use any media“

Im System-Tab wählst du OVMF (UEFI) als BIOS aus, entfernst den Haken bei „Add EFI Disk“ und änderst den SCSI Controller auf „VirtIO SCSI“ – also die Version ohne Single.

Lösche die vorgeschlagene Disk durch Klick auf den Papierkorb (ist hier schon passiert 🙂 ).

Im CPU-Tab klickst du auf das kleine Kreuz im Type-Feld und wechselst dadurch auf Default (kvm64). Ich empfehle dir ausreichend Cores auszuwählen, sonst wird die Wartezeit sehr lang.

Stelle sicher, das der Haken bei „Start after created“ nicht gesetzt ist, bevor du auf „Finish“ klickst.

Im Anschluss gehst du auf den Hardware-Tab und löscht das vorhandene CD/DVD-Drive. Als IDE wird das eh nicht funktionieren.

Jetzt wechselst du wieder auf die Proxmox-Shell und importierst das entpackte und umgewandelte RaspiI-mage von oben in deine neue VM. Ändere also ggf. die 102 in deine dreistellige VM-Nummer und passe ggf. das Ziel an (bei mir local-lvm, könnte bei dir auch nur local o.ä. sein (die TAB-Taste ist dein Freund)):

qm importdisk 102 /var/lib/vz/template/qcow/2024-11-19-raspios-bookworm-arm64-lite.qcow2 local-lvm

Das Ergebnis sollte dann so aussehen:

importing disk '/var/lib/vz/template/qcow/2024-11-19-raspios-bookworm-arm64-lite.qcow2' to VM 102 ...
  Logical volume "vm-102-disk-1" created.
transferred 0.0 B of 30.0 GiB (0.00%)
...
transferred 30.0 GiB of 30.0 GiB (100.00%)
unused0: successfully imported disk 'local-lvm:vm-102-disk-1'

Im Hardware-Tab deiner VM sollte jetzt eine neue „Unused Disk“ vorhanden sein, mache einen Doppelklick darauf:

Stelle sicher, das SCSI 0 ausgewählt ist und klicke auf Add.

ALs nächstes fügen wir das CD/DVD-Laufwerk mit dem Debian-ARM64-ISO hinzu, dies wird dann als SCSI 1 eingebunden:

Ab diesem Moment haben wir ein System mit dem RaspiOS-Image als SCSI 0 (HDD) und der Debian-ARM64-ISO als DVD-Laufwerk unter SCSI 1.

Jetzt ändern wir die Bootreihenfolge und stellen sicher, dass das DVD-Laufwerk das erste Boot-Laufwerk ist, net0 kannst du deaktivieren und SCSI0 kannst du schon mal aktivieren. Wichtig ist dann aber die Reihenfolge – DVD als erstes!

Dann öffnest du in der Proxmox-Shell mit nano /etc/pve/qemu-server/102.conf (ändere 102 in deine dreistellige VM-ID) den Editor, kommentiere die Zeile mit „vmgenid“ aus und füge die Zeile arch: aarch64 hinzu. Sollte da eine Zeile mit „cpu: “ beginndend sein, lösche diese.

Speichere und schließe die Datei (STRG-S, gefolgt von STRG-X) und starte die VM über den Start-Button in der Web-GUI oder qm start 102. Klicke dann zeitnah auf „>- Console“, dann öffnet sich ein neues Fenster. Im ersten Dialog wählst du „Advanced options…“

…gefolgt von „Rescue mode“.

Dann wird der Bildschirm schwarz, aber keine Sorge – du musst nur warten.

Nach einiger Wartezeit (kann durchaus 1 Minute werden) öffnet sich der gewohnte Dialog zur Auswahl von Sprache, Tastatur-Layout, Rechnername, Domäne (.internal), etc.

Dann kommt irgendwann die Frage nach dem Root-Dateisystem. Wenn du meiner Anleitung bislang sauber gefolgt bist, kannst du jetzt „/dev/sda2“ auswählen.

Dann wählst du „Execute a shell in /dev/sda2″…

…und klickst auf „Continue“:

Sobald sich die Konsole öffnet, kannst du folgendes Kommando absetzen

raspi-config --expand-rootfs

Wichtg! Jetzt klickst du auf den Reset-Button deiner ARM64-VM und zwingst diese somit zum Reboot.

Dann musst du leider die letzten Schritte alle wiederholen (advanced options, rescue mode, Sprache, Layout, /dev/sda2, execute shell). Sobald du wieder im Rescue-System der VM bist geht es weiter mit:

resize2fs /dev/sda2

Als nächstes ändern wir die Datei /etc/fstab ab:

nano /etc/fstab

Füge hier am Ende der Datei folgende Zeile hinzu und speichere und schließe im Anschluss die Datei wieder mit (STRG-S, STRG-X)

none    /sys/firmware/efi/efivars efivarfs defaults

Als nächstes installieren wir und den Bootloader für efi-64 und löschen im Anschluss nicht benötigte rpi-Images:

mount /boot/firmware
touch /boot/firmware/ssh
mount /sys/firmware/efi/efivars

Als vorletzten Schritt passt du den Bootloader an und aktivierst die neuen Einstellungen:

grub-install --efi-directory=/boot/firmware
update-grub2

Dann verlässt du die VM-Shell mit exit und wählst im folgenden Dialog „System neu starten“ aus:

Wenn die VM dann neu startet drückst du direkt im Anschluss mehrfach die ESC-Taste, um in das BIOS zu gelangen. Wähle dort den Boot Maintenance Manager aus:

Und prüfe, ob „debian“ in der Boot-Reihenfolge ganz oben steht. Wenn nicht ändere das entsprechend ab:

Sollte gar kein Eintrag für debian vorhanden sein, kannst du ihn an dieser Stelle auch neu erstellen durch:

  • Zurück zum Hauptmenü vom BIOS.
  • Klick Boot Options
  • Add Boot Option
  • Klick bootfs.
  • Klick EFI > Debian
  • Klick grubbaa64.efi
  • Gib „debian“ ein
  • Klick Commit.
  • Ändere die Reihenfolge und stelle sicher, das „debian“ ganz oben steht.

Dann geht du zurück in das Hauptmenü vom BIOS, wählst „Continue“ und jetzt brauchst du ganz viel Geduld (der Bildschirm ist wirklich für mehrere Minuten schwarz) …und dann

Es folgt der gewohnte Installationsdialog mit Sprache, Keyboard-Layout, User, Password, – ich erspare dir die ganzen Screenshots.

Sollte die VM in die Grub-CLI bootet, musst du erneut das Debian-netinst-ISO von der CD/DVD laden und in den Rettungsmodus wechseln. Sobald du in der Shell bist, aktualisiere Grub erneut, indem du update-grub2 ausführst. Verlassen dann die Shell und starten die VM erneut.

Wenn du durch bist mit der Installation begrüßt dich der Login-Bildschirm.

Logge dich mit deinen soeben erstellten Credentials ein und checke Betriebsystem und CPU mit uname -a && lscpu

Linux raspberrypi 6.1.0-32-arm64 #1 SMP Debian 6.1.129-1 (2025-03-06) aarch64 GNU/Linux
Architecture:             aarch64
  CPU op-mode(s):         32-bit, 64-bit
  Byte Order:             Little Endian
CPU(s):                   2
  On-line CPU(s) list:    0,1
Vendor ID:                ARM
  Model name:             Cortex-A57
    Model:                0
    Thread(s) per core:   1
    Core(s) per socket:   2
    Socket(s):            1
    Stepping:             r1p0
    BogoMIPS:             125.00
    Flags:                fp asimd evtstrm aes pmull sha1 sha2 crc32 cpuid
NUMA:
  NUMA node(s):           1
  NUMA node0 CPU(s):      0,1
Vulnerabilities:
  Gather data sampling:   Not affected
  Itlb multihit:          Not affected
  L1tf:                   Not affected
  Mds:                    Not affected
  Meltdown:               Not affected
  Mmio stale data:        Not affected
  Reg file data sampling: Not affected
  Retbleed:               Not affected
  Spec rstack overflow:   Not affected
  Spec store bypass:      Vulnerable
  Spectre v1:             Mitigation; __user pointer sanitization
  Spectre v2:             Vulnerable
  Srbds:                  Not affected
  Tsx async abort:        Not affected

Wenn du magst, kannst du noch mit sudo apt autoremove ein wenig aufräumen oder mit sudo apt update && sudo apt upgrade das System auf den aktuellsten Stand bringen. Ich persönlich füge die neue VM zunächst der lokalen Wazuh-Überwachung hinzu, aber dazu evtl. in einem späteren Tutorial mehr.

Installation von nProbe

Die Installation von nProbe ist dagegen vergleichsweise einfach, um die Konfiguration kümmern wir uns dann später:

wget https://packages.ntop.org/RaspberryPI/apt-ntop.deb
sudo dpkg -i apt-ntop.deb
sudo apt-get update

sudo apt-get install nprobe

Installation softlowd unter OpenWRT

Auch die ist verhältnismäßig unspektakulär:

opkg update
opkg install softflowd

Konfiguration

Jetzt kommt der wirklich spaßige Teil. Ich fange bei solch komplexen Konfigurationen gerne an einem der beiden Enden an, nie in der Mitte – das kennt man sicher von der Fehlersuche 🙂

In diesem Fall fange ich mit dem OpenWRT-Router an, da dieser ja die NetFlows per softflowd an die nProbe senden soll, diese dann schon mal anfängt, die Daten passend für ntopng aufzubereiten, um sie dann selbst per ZeroMQ (ein mehr als geniales Protokoll dafür) an ntopng zu senden.

Und bevor wir da gleich anfangen die Deamons und Skripte zu konfigurieren und dann beim Start den Kopf einziehen, fangen wir ganz klein mit dem OpenWRT-Router an und erarbeiten uns (die Arbeit habe ich dir mit Masse schon abgenommen) auf der Kommandozeile unsere eigentliche Konfiguration.

Wenn du softflowd ganz stumpf auf der Kommandozeile eingibst, zeigt dir die App, was sie alles kann:

root@GL-MT3000:~# softflowd
-i, -r or -R option not specified.
Usage: softflowd [options] [bpf_program]
This is softflowd version 1.0.0. Valid commandline options:
  -i [idx:]interface      Specify interface to listen on
  -r pcap_file            Specify packet capture file to read
  -t timeout=time         Specify named timeout
  -m max_flows            Specify maximum number of flows to track (default 8192)
  -n host:port            Send Cisco NetFlow(tm)-compatible packets to host:port
  -p pidfile              Record pid in specified file
                          (default: /var/run/softflowd.pid)
  -c socketfile           Location of control socket
                          (default: /var/run/softflowd.ctl)
  -v 1|5|9|10|psamp       NetFlow export packet version
                          10 means IPFIX and psamp means PSAMP (packet sampling)
  -L hoplimit             Set TTL/hoplimit for export datagrams
  -T full|port|proto|ip|  Set flow tracking level (default: full)
     vlan                 ("vlan" tracking means "full" tracking with vlanid)
     ether                ("ether" tracking means "vlan" tracking with ether header)
  -6                      Track IPv6 flows, regardless of whether selected
                          NetFlow export protocol supports it
  -d                      Don't daemonise (run in foreground)
  -D                      Debug mode: foreground + verbosity + track v6 flows
  -P udp|tcp|sctp         Specify transport layer protocol for exporting packets
  -A sec|milli|micro|nano Specify absolute time format form exporting records
  -s sampling_rate        Specify periodical sampling rate (denominator)
  -b                      Bidirectional mode in IPFIX (-b work with -v 10)
  -a                      Adjusting time for reading pcap file (-a work with -r)
  -C capture_length       Specify length for packet capture (snaplen)
  -l                      Load balancing mode for multiple destinations
  -R receive_port         Specify port number for PSAMP receive mode
  -h                      Display this help

Valid timeout names and default values:
  tcp     (default   3600)  tcp.rst (default    120)  tcp.fin (default    300)
  udp     (default    300)  icmp    (default    300)  general (default   3600)
  maxlife (default 604800)  expint  (default     60)

Okay, was davon ist interessant für uns:

  • -i spezifiziert das Interface, das kann bei einem OpenWRT-Router eth0 (das WAN-Interface) sein, aber besser ist noch br-lan, da durch diese Schnittstelle der gesamte interne Verkehr geht, egal ob LAN oder WLAN – und NAT hier noch nicht gewirkt hat.
  • -n definiert den Zielhost und Port für die generierten NetFlows (auch wenn das hier mit CISCO etwas unglücklich formuliert ist). Die IP-Adresse meiner ARM64-VM mit nProbe ist die 192.168.178.175 und nProbe hört per default aus Port 2055/UDP.
  • -v legt die Form der NetFlows fest, nProbe kann man v5, v9 und IPFIX umgehen, sagt der Entwickler auf seiner Webseite.
  • -D startet softflowd im Ddebug-Modus. Oh ja – damit fangen wir an!

Das schaut dann so aus:

softflowd -i br-lan -n 192.168.178.175:2055 -v 9 -D

Und dann geht es auch schon los, softflowd generiert NetFlows:

softflowd v1.0.0 starting data collection
Exporting flows to [192.168.178.175]:2055
ADD FLOW seq:1 [139.7.117.169]:4500 <> [192.168.8.161]:4500 proto:17 vlan>:0 vlan<:0  ether:00:00:00:00:00:00 <> 00:00:00:00:00:00
ADD FLOW seq:2 [17.57.146.27]:5223 <> [192.168.8.161]:51969 proto:6 vlan>:0 vlan<:0  ether:00:00:00:00:00:00 <> 00:00:00:00:00:00
ADD FLOW seq:3 [192.168.8.161]:49391 <> [216.239.36.127]:5223 proto:6 vlan>:0 vlan<:0  ether:00:00:00:00:00:00 <> 00:00:00:00:00:00
ADD FLOW seq:4 [192.168.8.161]:0 <> [224.0.0.22]:0 proto:2 vlan>:0 vlan<:0  ether:00:00:00:00:00:00 <> 00:00:00:00:00:00
ADD FLOW seq:5 [192.168.8.161]:5353 <> [224.0.0.251]:5353 proto:17 vlan>:0 vlan<:0  ether:00:00:00:00:00:00 <> 00:00:00:00:00:00
ADD FLOW seq:6 [fe80::9a:8ec6:7420:989f]:5353 <> [ff02::fb]:5353 proto:17 vlan>:0 vlan<:0  ether:00:00:00:00:00:00 <> 00:00:00:00:00:00
ADD FLOW seq:7 [192.168.8.1]:53 <> [192.168.8.161]:51278 proto:17 vlan>:0 vlan<:0  ether:00:00:00:00:00:00 <> 00:00:00:00:00:00
ADD FLOW seq:8 [192.168.8.1]:53 <> [192.168.8.161]:61668 proto:17 vlan>:0 vlan<:0  ether:00:00:00:00:00:00 <> 00:00:00:00:00:00
ADD FLOW seq:9 [192.168.8.1]:53 <> [192.168.8.161]:63720 proto:17 vlan>:0 vlan<:0  ether:00:00:00:00:00:00 <> 00:00:00:00:00:00
ADD FLOW seq:10 [17.242.179.27]:443 <> [192.168.8.161]:52237 proto:6 vlan>:0 vlan<:0  ether:00:00:00:00:00:00 <> 00:00:00:00:00:00

Aber kommen die auch bei der nProbe an? Dazu wechseln wir zur nProbe-Shell und sniffen mal auf der Netzwerkkarte, ob irgendetwas vom OpenWRT-Router (192.168.8.1) ankommt.

user@nProbe:~ $ sudo tcpdump -n host 192.168.8.1
tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), snapshot length 262144 bytes
15:47:01.654731 IP 192.168.8.1.34709 > 192.168.178.175.2055: UDP, length 372
15:47:01.660007 IP 192.168.178.175 > 192.168.8.1: ICMP 192.168.178.175 udp port 2055 unreachable, length 408

Ah, okay – klare Ansage. Da kommt etwas auf Zielport 2055, aber nProbe sagt Port nicht erreichbar. Das ist logisch, da die nProbe noch nicht gestartet ist, hört auch niemand auf diesem Port 2055/UDP. Also kümmern wir uns jetzt darum.

Mit nprobe –help bekommst du alle Optionen aufgelistet, den Auszug erspare ich dir hier (er füllt mehrere Bildschirmseiten). Also ein anderer Ansatz, auch hier hilft uns der Entwickler mit einer hervorragenden Dokumentation. Es gibt einen eigenen Abschnitt „Using ntopng with nProbe„, der unserem Anwendungsfall sehr ähnlich ist. Hier wird auch erklärt, wie man mit nur einer nProbe die NetFlows aus mehreren Quellen sammeln kann, um sie dann an eine ntopng-Instanz weiterzugeben. Volltreffer! Ich habe mehrere OpenWRT-Router, eine ntopng-Instanz in der Community Edition (kostenlos) und kann mit der embedded nProbe-Lizenz für knapp 100€ bis zu 4 NetFlow-Exporter softflowd anzapfen.

Aber zurück zur Syntax, nProbe verhält sich wie ein intelligentes Relais, daher sind Angaben wie Quelle und Ziel obligatorisch.

  • –collector-port ist der Port, auf dem nProbe NetFlows von einem Exporter wie softflowd empfängt
  • –zmq weist nProbe an, die NetFlows als ZeroMQ an ein bestimmtes Ziel weiterzuleiten, das ist ntopng, das bei mir unter 192.168.178.162 erreichbar ist. In den Beispielen wird der Port 5556 nur für eine Probe verwendet, also nehmen wir diesen auch.
  • –zmq-probe-mode verdeutlicht noch einmal, dass kein physikalisches Interface überwacht werden soll, sondern ausschließlich ZeroMQ zum Einsatz kommen soll
  • -n scheint auf den ersten Blick unwichtig, gibt aber an, wohin die nProbe die NetFlows senden soll. Da wir die NetFlows aber nicht einfach weiterleiten, sondern durch die nProbe verarbeiten und per ZeroMQ weiterleiten, müssen wir hier explizit none angeben
  • -T steht für das Template (kennt man sicher von Datenbanken), für unser Ziel ntopng ist die Variable %NTOPNG%

Zusammengefast sieht das dann so aus:

nprobe -i none --collector-port 2055 --zmq "tcp://192.168.178.162:5556" --zmq-probe-mode  -n none -T @NTOPNG@

Und in der Bildschirmausgabe so:

user@nProbe:~ $ nprobe  --collector-port 2055 --zmq "tcp://192.168.178.162:5556" --zmq-probe-mode  -n none -T @NTOPNG@
27/Mar/2025 15:59:57 [plugin.c:176] No plugins found in ./plugins
27/Mar/2025 15:59:57 [plugin.c:184] Loading 22 plugins [.so] from /usr/lib/nprobe/plugins
27/Mar/2025 15:59:57 [nprobe.c:6396] Disabling flow cache during collection
...
27/Mar/2025 15:59:57 [nprobe.c:8423] -i is ignored as --collector-port|-3 has been used: using '-i none'
27/Mar/2025 15:59:57 [nprobe.c:8475] Flow cache is disabled in flow collection mode
27/Mar/2025 15:59:57 [nprobe.c:8478] Welcome to nProbe v.10.7.250326 for aarch64-unknown-linux-gnu
27/Mar/2025 15:59:57 [nprobe.c:8500] Pro Edition running on Debian GNU/Linux 12 (bookworm) [Raspberry]
27/Mar/2025 15:59:57 [nprobe.c:8508] Current limits [4 ZMQ exporters][4 collector devices]
27/Mar/2025 15:59:57 [nprobe.c:8523] SystemId: L237A19D85E6BA0A5--OL
27/Mar/2025 15:59:57 [nprobe.c:8616] Sample rate [packet: 1][flow collection/export: 1/1]
...
27/Mar/2025 15:59:58 [nprobe.c:12306] Flow export type (-T): bidirectional flows
27/Mar/2025 15:59:58 [nprobe.c:12512] Flows ASs will not be computed (no GeoDB files loaded with --as-list)
27/Mar/2025 15:59:58 [nprobe.c:12544] Flows will be exported in NetFlow 9 format
27/Mar/2025 15:59:58 [util.c:6840] Initializing ZMQ as client
27/Mar/2025 15:59:58 [util.c:6871] Exporting flows towards ZMQ endpoint tcp://192.168.178.162:5556
27/Mar/2025 15:59:58 [nprobe.c:12783] Not capturing packet from interface (collector mode)
27/Mar/2025 15:59:58 [util.c:5596] WARNING: Skept UDP socket buffer enlargement: lack of privileges or in a container
27/Mar/2025 15:59:58 [util.c:5597] WARNING: Flow collection drops are possible with bursty exporters!
27/Mar/2025 15:59:58 [util.c:5606] Privileges are not dropped as we're not superuser
27/Mar/2025 15:59:58 [collect.c:248] Flow collector listening on port 2055 (IPv4/v6)
27/Mar/2025 15:59:58 [export.c:533] Using TLV as serialization format
27/Mar/2025 15:59:58 [nprobe.c:13105] nProbe started successfully
27/Mar/2025 16:11:01 [collect.c:3677] Collecting flows from 192.168.8.1 [total: 1/4]
27/Mar/2025 16:11:01 [collect.c:2013] Added new flow template definition [id=1024][flow_version=9][netflow_device=192.168.8.1:34709][observation_domain_id=0][total=1]
27/Mar/2025 16:11:01 [collect.c:2013] Added new flow template definition [id=1025][flow_version=9][netflow_device=192.168.8.1:34709][observation_domain_id=0][total=2]
27/Mar/2025 16:11:01 [collect.c:2013] Added new flow template definition [id=2048][flow_version=9][netflow_device=192.168.8.1:34709][observation_domain_id=0][total=3]
27/Mar/2025 16:11:01 [collect.c:2013] Added new flow template definition [id=2049][flow_version=9][netflow_device=192.168.8.1:34709][observation_domain_id=0][total=4]
27/Mar/2025 16:11:01 [collect.c:2013] Added new flow template definition [id=256][flow_version=9][netflow_device=192.168.8.1:34709][observation_domain_id=0][total=5]

Die letzten 5 Zeilen sehen gut aus.

Also wechseln wir in die Shell von ntopng und beginnen auch hier auf der Kommandozeile. Beende gegebenenfalls das Skript fritzdump.sh, wenn du mein anderes Tutorial hier verfolgt hast. Dann kennst du ntopng aber schon ein wenig. ntopng benötigt mindestens eine Datenquelle, um Flows visualisieren zu können. Bisher (Tutorial) war das der Paketmitschnitt der Fritzbox, jetzt soll es die nProbe sein.

Zusätzlich können wir noch angeben, was das lokale Subnetz ist, das habe ich hier mit supernetting zusammengefasst.

ntopng -i tcp://*:5556c -m "192.168.0.0/16=local"

Wir lassen ntopng hier auf allen Interfaces auf Port 5556 lauschen, du kannst auch explizit nur eines angeben. Das kleine c bedeutet, dass ntopng hier im Collector-Modus arbeitet. Sonst würde ntopng aktiv bei der nProbe nach neuen Flows fragen, hier verhält es sich passiv und lässt die nProbe berichten.

Läuft!…würde ich sagen. NetFlows aus einem „völlig fremden“ Netzwerk (192.168.8.0/24)

Zusammenfassung

Okay, nachdem das alles so gut auf der Kommandozeile funktioniert, übergeben wir das Ganze an Daemons oder Skripte, die die Arbeit im Hintergrund erledigen.

Beginnen wir wieder mit dem OpenWRT-Router. Beende softflowd mit CTRL-X und du hast wieder die Kontrolle über die Kommandozeile.

OpenWRT bietet die Konfiguration über uci an, einen eigenen Konfigurationsmanager.

uci add softflowd softflowd
uci set softflowd.@softflowd[0].enabled='1'
uci set softflowd.@softflowd[0].interface='br-lan'  # Zu überwachende Schnittstelle
uci set softflowd.@softflowd[0].host_port='COLLECTOR_IP:2055'  # Ziel-IP/Port des NetFlow-Kollektors
uci set softflowd.@softflowd[0].export_version='9'  # NetFlow v9 empfohlen
uci commit softflowd


#uci set softflowd.@softflowd[0].track_ipv6='1' #auskommentieren, wenn du auch IPv6 tracken möchtest

/etc/init.d/softflowd start
/etc/init.d/softflowd enable

Das war es schon, der Dienst läuft im Hintergrund. Du kannst mit softflowctl statistics oder softflowctl dump-flows das ganze auch verifizieren. Aufpassen! softflowctl und nicht nicht softflowd 🙂

root@GL-MT3000:~# softflowctl statistics
softflowd[12511]: Accumulated statistics since 2025-03-26T12:24:16 UTC:
Number of active flows: 2
Packets processed: 56
Packets non-sampled: 5453
Fragments: 0
Ignored packets: 798 (798 non-IP, 0 too short)
Flows expired: 42 (0 forced)
Flows exported: 42 (45 records) in 23 packets (0 failures)
Packets received by libpcap: 6315
Packets dropped by libpcap: 0
Packets dropped by interface: 0

Expired flow statistics:  minimum       average       maximum
  Flow bytes:                  40           279          1500
  Flow packets:                 1             1             3
  Duration:                  0.00s        83.46s      1500.50s

Expired flow reasons:
       tcp =        15   tcp.rst =         1   tcp.fin =         1
       udp =        19      icmp =         5   general =         1
   maxlife =         0
over 2 GiB =         0
  maxflows =         0
   flushed =         0

Per-protocol statistics:     Octets      Packets   Avg Life    Max Life
           icmp (1):           2988            5       0.00s       0.00s
           igmp (2):             40            1       0.00s       0.00s
            tcp (6):           4616           25     206.19s    1500.50s
           udp (17):           4070           19       0.00s       0.00s
root@GL-MT3000:~# softflowctl dump-flows
softflowd[12511]: Dumping flow data:
ACTIVE seq:38 [178.254.4.110]:993 <> [192.168.8.193]:50370 proto:6 octets>:117 packets>:1 octets<:0 packets<:0 start:2025-03-26T14:48:45.874 finish:2025-03-26T14:48:45.874 tcp>:18 tcp<:00 flowlabel>:00000000 flowlabel<:00000000 vlan>:0 vlan<:0 ether:00:00:00:00:00:00 <> 00:00:00:00:00:00
EXPIRY EVENT for flow 38 in 702 seconds

ACTIVE seq:21 [17.57.146.55]:5223 <> [192.168.8.193]:56339 proto:6 octets>:0 packets>:0 octets<:200 packets<:5 start:2025-03-26T13:50:58.289 finish:2025-03-26T15:31:15.272 tcp>:00 tcp<:10 flowlabel>:00000000 flowlabel<:00000000 vlan>:0 vlan<:0 ether:00:00:00:00:00:00 <> 00:00:00:00:00:00
EXPIRY EVENT for flow 21 in 3252 seconds

ACTIVE seq:45 [17.253.15.201]:443 <> [192.168.8.193]:57143 proto:6 octets>:1399 packets>:1 octets<:0 packets<:0 start:2025-03-26T15:32:28.054 finish:2025-03-26T15:32:28.054 tcp>:18 tcp<:00 flowlabel>:00000000 flowlabel<:00000000 vlan>:0 vlan<:0 ether:00:00:00:00:00:00 <> 00:00:00:00:00:00
EXPIRY EVENT for flow 45 in 3325 seconds
...

Die eigentliche Konfigurationsdatei kannst du auch manuell unter /etc/config/softflowd mit einem Editor bearbeiten und anschließend den Dienst mit /etc/init.d/softflowd restart neu starten. Die ist recht selbsterklärend, da gehe ich jetzt nicht weiter drauf ein.

Die nProbe hat zwar ein Konfigurationstool, das du wie folgt starten kannst, aber… (das aber siehst du gleich):

sudo nprobe-config

Natürlich wollen wir zunächst eine neue Konfiguration erstellen:

Wir möchten Flows sammeln und dann an ntopng weiterleiten:

Dann vergibst du einen aussagekräftigen Namen, wählst als Port 2055 als eingehenden Port für softflowd und die IP-Adresse von ntopng sowie den Port 5556, auf dem ntopng auf die Pakete von der nProbe wartet.

Was auffällt ist, das du ZeroMQ als Protokoll gar nicht auswählen kannst. Also ist doch wieder Handarbeit nötig. Du findest die entsprechende Konfigurationsdatei unter /run/nprobe.conf für einen Flow, oder wenn du die mittels der GUI eine neue Konfig erstellt hast unter /run/nprobe-<NAME>.conf. Also wenn dein aussagekräftige Name „openwrt“ war unter /run/nprobe-openwrt.conf. Dort findest du alle einzelnen Parameter wie auf der Kommandozeile.

Den Dienst selbst kannst du dann wie folgt starten

systemctl start nprobe
systemctl enable nprobe

Bleibt noch ntopng selbst. Da wir zwingend eine Schnittstelle übergeben müssen, bleibst du entweder bei der Kommandozeile und hängst nur ein & an, bevor du Enter drückst. Dann läuft der Dienst im Hintergrund. Oder du änderst die letzte Zeile von fritzdump.sh (die, die mit wget beginnt) aus dem anderen Tutorial (oben verlinkt) wie folgt ab

wget --no-check-certificate -qO- $FRITZIP/cgi-bin/capture_notimeout?ifaceorminor=$IFACE\&snaplen=\&capture=Start\&sid=$SID | ntopng -m "192.168.0.0/16=local" -q -F syslog --community -i tcp://*:5556c -i -

Beachte, dass der Parameter -i zweimal enthalten ist, zuerst unser NetFlow von der nProbe und dann STDIN, der Paketmitschnitt der Fritzbox.

Jetzt kann das ntop-Team gerne 100€ für die nProbe-Lizenz von mir haben, dann erspare ich mir den 10-minütigen Neustart der nProbe zur Evaluierung. 🙂

An der Performance kann man sicher noch etwas schrauben, ich werde dieses Tutorial anpassen, wenn ich Verbesserungen am Workflow oder den Parametern finde.

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert