home January 01, 2017

VsFtpd


A Very Secure FTP Server

If you want to setup a highly secure, efficient and fast anonymous ftp server then you might want to consider VsFtpd. It is probably the most secure and fastest FTP server for UNIX-like systems.

Is vsftpd the right server for me?

If your main requirement from an FTP server is one of the following then yes, vsftpd is probably the FTP server you are looking for.

Despite being small for purposes of speed and security, many more complicated FTP setups are achievable with vsftpd. By no means an exclusive list, vsftpd will handle:

The only reason you might prefer a different FTP server to vsftpd is if you really need the configurability of one of the more bloated FTP servers. In this regard, vsftpd is a small modular component in the proper spirit of UNIX. Consider moving to vsftpd even if it means sacrificing some obscure feature of your current FTP server. The security, performance and stability gains are worth it. VsFtpd

Getting Started

In this exercise we are going to setup a stand alone ftp daemon listening on port 21. It will only allow anonymous read only access to the /ftp tree. The clients are going to be limited to the amount of total connects made, the amount of connects per client and the number of clients per ip address. The server is going to run with minimal privileges of the user "nobody" and full logging will be enabled. Finally, we are going to limit clients to specific connection timeouts and limit the commands we will accept from all ftp clients.

#######################################################
###  moneyslow.com  vsftpd.conf   BEGIN
#######################################################
# manpage: http://vsftpd.beasts.org/vsftpd_conf.html
# Setup specially for an OpenBSD install
#
# Run in daemon mode
background=YES
listen=YES
listen_address=120.111.222.111
#pasv_address=127.0.0.1
#
# The new highly restrictive seccomp filter sandbox
# If you see "OOPS: priv_sock_get_cmd" then disable seccomp
seccomp_sandbox=NO
#
# User to run daemon as
nopriv_user=_vsftpd
ftp_username=_ftp
#
# Ftp ports
connect_from_port_20=NO
ftp_data_port=20
listen_port=21
pasv_min_port=49152
pasv_max_port=65535
pasv_promiscuous=NO
port_enable=NO
port_promiscuous=NO
#
# SSL (force options for a SSL only server)
#ssl_enable=YES
#ssl_tlsv1=YES
#ssl_sslv2=NO
#ssl_sslv3=NO
#rsa_cert_file=/etc/ssl/private/vsftpd.pem
#allow_anon_ssl=YES
#force_anon_data_ssl=YES
#force_anon_logins_ssl=YES
#force_local_data_ssl=YES
#force_local_logins_ssl=YES
#
# Timeouts
connect_timeout=60
data_connection_timeout=120
idle_session_timeout=120
#
# Information messages
setproctitle_enable=YES
banner_file=/etc/banner
dirmessage_enable=YES
ftpd_banner=moneyslow.com ftp server
#
# Access limits and controls
async_abor_enable=NO
cmds_allowed=ABOR,APPE,CWD,DELE,HELP,LIST,MDTM,MKD,NLST,PASS,PASV,PWD,QUIT,RETR,RMD,RNFR,RNTO,SIZE,STOR,TYPE,USER
#cmds_allowed=ABOR,CWD,DELE,LIST,MDTM,MKD,NLST,PASS,PASV,PWD,QUIT,RETR,RMD,RNFR,RNTO,SIZE,STOR,TYPE,USER,ACCT,APPE,CDUP,HELP,MODE,NOOP,REIN,STAT,STOU,STRU,SYST
delay_successful_login=1
delete_failed_uploads=yes
guest_enable=NO
write_enable=YES
max_clients=100
max_login_fails=1
max_per_ip=2
pam_service_name=vsftpd
tcp_wrappers=NO
hide_file={.*,*.mp3}
deny_file={*.mp3}
#
# Preferences
ascii_upload_enable=NO
ascii_download_enable=NO
hide_ids=YES
ls_recurse_enable=NO
use_localtime=NO
#
# Allow anonymous FTP?
anonymous_enable=YES
anon_max_rate=0
anon_mkdir_write_enable=NO
anon_root=/disk01/ftp/
anon_world_readable_only=YES
anon_umask=0022
anon_upload_enable=NO
anon_other_write_enable=NO
no_anon_password=NO
#
# Allow local user access?
local_enable=YES
local_max_rate=0
local_umask=0022
chroot_local_user=YES
check_shell=NO
chmod_enable=NO
secure_chroot_dir=/var/empty
userlist_enable=YES
userlist_deny=NO
userlist_file=/etc/vsftpd_users
#
# Logging
dual_log_enable=NO
log_ftp_protocol=NO
vsftpd_log_file=/var/log/vsftpd.log
xferlog_enable=YES
xferlog_std_format=NO
xferlog_file=/var/log/xferlog
#
#######################################################
###  moneyslow.com  vsftpd.conf  END
#######################################################

Installing the package or building the binaries?

