Proper way to handle FTP over SSL with restrictive firewall rules

firewallftpftpsiptablesssl

Without SSL, FTP works fine over a stateful Firewall, like netfilter (iptables) + the nf_conntrack_ftp kernel module like this:

# modprobe nf_conntrack_ftp
# iptables -A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
# iptables -A INPUT -p tcp --dport 21 -j ACCEPT

The problem is that, when SSL is used, the FTP connection tracking module cannot work because it is unable to spy on the session to discover the session-port chosen for data exchange. It is thus unable to open that port dynamically.

Is there a proper way to make a SSL-enabled FTP server work, without disabling the firewall?

For information, I use vsftpd with the ssl_enable=YES configuration option.

Best Answer

There are several modes with SSL and FTP:

  • Implicit SSL, that is SSL from start (usually port 990) and never plain text. In this case you get no clear text information at the firewall about the dynamic data ports and thus cannot restrict communication to only these ports.
  • Explicit SSL with "AUTH TLS" command before login to enable SSL but without CCC after login to disable SSL. Here you have the same problem as with implicit SSL, that is you cannot read which data ports are in use.
  • Explicit SSL as before but with CCC command after login. In this case the login is protected by SSL, but the rest of the control connection uses plain text. The data transfer can still be protected by SSL. You must enable this mode at the client, like with ftp:ssl-use-ccc with lftp. There is no way to enforce this mode at the ftp server.

If you cannot get the exact data ports because the relevant commands are encrypted you could at least make the firewall a bit less restrictive:

  • In active mode ftp the server will originate the data connections from port 20 so you can have an iptables rule allowing these connections, i.e. something like iptables -A OUTPUT -p tcp --sport 20 -j ACCEPT and additionally accept established connections.
  • In passive mode ftp you could restrict the port range offered by vsftpd with pasv_max_port and pasv_min_port settings and add a matching rule like iptables -A INPUT -p tcp --dport min_port:max_port -j ACCEPT. This is not very restrictive but at least more restrictive than disabling the firewall.
Related Question