Using FTPS (FTP over explicit TLS/SSL) with active ftp?

I have run in to this issue. It looks like you need to open up the ftp data transfer range of ports when using FTP with explicit TLS/SSL. Try the following:

iptables -A INPUT -p tcp --sport 1024: --dport 64000:65535 -m state --state ESTABLISHED -j ACCEPT

iptables -A OUTPUT -p tcp --sport 64000:65535 --dport 1024: -m state --state ESTABLISHED,RELATED -j ACCEPT

You need to explicitly allow access to ftp-data incoming port range. Nic's answer recommends statically opening the full range, but that might be too open. Besides, RELATED is useless in this case because conntrack_ftp module can't snoop an encrypted control connection.

My recommendation is to use the recent match. Try the following:

iptables -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
iptables -A INPUT -m state --state NEW -j in_new
iptables -A in_new -p tcp --sport 1024: --syn --dport 64000:65535 -m recent --name ftpdata --update --seconds 1800 --reap -j ACCEPT
iptables -A in_new -p tcp               --syn --dport ftp         -m recent --name ftpdata --set -j ACCEPT

The --setrule will be matched by control connection and will add the source ip to ftpdata recent list. The --update rule will do most of the interesting work:

  • Will match if the source address of the packet is in the ftpdata list (--update) and the source addres was seen within the last 1800 seconds (--seconds 1800).
  • If matched, the "last seen" timestamp of the source address will be updated (--update).
  • Entries in the ftpdata list not seen in the last 1800 will be removed (--reap).

So, after the control connection was ACCEPTed, you have 1800 seconds to initiate data connections. After that time you will need to reopen the control connection to get the source address re-added to the ftpdata list.

An inconvenience of this solution if that ftp clients would not be able to initiate data connections after 1800 seconds of their last control connection establisment time. You could use 24h if you like, it will be less opened anyways than having the full port range permanently opened. You can also have a sequence like:

iptables -A INPUT -m state --state ESTABLISHED -p tcp --dport ftp -m recent --set
iptables -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT

to refresh the source address whenever an established control connection packet comes in but I prefer to have the --state RELATED,ESTABLISHED rule near the top.

Check also accept_timeout, data_connection_timeout and idle_session_timeout params of vsftpd.conf.