packet logging with iptables

<note>
i wasted 2 hours of my life getting this working on a fresh install of unbuntu 10.10. turns out that the default version of rsyslog that you get when you ‘apt-get install rsyslog’ is version 4.x, which has a bug that prevents the logging from being directed correctly to /var/log/iptables.log. i had to remove rsyslog (apt-get remove rsyslog), then go get the newest version of rsyslog (5.8) from the site and compile from source. after compiling and pulling in the new conf file (its a little different in rsyslog 5.x than 4.x), things worked as expected. ye be warned.
</note>

recently i wanted to see what packets were getting passed or blocked on a linux server running iptables. i really wanted to see a log that showed every inbound and outbound packet, and both dropped and allowed packets.

you can see all the packets in tcpdump/wireshark/etc, but it doesn’t show you that iptables dropped the connection (you just see there is no syn ack response). so my goal was to create a iptables ruleset that logged every packet to a separate file, distinguished what was allowed and what was dropped, and to have the logs rotating automatically. here is how i did it:

notes: i am doing this on linux mint 10 (julia), which is based off of ubuntu 10.10. also, for pretty much everything i am doing i have to be root, so i ran “sudo su – ” so i was logged in as root, thats why you wont see any sudo commands. lastly, if you want a practical crash course in iptables, i suggest google and slicehost’s series here.
the first thing to do is change where iptables logs to (on most systems it goes to /var/log/messages). to make this take effect, you will have to restart the rsyslog service after making the changes.

nano /etc/rsyslog.d/50-default.conf
add the following lines:
:msg, contains, "iptables"      -/var/log/iptables.log
&amp; ~

now that we have the log destination changed, we need to set up our firewall rules in iptables. other than logging, i also wanted to set up a rule that blocked any brute force attempts on my ssh server. you can save the following text to a file (or download it here) and then import it into iptables by running “iptables-restore < saved_file_name”

# Generated by iptables-save v1.4.4 on Fri Apr  8 22:58:56 2011

*filter
:INPUT DROP [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
:logaccept - [0:0]
:logdrop - [0:0]

# accept all loopback connections
-A INPUT -i lo -j ACCEPT

# forward all established connections to the logaccept chain
-A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j logaccept

# forward all icmp traffic to the logaccept chain
-A INPUT -p icmp -j logaccept

# if source ip has set up more than 5 new connections in 10 minutes, send all new connections to the logdrop chain. if source ip has set up 5 or less new connections in 10 minutes, forward to the logaccept chain.
-A INPUT -p tcp -m tcp --dport 22 -m state --state NEW -m recent --update --seconds 600 --hitcount 5 --name DEFAULT --rsource -j logdrop
-A INPUT -p tcp -m tcp --dport 22 -m state --state NEW -m recent --set --name DEFAULT --rsource
-A INPUT -p tcp -m tcp --dport 22 -j logaccept

# cleanup rule to send all other traffic to the logdrop chain
-A INPUT -j logdrop

# allow all outbound loopback traffic
-A OUTPUT -o lo -j ACCEPT

# forward all outbound traffic to the logaccept chain
-A OUTPUT -j logaccept

# create your logaccept chain. this appends "iptables accept " to the front of the log entry and then allows the traffic to pass through
-A logaccept -j LOG --log-prefix "iptables accept "
-A logaccept -j ACCEPT

# create your logdrop chain. this appends "iptables drop " to the front of every packet and the drops the packets
-A logdrop -j LOG --log-prefix "iptables drop "
-A logdrop -j DROP

COMMIT

one quick thing i found helpful. the default iptables -L command to list rules leaves a lot to be desired. to speed things up (and keep it persistent across reboots), i created an alias in my .bashrc file for my root user for the command iptables_list, which translated to iptables -L -v -n –line-numbers (see picture below):

after loading my iptables rules and then running my iptables_list alias, here is what i saw:

now that i had the iptables logging and iptables rules in place, i wanted to make sure the log didn’t get too large. i set up a logrotate job that ran daily to keep the log file from getting too large (obviously if you were in a high traffic environment once a day might not be often enough to rotate).

nano /etc/logrotate.d/iptables

add the following text to the file

/var/log/iptables.log
{
rotate 3
daily
missingok
notifempty
delaycompress
compress
postrotate
/usr/sbin/service rsyslog restart > /dev/null
endscript
}

it might look like a mess with a simple cat command, but the end result was exactly what i was looking for:

cat on iptables.log

after a little clean up with grep and cut:

references:

  • http://blog.shadypixel.com/log-iptables-messages-to-a-separate-file-with-rsyslog/
  • http://articles.slicehost.com/2011/2/21/introducing-iptables-part-3
  • http://www.linode.com/wiki/index.php/Netfilter_IPTables_Mini_Howto
  • http://www.liniac.upenn.edu/sysadmin/security/iptables.html