14 October 2012

Easy way to config iptables working with ftp

Today I need to build up an Linux server to provide ftp service to my intranet users, I've choose vsftpd as the ftp server because it is default shipped with CentOS. Everything works fine, I can upload and download files through ftp service. Later that I need to secure the server with firewall - iptables of course, the built in firewall for linux - I config the rule to allow tcp destination port :21.

Now I can only logon to ftp sevice and I can not list or download any files. What the hill happen to my server ? After a while calm down, I realize that ftp is a multi ports protocol. It uses port 20/21 for command, and some random port bigger than 1024 for data transfer. Yes, a range of random ports to send or receive data - so to archive this goal, how can I config the iptables to allow these random ports !?
After searching, I found a lot of guidances which similar to each other to complete this but most of them require taking more action and much more complex to remember. They talk about passive and active ftp, talk about changing the default data port range in vsftpd configuration file, defining a static port range and make iptables reserver for that range, and blah blah blah ...

Too much complex and I get mess up with them, I really don't care about active or passive ftp. All I just want is iptables can "understand" the ftp protocol and let it get through. Fortunately, this can be real, ah hah, the iptables does understand ftp protocol if it was configured properly. I found a really easy way to make iptables can "read" and working with ftp. It's my honor to share the lession with you.

Instruction steps :

As I did mention when service ftp is running and iptables has enabled, I only can login to ftp service without sending or receive any piece of data.

Client# lftp ftpuser@

lftp ftpuser@> put install.log
`install.log' at 0 (0%) [Delaying before reconnect: 9]

and it hang for a while until timed out.

Luckily, iptables has a module called ip_conntrack_ftp used to do tracking ftp connection. This module is default shipped with CentOS/Fedora Linux distro. All I need is to check if it exist and modify the iptables config file to enable it.

Let see if the server has the conntrack_ftp module.

Server# find /lib/modules/ | grep conntrack_ftp


Enable it in the iptables config-file and make sure to restart the iptables service for applying.

Server# vim /etc/sysconfig/iptables-config

IPTABLES_MODULES="ip_conntrack_netbios_ns ip_conntrack_ftp"

Let see if the server has loaded that module.

Server# lsmod | grep conntrack_ftp

ip_conntrack_ftp 41361 0
ip_conntrack 91621 5 ip_conntrack_ftp,ip_conntrack_netbios_ns,xt_state,iptable_nat,ip_nat

From client, try again uploading some test file.

Client# lftp ftpuser@

lftp ftpuser@> put install.log
9719 bytes transferred

Awesome ! With just a little config, I have make iptables corporates with ftp service smoothly no matter active or passive mode has been used. The point is : 

Module ip_conntrack_ftp does help iptables really understand the ftp protocol, it can read the "PORT" command in ftp session and then open the appropriate ports to get ftp traffic get through.