Graphing iptables stats
I have iptables on a couple of different Linux hosts. There are a number of tools that allow you to centralize the logs of different hosts (and services) but they often focus on some form of alert management. I need something that allows me to gather the logs from different hosts, put them all in one central database and then generate some statistics on this data.
Iptables logs to the local syslogger but ulogd allows for extra logging features.
Ulogd, map iptables log
ulogd is a userspace logging daemon for netfilter/iptables related logging. I use it to log firewalled packets to a mysql database.
Ulogd is available as a package on most popular Linux flavors but it is possible that you get an older version. If you need version 2 you’ll probably will have to compile everything from source.
Having the packets in a database does not mean you can easily make sense out of it. I needed a tool to visualize the number of events. I would also like to have them outlined on a map to get some idea on the origin of events. A posting on the blog of Xavier Mertens, “” has a Perl script that maps everything on a Google Maps. This covers part of my question. I preferred one tool that could do both so I write my own tool, in PHP.
ulogd-viz is available on Github.
It is written in PHP and requires
- a web server;
- a mysql database;
- a Google API key;
- the GeoIP Pear package;
- a copy of the Maxmind GeoIP database.
I will not cover how to get ulogd running. Basically you need to make sure it logs to a mysql database. The configuration is done in /etc/ulogd.conf. To activate mysql enable the correct plugin.
Defining what packets it needs to log exactly is a matter of inserting the log rule in the right place in the iptables log rule set.
If you are using UFW and want to filter everything (careful because this can easily fill the available drive space) that comes in then use this rule
iptables -I ufw-before-input -j ULOG --ulog-nlgroup 1 --ulog-prefix ULOG
The easiest way to get ulogd-viz is by cloning it. Go to the directory where you’d like to install it and start
git clone https://github.com/cudeso/ulogd-viz.git
Remember that ulogd-viz does not have any authentication or ACL features. If you want to limit access (strongly recommended) you will have to set this in the server configuration. It would also be a very bad idea to install this on a public available web server without proper authentication and access control.
All the configuration is done in two files, config/ulogd.php and config/ulogd.ini. The cloned git directory contains a default config file, you just have to copy it to a working config file.
cp config/ulogd.ini.default config/ulogd.ini
ulogd-viz needs to be able to read the content of the database. Enter the correct credentials in the database section.
[database] username = password = database = host = localhost ulogtable = ulog
It is not entirely necessary but in order to use the ‘shortcut’ feature of ulogd-viz you will need to add an additional table. You can find the create script at db/create.sql. Ulogd-viz will run just fine but the ajax request for get.php?shortcut=get will return errors. Notice that this request has a rand value added to prevent caching (&rand=3376).
Geoip and Google API
The next thing that you need is a copy of the Maxmind GeoIP database. Download the GeoLite City database, extract it and move it to the library location.
Now get a Google API key and look up your ‘home’ coordinates on Google Map. Packets that match with RFC1918 will be geo-mapped to this location.
Now add all this information to the configuration file
[geoip] database = "/var/www/htdocs/ulogd-viz/library/geoipdb.dat" googlemaps = "enterkey" home_latitude = "50.8387" home_longitude = "4.363405"
Make sure you configure your web server to have its default documentroot set to the www directory. Test if you can access the site by browsing to it and consult the web server logs if something does not work as expected.
The first screen that you get is the dashboard. The upper part of the dashboard allows you to select a 1 : timeframe (last hour, last day, last week, …), filter on 2 : ports and protocols and filter on 3 : source or destination IP.
From the dashboard you can select three different 4 : output types
- Charts and tables will give you a Google Chart and a Google Table, exportable to a CSV;
- Maps renders a Google Map with the source of the IPs mapped out geographically;
- Table lists the recorded entries, but capped with a maximum that is set in the configuration file (this maximum is set to prevent database connection timeouts).
You can add multiple ports and multiple ips. Once you are done you can generate the result by clicking on 5 : Generate.
The lower part of the dashboard provides some shortcuts to useful graphs and statistics. These are for example the list of detected hits for a blacklist, the top 5 ports, etc. You can click on the info blocks to get the full query.
The dashboard allows you to filter the results and restrict the results to a selected timeframe.
The 1 : timeframe allows you to select the results for the last hour, last day, last week , etc.
You can then filter on 2 : protocol and 3 : port. If you do not set a port then it will just filter out the protocol. If you select ICMP as a protocol then the port field will act as a filter for the ICMP code.
Additionally you can 4 : include or exclude a 5 : single IP, either 6 : source, destination or both.
Charts and Tables
The first output type is the Google Chart and Tables screen. It prints out the firewall entries in a graph and a table.
If you have not selected to filter on a port / protocol you’ll get a single line graph and single column table. If you have selected a filter port / protocol filter in the dashboard screen you’ll get a multi-line graph with the 1 : Graph legend printed on the right. For every line in the graph you get a 2 : Table column. Remember that the filter on port / protocol is limited to five entries. Filters for IPs are not displayed on the graph. These entries are depending on your choice in the dashboard, omitted from the results or only the results from the selected IPs are displayed.
You can 3 : Export to CSV or 4 : Save the query as a shortcut.
You can go back to the dashboard with 5 : Run another query.
The output to a map returns a Google Map with the geo location of the IPs mapped out on the map.
The entries are filtered depending on the filters that you had previously set in the dashboard (similar as for Charts and Tables).
The last output that is available is the raw table output.
The tools menu has a tool that allows you to convert timestamps (timestamp <-> user readable format) and IPs (ip notation <-> long notation).
The statistics page provides some of the statistics that can already be found on the dashboard page, extended with other useful information.
You can set up a blacklist against which the logged entries are checked. This will not block any packets! It will only reveal if your firewall detected access to certain IPs (for example known C2-servers).
The blacklist itself is a text file with an IP per line. The location is set in the configuration file.
Cron to clean-up
There is a cron script that can automatically clean up the older entries. In the configuration file you can define how long files have to be kept. You should add the execution of this cron script somewhere in your cron tab.
10 5 * * * root php <enter_path_to_ulogd-viz>/config/cron.php
You can execute the cron script manually with
If you do not run the clean up script then the number of logged entries will only grow. Depending on how much drive space you have reserved for the database this could fill your entire drive.
Centralize the logs
The setup described above has the web server (and database server) on the host on which the firewall is running. This is not always desirable. Ideally you run a database server locally on each host to collect the events and then export these events to a central database.
ulogd-viz does not have a “host” identifier by which you can select from the centralized database only the events for a specific firewall. In order to do this, you’ll have to filter by destination address.
You can achieve this result in a number of ways.
- Open mysql via a management interface, allow incoming mysql traffic (use the encryption and authentication features of mysql);
- Have mysql run in an SSL tunnel;
- Dump the data locally and transfer it via SSH (see example below);
#!/bin/bash # Dump data locally; then copy to central server mysqldump -u root -p'ulogd-pw' ulogd > ulogd-dump.sql cat ulogd-dump.sql | ssh -i privatekey -l myuser 10.0.0.1 mysql -u ulogd-import -p'ulogd-import' ulogd-central
- Select on MAC ID;
- Generate report from the cron-job (PDF);