Setting up ProFTPD on Debian with Explicit FTPS and Alternate mod_auth_file File

Not a real step-by-step guide, but more like notes for future references. 

Revision history (dd/mm/yy):

09/09/2014 – minor changes to proftpd.conf.

17/10/2014 – removed SSLv3 from tls.conf.

Software

Software used in this article:

  1. Debian Wheezy
  2. ProFTPD 1.3.4a
  3. OpenSSL 1.0.1e

Pre-Installation Notes

NOTE 1: our server is behind NAT, therefore we’ll use a passive FTP mode to connect from outside. Mikrotik router’s NAT configuration (SSH method) is provided.

NOTE 2: we’ll be using mod_auth_file for FTP authentication.

NOTE 3: we’ll use “DefaultServer on” with no additional VirtualHosts.

Installation

Install openssl and proftpd (choose standalone version):

# apt-get update && apt-get install proftpd openssl
[...]
Run proftpd: standalone
[...]

Configuration

We will create a new directory for FTP uploads. We will also prevent other users from removing or renaming a file in the directory unless they own the file or the directory:

# mkdir -m 1777 /ftp

Double-check permissions:

# ls -ld /ftp
drwxrwxrwt 2 root root 4096 Jan 25 21:36 /ftp/

Navigate to the proftpd installation directory:

# cd /etc/proftpd

Backup the default configuration files first:

# cp ./proftpd.conf ./proftpd.conf.$(date +%F)
# cp ./tls.conf ./tls.conf.$(date +%F)
# cp ./virtuals.conf ./virtuals.conf.$(date +%F)

Create a new folder to store an FTP authentication file as well as prevent world from accessing it:

# mkdir -m 0770 ./auth
# chown proftpd ./auth

Check permissions:

# ls -ld ./auth
drwxrwx--- 2 proftpd root 4096 Jan 26 18:14 ./auth/

List the five biggest UIDs that are already in use:

# cat /etc/passwd | cut -d: -f3 | sort -n | tail -n 5
1001
1002
1003
1004
65534

Create a new FTP user for sandy with UID of 1100 (not in use):

# ftpasswd --passwd --file=/etc/proftpd/auth/users.passwd --name=sandy --home=/ftp \
--shell=/bin/false --uid=1100 --gid=1100

Consult the man page of ftpasswd for more info if required.

Let’s see the auth file’s content:

# cat ./auth/users.passwd
sandy:$1$a3lD4ThisIsNotARealPassword6m5Z2:1100:1100::/ftp:/bin/false

Make file readable for proftpd user:

# chown proftpd /etc/proftpd/auth/users.passwd

Create a new folder to store SSL certificates:

# mkdir /etc/proftpd/ssl

Generate an SSL certificate for FTPS:

# openssl req -new -x509 -days 1825 -sha256 -nodes -out ./ssl/server.crt \
-keyout ./ssl/server.key
Generating a 2048 bit RSA private key
...........+++
.................................................................................+++
writing new private key to './server.key'
-----
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [AU]:GB
State or Province Name (full name) [Some-State]:Outer Space
Locality Name (eg, city) []:Nibiru
Organization Name (eg, company) [Internet Widgits Pty Ltd]:ftp.example.com
Organizational Unit Name (eg, section) []:
Common Name (e.g. server FQDN or YOUR name) []:ftp.example.com
Email Address []:[email protected]

Make SSL certificates non world-readable:

# chmod 0440 ./ssl/*

proftpd.conf

Here’s our proftpd.conf configuration:

# cat ./proftpd.conf
#/etc/profptd/proftpd.conf

#######################################################################
# Server Config                                                       #
#######################################################################

Include			/etc/proftpd/modules.conf
Include 		/etc/proftpd/tls.conf

ServerName		"Private FTP Server"
ServerType		standalone
ServerAdmin		[email protected]
DefaultServer		on
AccessGrantMsg		"User %u logged in."

# keep the required auth module only
AuthOrder		mod_auth_file.c

UseReverseDNS		off
RequireValidShell       off

# we want the main server instance to listen on a specific IP
DefaultAddress          localhost
Port			21
PassivePorts            64000 65000

# never ever run as root
User			proftpd
Group			nogroup

# pid file
ScoreboardFile		/var/run/proftpd.score

# for DOS prevention, only works in standalone mode
MaxInstances		20

# for passive FTP mode
MasqueradeAddress	54.X.Y.Z

MultilineRFC2228	on
ShowSymlinks		off
UseIPv6			off
DefaultTransferMode	binary

# DebugLevel only applies to SystemLog files
DebugLevel              0 
TransferLog		/var/log/proftpd/xferlog
SystemLog		/var/log/proftpd/proftpd.log
WtmpLog                 off

#######################################################################
# Global Config                                                       #
#######################################################################

<Global>
 RootLogin		off
 AuthPAM                off
 AuthUserFile           /etc/proftpd/auth/users.passwd

 # jailing
 DefaultRoot		/ftp
 #DefaultChdir		/ftp/shared

 # give out minimal information
 ServerIdent		on "Private FTP Server"
 IdentLookups		off

 # no welcome message until user has authenticated
 DeferWelcome           off
 DisplayLogin		/etc/proftpd/welcome.msg
 DisplayConnect         /etc/issue.net

 TimeoutLogin		120
 TimeoutNoTransfer	300
 TimeoutStalled		3600
 TimeoutIdle		600

 MaxClients 		5 "Sorry, ftp server has reached its maximum user limit (%m)"
 MaxClientsPerUser 	5 "Sorry, no more than %m connections per user."

 # restrict sandy's uploads to 1 gigabyte per file
 MaxStoreFileSize       1 Gb user sandy 

 # allow unlimited upload and download size for everyone else
 MaxStoreFileSize       *
 MaxRetrieveFileSize    *

 MaxLoginAttempts	3
 DenyFilter		\*.*/

 Umask			022 
 AllowOverwrite		on
 AllowOverride		off

 # allow to resume not only the downloads, but the uploads too
 AllowRetrieveRestart	on
 AllowStoreRestart	on

 RequireValidShell	off
