Logging traffic at the iptables level and exclude multiple subnets that can’t be noted in CIDR
ULOG and NFLOG are a better solution to this. LOG is useful for some minor stuff.
The LOG option in iptables is quite useful when dealing with packets traversing the stack. For instance, I was attempting to sniff traffic with tcpdump that was sourced and destined for the bound local IP of the interface. Of course, tcpdump didn’t see any of the packets because the network stack (in the kernel) was turning the packets back before they reached the place where tcpdump hooks into (low level).
Here is a good diagram that explains the linux kernel network stack, and here is a good diagram on how iptables works. You can correlate items on the iptables diagram to the kernel network stack diagram to understand how they interact. This is why tcpdump/pcap, which hooks into (unknown kernel level networking class) awaiting packets, does not see packets sourced and destined for the IP on the same interface.
Since I was curious if the packets were hitting the ipt_NETFLOW iptables module, all I really cared about was checking whether they arrived to iptables without issue. LOG allowed me to do this, but I still had a problem.
I have two sites, both with subnets that are far away from each other, 192.168.10.0/24 and 192.168.100.0/24 (for instance). I wished to exclude both sites’ traffic from a LOG option in iptables. Seems pretty trivial when dealing with a rule set. If you can’t drop the packets at rule 0, then drop it at rule 1, etc. However, since the LOG option, well, logs, exclusions can not be done without dropping packets; which is not at all what I want to do.
In iptables, there are various ways to qualify packets, such as source/destination IP address, src/dst port, and a large variety of other things; the problem I faced is simple. The source IP qualifier [what is really termed a “match”] (-s) and/or destination IP qualifier (-d), and/or the src/dst port qualifiers (–sport, –dport) do not take any parameter other than a single host description, such as CIDR notation. There is no parsing of comma-separated lists for instance, and no clean way exclude multiple subnets or port ranges. “Just add two statements in the same line,” you might think. Wrong. This fails.
So, quite simply, we can complement the -s, -d, –sport, –dport, with another qualifier. The handy iprange or multiport match extensions. I expect you can read the iptables man page, so I won’t go into great detail, but here is an example:
I want to LOG packets that arrive to iptables on INPUT, but exclude two subnets: 192.168.10.0/24 and 192.168.100.0/24.
-A INPUT -s ! 192.168.10.0/24 -m iprange ! --src-range 192.168.100.1-192.168.100.254 -j LOG
To note, I find it much easier to deal with the iptables config file directly than just adding random rules at the command-line. On CentOS/RHEL this lives at /etc/sysconfig/iptables. So just copy that file for backup, and merry editing.
P.S. I hate the term “supernet” and all of its verb tenses/forms.