Building Detailed Network Reports with Netflow
Pages: 1, 2, 3, 4
flow-nfilter
We can do a lot on the fly with flowdumper and can aggregate data nicely with flow-stat, but the detailed data provided by Netflow should let you do just about any sort of report. You should easily be able to list all SMTP connection attempts to systems that aren't supposed to be SMTP servers. Perhaps you could write the flowdumper Expression from the Infernal Regions to accomplish this, but there are better ways--especially if you intend to use this report repeatedly. The flow-nfilter(1) program lets you write detailed reports on Netflow data.
Flow-nfilter's configuration relies on "primitives": small definitions that describe one characteristic of traffic--a network port, an IP address, and so on. It assembles these primitives into larger rules that constitute reports. By default, flow-nfilter stores these primitives and definitions in /usr/local/etc/flow-tools/filter.cfg. I will start with primitives and proceed to building actual reports.
Every primitive definition starts with the filter-primitive label and a name. It then contains the type of primitive. The man page lists many different types of primitives that cover every situation, but this list is too much to read for common situations. (Read the man page for flow-nfilter for a list of the available filtering primitives, but the handful below will get you started.) The most commonly used primitives include ip-protocol, ip-port, ip-address, and ip-address-prefix. The following example is a primitive for the TCP protocol:
filter-primitive TCP
type ip-protocol
permit tcp
default deny
While its name is TCP, the permit statement tells the primitive that it matches anything of protocol type tcp. You could also use 6, the protocol number for TCP as defined in /etc/protocols. The default deny at the end means the primitive doesn't match anything that isn't TCP. (Primitives have an implicit default deny, but I find explicit statements more comfortable.)
Similarly, the ip-port primitive type matches TCP or UDP ports. This primitive, smtpports, matches connections to port 25 and only port 25:
filter-primitive smtpports
type ip-port
permit 25
default deny
The adept among you can already see where this is heading; TCP connections to port 25 are either SMTP conversations or masquerading as SMTP conversations.
You can define entire networks with the ip-address-prefix primitive type. The hostingnet primitive matches the entire 192.168.88.0 network:
filter-primitive hostingnet
type ip-address-prefix
permit 192.168.88.0/24
default deny
Finally, you can match individual IP addresses with the ip-address type:
filter-primitive local_mailservers
type ip-address
permit 192.168.88.33
default deny
Primitives can get quite complicated. For example, suppose I want to make a filter primitive that includes everything that isn't a mail server. The trick to this is to start small and gradually grow.
filter-primitive local_not_mailservers
type ip-address
deny 192.168.88.33
permit 192.168.88.0/24
default deny
The primitive itself is an IP address--actually, a set of them. It isn't a network, because there's a hole in it. I started by denying my actual mail server's IP. I then accepted the whole block of addresses in the network. At the end, if an IP isn't explicitly permitted, it's denied. This primitive will match any IP address from 192.168.88.0 through 192.168.88.32 and from 192.168.88.34 through 192.168.88.254.
You can list several related items in a single primitive. For example, my company's security policy forbids use of telnet (port 23) and MS SQL (port 1433) connections over the public internet. If I see this traffic on my network, something interesting is going on. This primitive matches both of these.
filter-primitive redflags
type ip-port
permit 23
permit 1433
default deny
Similarly, you could have a list of IP addresses in permit statements. You can't combine unrelated items in a primitive, however; to combine port 25 and protocol tcp, you must create a rule.