Saturday, January 10, 2004

A FreeBSD Kernel Module for Generating NetFlow Records

While visiting SourceForge, I queried for NetFlow and found ng_netflow, a NetGraph-based kernel module for FreeBSD. The project was started this week and the first release, ng_netflow 0.1, occurred three days ago! The author warns that this early version is for demonstration only, as the method ng_netflow uses to time out flow records can be extremely slow. With ng_netflow in the kernel, however, this method has the possibility for being much faster than userland implementations like Fprobe.

I tested ng_netflow on a FreeBSD 4.9 system named janney, with IP address 172.27.20.5. To use ng_netflow, download the archive and extract it. Change into the ng_netflow-0.1 directory and execute ‘make’.

janney# tar -xzf ng_netflow-0.1.tar.gz
janney # cd ng_netflow-0.1
janney # ls
CVS Makefile flowctl
ChangeLog README ng_netflow
janney # make && make install
...edited...
===> ng_netflow
install -o root -g wheel -m 555 ng_netflow.ko /modules
install -o root -g wheel -m 444 ng_netflow.4.gz /usr/share/man/man4
===> flowctl
install -s -o root -g wheel -m 555 flowctl /usr/local/sbin
install -o root -g wheel -m 444 flowctl.8.gz /usr/share/man/man8

To enable the kernel module, use the following syntax. Note it differs from the man page, which has errors. Interface em0 is the interface which will listen for traffic to be represented as NetFlow data. 172.27.20.3 is the NetFlow collector, bourque.

janney# kldload ng_ether
janney# kldload ng_tee
janney# kldload ng_netflow
janney# ngctl -f - << EOF
? mkpeer em0: tee lower right
? connect em0: em0:lower upper left
? mkpeer em0:lower netflow right2left iface0
? name em0:lower.right2left netflow
? msg netflow: setifindex { iface=0 index=1 }
? mkpeer netflow: ksocket export inet/dgram/udp
? msg netflow:export connect inet/172.27.20.3:4444
? EOF

You can check the status of the ng_netflow kernel module with the following command:

janney# flowctl netflow show
SrcIf SrcIPaddress DstIf DstIPaddress Pr SrcP DstP Pkts
em0 192.168.1.2 em0 192.168.1.1 6 03f8 006f 5

These results show flows between 192.168.1.1 and 192.168.1.2. These are the IP addresses in the lab system for which monitoring interface em0 on janney has visibility. Once enabled, and traffic is flowing past the em0 interface on janney, the ng_netflow probe will emit NetFlow records to the collector. We verify this with Tcpdump on the collector, bourque:

bourque# tcpdump -n -s 1515 -i fxp0 -X port 4444
tcpdump: listening on fxp0
08:15:08.271115 172.27.20.5.1064 > 172.27.20.3.4444: udp 72
0x0000 4500 0064 0842 0000 4011 f208 ac1b 1405 E..d.B..@.......
0x0010 ac1b 1403 0428 115c 0050 f86c 0005 0001 .....(.\.P.l....
0x0020 0000 03c5 3ffe a98c 0004 df9c 0000 0000 ....?...........
0x0030 0000 0000 c0a8 0102 c0a8 0101 0000 0000 ................
0x0040 0001 0001 0000 0001 0000 0054 0000 03b2 ...........T....
0x0050 0000 03b2 0000 0000 0000 0100 0000 0000 ................
0x0060 1818 0000 ....

As you can see, janney (172.27.20.5) is emitting NetFlow records to port 4444 UDP on 172.27.20.3. Now you need to use something like Flow-captire to collect the records.

flow-capture -w /nsm/netflow/ng_netflow/test/ 0/0/4444

We use Flow-cat and Flow-print to see the records:

bourque# flow-cat * | flow-print | less
srcIP dstIP prot srcPort dstPort octets packets
192.168.1.2 192.168.1.1 6 1023 111 312 5
192.168.1.2 192.168.1.1 6 1022 111 312 5
192.168.1.2 192.168.1.1 6 1021 111 312 5
192.168.1.2 192.168.1.1 17 1023 111 84 1
192.168.1.2 192.168.1.1 6 1020 1023 312 5
192.168.1.2 192.168.1.1 17 1020 111 84 1
192.168.1.2 192.168.1.1 17 1022 111 84 1
192.168.1.2 192.168.1.1 17 1019 1023 156 1
192.168.1.2 192.168.1.1 17 1021 2049 68 1
192.168.1.2 192.168.1.1 17 1018 2049 6204 42
192.168.1.2 192.168.1.1 6 1019 111 312 5
192.168.1.2 192.168.1.1 6 1018 111 312 5
192.168.1.2 192.168.1.1 17 1017 111 84 1
192.168.1.2 192.168.1.1 17 1016 1023 156 1
192.168.1.2 192.168.1.1 17 1018 2049 9053528 56586

I personally prefer to work with Argus data, but many sites have extensive NetFlow-based monitoring systems.

If you prefer to implement a user-land NetFlow probe, try Fprobe, in the ports tree at /usr/ports/net/fprobe.

Fprobe allows a standalone NSM platform to export NetFlow records just as a Cisco router would. It’s an application installed on a server which listens for traffic and generates NetFlow records based on what it sees. Fprobe is a good alternative for analysts who want to create NetFlow data without adding to the processing load of their router, or whose routers don’t support NetFlow due to lack of memory or an old Cisco IOS version.

The following command tells Fprobe to listen on the ngeth0 monitoring interface and export NetFlow data to a collector on port 2055 UDP at 172.27.20.3:

/usr/local/bin/fprobe -i ngeth0 –f ip 172.27.20.3:2055

The default export format is NetFlow v5, although Fprobe also supports versions 1, 5, and 7. The “-f ip” switch tells Fprobe to use the Berkeley Packet Filter “ip” as a filter. Although the –f switch is optional, the Fprobe manpage advocates its use. In the configuration I use, I have Fprobe run on the NSM platform and export NetFlow data to a collector also running on the NSM platform.

We read the Fprobe records using the Flow-tools just as we did for ng_netflow.