I have some servers on Rackspace cloud platform. Having full control over OS allows to make many useful testing, even if its virtualized  Recently while doing some server hardening work I discovered not an obviously thing with iptables. In fact some of my firewall rules where completely ignored!!

I am not the iptables newbie and was very surprised by such behavior. Find the story below...

My goal was to close outbound mail traffic for all processes except postfix, to prevent potential spam by misconfigured PHP scripts or malware.  It simple means deny outgoing TCP connections with port 25. So I wrote these rules to iptables:

iptables -A OUTPUT -p tcp -m tcp --dport 25 -m owner --uid-owner postfix -j ACCEPT
iptables -A OUTPUT -j DROP

Next I tried to connect to google MX server under WWW account to check if block is in place. BUT (!) connection was successful, that was a real surprise.

# su - www-data
$ telnet aspmx.l.google.com 25
Trying 2607:f8b0:4001:c02::1a...
Connected to aspmx.l.google.com.
Escape character is '^]'.
220 mx.google.com ESMTP de4si13860498igb.33

I spend sometime time for investigation with no luck, and by chance  saw strange address "2607:f8b0:4001:c02::1a". Its IPv6 address and its used by default in this connection. IPv6 was in charge!

Thing is that Rackspace servers has IPv6 enabled by default. Linux uses different set of iptables rules for this protocol.   There is separate command iptables6 to manage firewall rules. If you get used only to IPv4 protocol this will surprise you!

# Configure IPv4 and IPv6 iptables in one file

To overcome this issue and still manage firewall from one configuration script I did simple aliases, see below. This way its possible to enter rule that will be used in IPv4 or IPv6 or in both sets.

# Rule will be only in IPv4
ipt4() {
   $IPTABLES "[email protected]"

# Rule will be only in IPv4
ipt6() {
   $IP6TABLES "[email protected]"

# Rule will be only in both IPv4 ans v6
ipt46() {

So my firewall rules to block output on 25 port will look like

ipt46 -A OUTPUT -p tcp -m tcp --dport 25 -m owner --uid-owner postfix -j ACCEPT
ipt46 -A OUTPUT -j DROP

This way your firewall is configured right!