Option 1: installing from a pre made package is the easiest option. If you decide to install VsFtpd from the package system of your OS then get it now. Linux and OpenBSD both have ready made packages available for install.

Option 2: Installing from Source.

Step 1: First you need to download the latest source code for vsftpd. Make a directory to work in and change to that directory. We are going to use /tmp for the example. Goto the VsFtpd home page and get the latest tar ball. Then untar it in /tmp and change to the directory vsftpd un-tared into.

Step 2: You now need to build vsftpd. This line will build the binaries and install them into the default path /usr/local/

./configure && make && make install

Step 3: Now that vsftpd is built and installed download the vsftpd.conf file above and put it in /usr/local/etc/vsftpd.conf . You may find that some package maintainers put the conf file in a different place. Verify where the vsftpd.conf file before coping it over.

Looking at the vsftpd.conf

The config file has a lot of options and there a few that will need your attention before you are ready to start the daemon. Remember that entire books are written on VsFtpd and we can not cover every option here. For the options we do not cover please take a look at the VsFtpd project documentation.

Run in daemon mode specifies that the daemon should listen (always on) and run in the background.

Advertised ip (only if needed) is only necessary if you have a NAT'ed firewall and have another ftp server machine on the inside. You need to tell the ftp server what the ip of the outside interface is, so the server can tell the client. Ftp is really brain dead and this is just another example.

User to run daemon as will be the user "nobody" in the example.

Ftp ports section lists all of the port options. we will be listening on port 21 and the data connection will use 49152 through 65535. You can adjust the passive ftp port range to a smaller subset of port if you want to. It is not recommended to use passive or port promiscuous modes unless you understand the security implications.

SSL (force options for a SSL only server) are the options you need to adjust if you decide to use ssl authentication, ssl data encryption or both. SSL through ftp is mostly a hack and we would recommend using sftp through ssh if you need encryption.

Timeouts are the limits we are putting on the clients. if they do not do anything in the time specified they are disconnected.

Information messages lists the banners the client will see when the connect. The text file /etc/banner is the banner that a user will see when they first log in. The "dirmessage_enable=YES" option will print the contents of the file ".message" when a client changes directory.

Access controls and Preferences are the limits on the ftp client. We can not trust any of the clients so we will limit what commands we will accept, what files they can see and at what speed they can download at. You may want to closely look at "cmds_allowed" and see if you need to support all of the ftp command listed. For example, an anonymous ftp server normally only needs read, change dir and retrieval commands enabled. The site raw FTP commands will list out all of the ftp commands and their purposes.

Allow anonymous FTP? our server is going to allow anonymous access. So these options specify that anonymous is enabled, with a password and the user is read-only.

Allow local user access? local user accounts are enabled in the example. They are allowed to read and write into their own chroot'd ftp directory. We suggest making the ftp user without a valid shell and make their home directory under the ftp tree like, "/disk01/ftp/user/".

userlist_file=/etc/vsftpd_users is a white list of users you will allow to log in to the ftp server. Since all user names in the /etc/password file are allowed by default we need to make sure that only user we specify are allowed. If the user tries to log in with a username not in this list their connection will be immediately dropped. BTW, anonymous ftp users can come in with the username "ftp" or "anonymous". The format of the text file is one username per line like so:

root@machine# cat /etc/vsftpd_users
ftp
anonymous
bob
sally
devteam

Activate logging says the server will log all transactions. All transfers and client commands will be logged to /var/log/vsftpd.log . We have enabled "log_ftp_protocol=YES" which is debugging logging. This way you can spot any troubles with ftp clients, but you may want to turn this option off eventually to reduce the size of the log files.

OPTIONAL: Generating a RSA key for ssl connections

If you are going to accept SSL connections using the "ssl_enable=YES" in the section "SSL (force options for a SSL only server)" you need to make a private RSA key for your server. Openssl on your machine can make the new certificate with the following options. When you generate the key you can enter information about your location of leave it blank. It is your choice.

root@machine: openssl req -x509 -nodes -newkey rsa:1024 -keyout /etc/ssl/private/vsftpd.pem -out /etc/ssl/private/vsftpd.pem

Generating a 1024 bit RSA private key
.++++++
writing new private key to '/etc/ssl/private/vsftpd.pem'
-----
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) []:
State or Province Name (full name) []:
Locality Name (eg, city) []:
Organization Name (eg, company) []:
Organizational Unit Name (eg, section) []:
Common Name (eg, fully qualified host name) []:
Email Address []:

root@machine: ls -la /etc/ssl/private/vsftpd.pem
-rw-r--r--  1 root  wheel  1234 Jan 10 10:10 /etc/ssl/private/vsftpd.pem

Starting the daemon

Now that vsftpd is built and installed and the vsftpd.conf is in place we can now start the daemon. The daemon will run as the user you selected in the conf file, "nobody" for this example, so make sure that user exists. When the ftp server starts it will listen on port 21 be default.