</Global>

# Delay engine reduces impact of the so-called Timing Attack
<IfModule mod_delay.c>
 DelayEngine on
</IfModule>

<Limit SITE_CHMOD>
 DenyAll
</Limit>

#######################################################################
# VirtualHosts #
#######################################################################

# for future use
Include /etc/proftpd/virtuals.conf

tls.conf

Here’s our tls.conf configuration:

# cat ./tls.conf
<IfModule mod_tls.c>
TLSEngine on
TLSRequired on
TLSProtocol TLSv1
TLSRSACertificateFile /etc/proftpd/ssl/server.crt
TLSRSACertificateKeyFile /etc/proftpd/ssl/server.key
TLSVerifyClient off
TLSOptions AllowClientRenegotiations NoSessionReuseRequired
TLSLog /var/log/proftpd/tls.log
</IfModule>

virtuals.conf

The virtuals.conf file contains no virtual hosts:

# cat ./virtuals.conf
# this file is empty

welcome.msg

Here’s our welcome.msg configuration:

# cat ./welcome.msg
Welcome %U from %R.
You are user number %N of %M allowed.
This is a private FTP system - no anonymous logins. 
You will be disconnected after 10 minutes of inactivity.

Restart ProFTPD Daemon

# service proftpd restart
[ ok ] Stopping ftp server: proftpd.
[....] Starting ftp server: proftpdlocal proftpd[5395] 127.0.0.1: 127.0.0.1:21 masquerading as 54.X.Y.Z
. ok

Configure NAT on Mikrotik RouterOS

TCP ports 21 and 64000-65000 need to be forwarded on Mikrotik router (as well as opened on iptables firewall) for public access. Do via SSH:

[sandy@mikrotik] > ip firewall nat
[sandy@mikrotik] /ip firewall nat> add chain=dstnat dst-address=54.X.Y.Z protocol=tcp dst-port=21 action=dst-nat to-addresses=10.X.Y.Z to-ports=21
[sandy@mikrotik] /ip firewall nat> add chain=dstnat dst-address=54.X.Y.Z protocol=tcp dst-port=64000-65000 action=dst-nat to-addresses=10.X.Y.Z to-ports=64000-65000

Connect with FileZilla Client from a Public Network

Connection details:
Host: ftpes://ftp.example.com
Username: sandy
Passwd: **********
Port: 21

We’ll be asked to accept the self-signed SSL certificate:

FileZilla client log:

Status: Resolving address of ftp.example.com
Status: Connecting to 54.X.Y.Z:21...
Status: Connection established, waiting for welcome message...
Response: 220 Private FTP Server
Command: AUTH TLS
Response: 234 AUTH TLS successful
Status: Initializing TLS...
Status: Verifying certificate...
Command: USER sandy
Status: TLS/SSL connection established.
Response: 331 Password required for sandy
Command: PASS ************
Response: 230-Welcome sandy from 91.X.Y.Z.
Response: 230-You are user number 1 of 10 allowed.
Response: 230-This is a private FTP system - no anonymous logins. 
Response: 230-You will be disconnected after 10 minutes of inactivity.
Response: 230 User sandy logged in.
Command: OPTS UTF8 ON
Response: 200 UTF8 set to on
Command: PBSZ 0
Response: 200 PBSZ 0 successful
Command: PROT P
Response: 200 Protection set to Private
Status: Connected
Status: Retrieving directory listing...
Command: PWD
Response: 257 "/" is the current directory
Status: Directory listing successful

Bugs

When installing ProFTPD on Ubuntu 14.04, you may notice the service being killed when cron runs logrotate:

ProFTPD killed (signal 15)
ProFTPD 1.3.5rc3 standalone mode SHUTDOWN

The workaround is to open the /etc/init.d/proftpd file and change the following line:

start-stop-daemon --stop --signal $SIGNAL --quiet --pidfile "$PIDFILE"

to:

start-stop-daemon --stop --signal $SIGNAL --retry 1 --quiet --pidfile "$PIDFILE"

You can test if ProFTPD is working after logrotate by running:

# logrotate -vf /etc/logrotate.conf

6 thoughts on “Setting up ProFTPD on Debian with Explicit FTPS and Alternate mod_auth_file File

  1. which parameter specifies ftpEs?
    e.g. for vsftpd it is: implicit_ssl=NO
    this configuration above seems like a configuration for ftpS.

    • Thanks for your input. As the article name implies, this configuration is for explicit FTPS (aka FTPES).

      I’m not aware of any ProFTPD parameter that particularly specifies FTPES, but if you want to use an implicit FTPS mode, you need to specify “UseImplicitSSL” under TLSOptions and probably use the standard implicit FTPS port 990.

  2. The best How-To I’ve found about a ftp server. After hours of read and search, you made my ftp server operate. Thanks for your tutorial!

  3. I have followed the guide, im on a Debian 8.6. and i cannot get it working. Im almost there i think. When i try to login via filezilla i always get :

    USER forensik
    Svar: 331 Password required for forensik
    Kommando: PASS **********
    Svar: 530 Login incorrect.
    Fel: Critical error, could not connect to server.

    The TLS fase is just going fine, i even tried to reinstall my proftpd and install a new one. Anyone know whats going on? I have tried both locally and from the internet, with the same result

    • Where is the FTP auth file located, and what are the permissions set on the file? Can you post the content of the file, removing any password hashes?

Leave a Reply

Your email address will not be published. Required fields are marked *