To start the daemon execute the following:

/usr/local/sbin/vsftpd

Testing the ftp server

To test the server use your favorite ftp client and point it to the machine you started the daemon on. Log in anonymously with the user name "ftp". Notice that we used the directive "no_anon_password=NO" so the server will ask anonymous users for a password. If you turn off anonymous passwords then web browsers will not be able to log in. Once logged in you should be able to do a "ls -la" and see the files in the /ftp directory.

Questions?

Is there any way to monitor clients connected to vsftpd ? Yes. We actually have two slightly different methods to monitor vsftpd clients. First, make sure you have enabled the config option, "setproctitle_enable=YES" like in our example above and restart your vsftpd server. Then run the command "watch ps -C vsftpd -o user,pid,stime,cmd" to watch the processes including ip, username and actions like idle or data retrevial. Looks like so:

user@machine#  watch ps -C vsftpd -o user,pid,stime,cmd 

Every 2.0s: ps -C vsftpd -o user,pid,stime,cmd   Mon Jan 10 10:11:12 2020

USER       PID STIME CMD
root      3699 10:10 vsftpd: LISTENER
ftp       3989 10:20 vsftpd: 10.20.30.10: connected
ftp       3991 10:30 vsftpd: 10.20.30.10/vsftpd: RETR bigfile.bz2
ftp       3949 10:23 vsftpd: 10.40.40.20: connected
ftp       3943 10:36 vsftpd: 10.40.40.20/vsftpd: RETR /public/otherfile.bz2

Also, if you also have access to the program "dstat" you can use the following shell script. This will show you not only the information from above, but also real time system stats like send/recieve bandwidth, memory usage and disk I/O. This script will give you real time system stats as well as a 5 second snap image of who is on your vsftpd server.

#!/bin/sh
#
## moneyslow.com VsFTPd Watcher -- vsftpd_watcher.sh
#
while [ 1 ]
  do
    clear
    echo "  moneyslow.com VsFTPd watcher                      `date`"
    echo ""
    ps -C vsftpd -o user,pid,stime,cmd
    echo ""
  # echo "----total-cpu-usage---- -dsk/total- -net/total- ---paging-- ---system--"
  # echo "usr sys idl wai hiq siq| read  writ| recv  send|  in   out | int   csw "
    dstat 1 5
done

Some browsers are having problems using the ftp server! This may because of the use of "no_anon_password=YES". When the browser connects it send the "ftp" username to the server. If "no_anon_password=YES" is set to yes then the server logs the browser in. The problem is the browser is not smart enough to realize it. So the browser then sends another USER or PASSWD request and of course this is an error if you are already logged in. Most browsers will just get confused at this point and sit there doing nothing. To fix this you might try setting "no_anon_password=NO"

Vsftpd will not serve data mounted over NFS, the remote client locks up. The problem may be in your mount options used in NFS. Try unmounting the nfs volume and remounting it with "nolock" add to your mount options. BTW, as a reference here are the nfs mount options from /etc/fstab we found that work,

"vers=3,tcp,ro,bg,soft,retry=10,rsize=32768,wsize=32768,timeo=90,nolock"

Can a client continue a incomplete download without starting over? Yes. The server supports resumed uploads and downloads. Remember, the client must also have the ability to resume uploads and downloads. Also, make sure you allow the raw ftp command "APPE" in the config option "cmds_allowed=" like the example above.

Do I have to give ftp users a valid shell ? No, you do not. If you add a user to your server and they are retracted to ftp access only then change their shell to /sbin/nologin.

Anonymous login works, but users are denied. Whats wrong ? If you are using a Linux server then you are using PAM for authentication. Make sure you have the config option, "pam_service_name=vsftpd" enabled. Second, if you have setup your users so they can not log in to the machine with ssh, make sure you set the shell in /etc/passwd to "/sbin/nologin" and _NOT_ "/bin/false". Using "/bin/false" as the shell will stop that user from logging in at all with any protocol. Finally, if you set the user shell to /sbin/nologin then also make sure the config option, "check_shell=NO" is also set.

You may need to setup a new PAM authentication file too. For Redhat systems the following syntax will work. Not that there is a file called /etc/ftpusers but this is to be empty(!).

#%PAM-1.0
session    optional     pam_keyinit.so    force revoke
auth       required     pam_listfile.so item=user sense=deny file=/etc/ftpusers onerr=succeed
auth       required     pam_shells.so
auth       include      system-auth
account    include      system-auth
session    include      system-auth
session    required     pam_loginuid.so

These are some of the log errors you might see for any of the above issues.

FAIL DOWNLOAD: Client
FAIL LOGIN: Client
vsftpd: pam_listfile(vsftpd:auth): Refused user for service vsftpd
vsftpd: pam_listfile(vsftpd:auth): Couldn't open /etc/vsftpd/ftpusers