* http://www.debiansec.com/linux/services/ftp.html, 2004/9
|
contents |
This tutorial is split up into the following topics:
Appendixes:
|
|
introduction |
This tutorial has actually being written because more and more people are trying to setup a ftp service,
but mainly choose software with a bad security history like wu-ftpd for that task. My personal suggestion for a
ftp server is vsftpd because of it's security,
performance and stability.
We will be using virtual users here since they do not have real privileges - unlike real system users. For additional
information please consult the faq.
|
|
installation |
Before we can start with the real topic of this tutorial, we need to install vsftpd of course. Since we want to
run vsftpd with virtual users and a per-user configuration we require at least version 1.1.0
of vsftpd. I have been using a backport of vsftpd 1.2.1-1
when writing this tutorial.
If your distribution is Debian/GNU Linux, you need to either backport it yourself or use my backport of vsftpd, since
currently vsftpd 1.0.0-2 is in stable and
1.2.1-1 in testing. For other distributions you should check with your distribution if you can rely on
a pre-built vsftpd.
|
|
base configuration |
We will not start using a bloated standard configuration and adopt that to our needs - which is the way most people
set up their services - no, we will configure from scratch changing the default values only where required:
/etc/vsftpd.conf (without chmod capabilities) |
|
The above configuration in combination with the default values of vsftpd provides a pretty secure
default configuration, which we will then override on a per-user basis.
However if you require the capability to chmod then the above configuration will not work since this
is not allowed for anonymous users. You should only use the configuration file below if you do really
require chmod capabilites. You would require chmod capabilites for instance when the users should be
able to change the permissions of "sensitive" information from the default umask you have
specified in the per-user configuration.
/etc/vsftpd.conf (with chmod capabilities) |
|
Now we need to:
- create directory /etc/vsftpd
- create directory /etc/vsftpd/users
- write list of denied users to /etc/vsftpd/denied_users
I suggest adding every system user in /etc/vsftpd/denied_users so no
system user is asked for submisson of the password in plaintext. Use cat /etc/passwd | cut -d ":" -f 1 | sort > /etc/vsftpd/denied_users
for creating that file.
Now when a user, who is listed in /etc/vsftpd/denied_users attempts to login, the
session will be terminated before prompting for the password like illustrated below:
example ftp session for denied user |
Connected to 192.168.0.1.
220 (vsFTPd 1.2.0)
Name (192.168.0.1:root): root
530 Permission denied.
Login failed.
ftp> quit
221 Goodbye.
|
|
|
|
xinetd vs. standalone |
If you like to use the power of xinetd, for instance to restrict the usage of the ftp server
to a specified time range or a couple of ip addresses, you can launch vsftpd from xinetd.
For that purpose you will require to change the base configuration, in detail remove
the listen and listen_address configuration option and configure your xinetd
service:
The above configuration will of course need to be adjusted for your needs, like you probably
want to limit the number of concurrent sessions (instances)
even more or ban a couple of subnetworks (no_access).
The banner_fail file could look like:
/etc/vsftpd/busy_banner |
421 Server busy, please try again later! |
|
|
PAM configuration |
After providing the username and verifiying it is not contained in /etc/vsftpd/denied_users, we still can not
login since we have nothing left to authentificate against left - assuming our /etc/vsftpd/denied_users always
contains all usernames from /etc/passwd.
Therefore we now need to configure our real authentification which will be based upon PAM. As example we can
authentificate against a username/password file in common database format:
/etc/pam.d/ftp |
auth required /lib/security/pam_userdb.so db=/etc/vsftpd/accounts
account required /lib/security/pam_userdb.so db=/etc/vsftpd/accounts
|
|
|
|
creating virtual users (PAM) |
Before being able to login, we need to create a valid user. Depending on the PAM authentification backend this
steps could vary. For instance when using a database as authentification backend you would require addind that user
to the specified table.
If you would like to follow from the above PAM sample configuration, you will need the db_load
program for creating the file in common database format. When using Debian just apt-get install libdb3-util. Afterwards
you need to create a file which contains the login and on the next line the password:
sample accounts.tmp (for building accounts.db) |
user1
password_for_user1
user2
password_for_user2
|
After creating the accounts.tmp, which is just a list of usernames and passwords, you need to
build the database with db3_load -T -t hash -f accounts.tmp /etc/vsftpd/accounts.db. Afterwards
you can erase your accounts.tmp since it is no longer required - until you upgrade your username/password database. You
should now set pretty restrictive permissions to the database: chmod 600 /etc/vsftpd/accounts.db
|
|
virtual user configuration |
Depending on your base configuration, you have a different per-user configuration:
/etc/vsftpd/users/user1 (without chmod capabilites) |
|
If you require chmod capabilities and have specified that in your base configuration, you
will go for the following:
/etc/vsftpd/users/user1 (with chmod capabilites) |
|
|
|
appendix a: vsftpd configuration options |
The configuration file takes a couple of options, which are partly explained shortly below. For more information
please refer to the vsftpd.conf man page, where this information has been stripped off.
option | description |
anon_umask |
The value that the umask for file creation is set to for anonymous users. |
anon_mkdir_write_enable |
If set to YES, anonymous users will be permitted to create new directories under certain conditions. For this to work, the option write_enable must be activated, and the anonymous ftp user must have write permission on the parent directory. |
anon_other_write_enable |
If set to YES, anonymous users will be permitted to perform write operations other than upload and create directory, such as deletion and renaming. This is generally not recommended but included for completeness. |
anon_upload_enable |
If set to YES, anonymous users will be permitted to upload files under certain conditions. For this to work, the option write_enable must be activated, and the anonymous ftp user must have write permission on desired upload locations. |
anon_world_readable_only |
When enabled, anonymous users will only be allowed to download files which are world readable. This is recognising that the ftp user may own files, especially in the presence of uploads. |
anonymous_enable |
Controls whether anonymous logins are permitted or not. |
async_abor_enable |
When enabled, a special FTP command known as "async ABOR" will be enabled. Only ill advised FTP clients will use this feature. Addtionally, this feature is awkward to handle, so it is disabled by default. Unfortunately, some FTP clients will hang when cancelling a transfer unless this feature is available, so you may wish to enable it. |
chroot_local_user |
If set to YES, local users will be placed in a chroot() jail in their home directory after login. |
connect_from_port_20 |
This controls whether PORT style data connections use port 20 (ftp-data) on the server machine. For security reasons, some clients may insist that this is the case. Conversely, disabling this option enables vsftpd to run with slightly less privilege. |
dirlist_enable |
If set to NO, all directory list commands will give permission denied. |
download_enable |
If set to NO, all download requests will give permission denied. |
guest_enable |
If enabled, all non-anonymous logins are classed as "guest" logins. A guest login is remapped to the user specified in the guest_username setting. |
guest_username |
This setting is the real username which guest users are mapped to. |
hide_ids |
If enabled, all user and group information in directory listings will be displayed as "ftp". |
listen |
If enabled, vsftpd will run in standalone mode. This means that vsftpd must not be run from an inetd of some kind. Instead, the vsftpd executable is run once directly. vsftpd itself will then take care of listening for and handling incoming connections. |
listen_address |
If vsftpd is in standalone mode, the default listen address (of all local interfaces) may be overridden by this setting. Provide a numeric IP address. |
local_enable |
Controls whether local logins are permitted or not. If enabled, normal user accounts in /etc/passwd may be used to log in. |
local_root |
This option represents a directory which vsftpd will try to change into after a local (i.e. non-anonymous) login. Failure is silently ignored. |
local_umask |
The value that the umask for file creation is set to for local users. |
max_clients |
If vsftpd is in standalone mode, this is the maximum number of clients which may be connected. Any additional clients connecting will get an error message. |
max_per_ip |
If vsftpd is in standalone mode, this is the maximum number of clients which may be connected from the same source internet address. A client will get an error message if they go over this limit. |
nopriv_user |
This is the name of the user that is used by vsftpd when it want to be totally unprivileged. Note that this should be a dedicated user, rather than nobody. The user nobody tends to be used for rather a lot of important things on most machines. |
pam_service_name |
This string is the name of the PAM service vsftpd will use. |
pasv_max_port |
The maximum port to allocate for PASV style data connections. Can be used to specify a narrow port range to assist firewalling. |
pasv_min_port |
The minimum port to allocate for PASV style data connections. Can be used to specify a narrow port range to assist firewalling. |
session_support |
This controls whether vsftpd attempts to maintain sessions for logins. If vsftpd is maintaining sessions, it will try and update utmp and wtmp. It will also open a pam_session if using PAM to authenticate, and only close this upon logout. You may wish to disable this if you do not need session logging, and you wish to give vsftpd more opportunity to run with less processes and / or less privilege. |
use_localtime |
If enabled, vsftpd will display directory listings with the the time in your local time zone. The default is to display GMT. The times returned by the MDTM FTP command are also affected by this option. |
user_config_dir |
This powerful option allows the override of any config option specified in the manual page, on a per-user basis. Usage is simple, and is best illustrated with an example. If you set user_config_dir=/etc/vsftpd_user_conf and then log on as the user "chris", then vsftpd will apply the settings in the file /etc/vsftpd_user_conf/chris for the duration of the session. |
userlist_enable |
If enabled, vsftpd will load a list of usernames, from the filename given by userlist_file. If a user tries to log in using a name in this file, they will be denied before they are asked for a password. This may be useful in preventing cleartext passwords being transmitted. |
userlist_file |
This option is the name of the file loaded when the userlist_enable option is active. |
virtual_use_local_privs |
If enabled, virtual users will use the same privileges as local users. By default, virtual users will use the same privileges as anonymous users, which tends to be more restrictive (especially in terms of write access). |
write_enable |
This controls whether any FTP commands which change the filesystem are allowed or not. These commands are: STOR, DELE, RNFR, RNTO, MKD, RMD, APPE and SITE. |
xferlog_enable |
If enabled, a log file will be maintained detailling uploads and downloads. |
|
|
appendix b: xinetd configuration options |
The xinetd configuration file takes a couple of different options, which are explained
shortly below. For more information please refer to the xinetd.conf man page, where this
information has been stripped off.
option | description |
banner_fail |
Takes the name of a file to be splatted at the remote host when a connection to that service is denied. This
banner is printed immediately upon denial of access.
This is useful for informing your users that they are doing something bad and they
shouldn't be doing it anymore.
|
disable |
This is boolean "yes" or "no". This will result in the service being disabled and not starting. |
instances |
Determines the number of servers that can be simultaneously active for a service (the
default is no limit). The value of this attribute can be either a number or UNLIMITED
which means that there is no limit.
|
log_on_failure |
Determines what information is logged when a server cannot be started (either because of
a lack of resources or because of access control restrictions). The service id is always
included in the log entry along with the reason for failure.
|
log_on_success |
Determines what information is logged when a server is started and when that server exits
(the service id is always included in the log entry).
|
no_access |
Determines the remote hosts to which the particular service is unavailable. Its value can
be specified in the same way as the value of the only_from attribute. These two
attributes determine the location access control enforced by xinetd. If none of the two
is specified for a service, the service is available to anyone. If both are specified for
a service, the one that is the better match for the address of the remote host determines
if the service is available to that host (for example, if the only_from list contains
128.138.209.0 and the no_access list contains 128.138.209.10 then the host with the
address 128.138.209.10 can not access the service).
|
only_from |
Determines the remote hosts to which the particular service is available. Its value is a
list of IP addresses which can be specified in any combination of the following ways:
-
a numeric address in the form of %d.%d.%d.%d. If the rightmost components are 0,
they are treated as wildcards (for example, 128.138.12.0 matches all hosts on the
128.138.12 subnet). 0.0.0.0 matches all Internet addresses.
-
a factorized address in the form of %d.%d.%d.{%d,%d,...}. There is no need for all
4 components (i.e. %d.%d.{%d,%d,...%d} is also ok). However, the factorized part
must be at the end of the address.
-
a network name (from /etc/networks).
-
a host name. When a connection is made to xinetd, a reverse lookup is performed,
and the canonical name returned is compared to the specified host name. You may
also use domain names in the form of .domain.com. If the reverse lookup of the
client's IP is within .domain.com, a match occurs.
-
an ip address/netmask range in the form of 1.2.3.4/32.
|
per_source |
Takes an integer or "UNLIMITED" as an argument. This specifies the maximum
instances of this service per source IP address.
|
server |
Determines the program to execute for this service |
server_args |
Determines the arguments passed to the server. |
socket_type |
Possible values for this attribute include:
dgram |
|
datagram-based service |
raw |
|
service that requires direct access to IP |
seqpacket |
|
service that requires reliable sequential datagram transmission |
stream |
|
stream-based service |
|
user |
Determines the uid for the server process. The user name must exist in /etc/passwd. This
attribute is ineffective if the effective user ID of xinetd is not super-user.
|
wait |
This attribute determines if the service is single-threaded or multi-threaded. If its
value is yes the service is single-threaded; this means that xinetd will start the server
and then it will stop handling requests for the service until the server dies. If the
attribute value is no, the service is multi-threaded and xinetd will keep handling new
service requests.
|
|
|
appendix c: faq |
If you have a question regarding vsftpd which has not been answered in any section
of this tutorial, feel free to email your question to website@linux-corner.net.
Frequently asked questions which have already been answered:
Firewalling information
|
The configuration options pasv_max_port and pasv_min_port
assist you in firewalling:
-
INPUT chain:
-
tcp
new/established
source port: 1024 - 65535
destination port: 21
-
tcp
new/established/related
destination port: pasv_min_port - pasv_max_port
-
OUTPUT chain:
-
tcp
related/established
source port: 20
destination port: 1024 - 65535
-
tcp
established
source port: 21
destination port: 1024 - 65535
-
tcp
established
source port: pasv_min_port - pasv_maxport
destination port: 1024 - 65535
With the above information (protocol, connection status, ports) you
should be able to write the iptables ruleset. Your kernel needs to support connection tracking though; additionally you will require
to use the ip_conntrack_ftp module of netfilter.
|
Where can I find binary packages for other distributions than Debian?
|
If you are not using Debian you are probably looking for RPM packages. I suggest you take a look at
rpmseek.com. Here you can probably also
find the db_load program used for creating virtual users with the common database format.
|
Why do you prefer vsftpd?
|
I could quote that mostly from the vsftpd website.
I am using vsftpd for it's excellent points in the following areas:
- security
- stability
- performance
I am not really quoting it, I have verified all of the above points and I would not be using
vsftpd if it would not perform that excellent. I know that there are other ftp servers out that
are said to be secure, however until now I have not verified others.
|
Why should one disallow system users?
|
The typical system user has a lot of more privileges than required for the standard FTP
user - like shell access. Granting each ftp user the privileges of a system user will
definately affect system security, also since FTP transmitts passwords in
cleartext. You can limit your real system users to not being
able to login, however in that case there is no reason why you should not go for
virtual users.
Immagine the root user logs in at the ftp server, the password is transmitted in cleartext
and it is PRETTY easy to sniff out the password with standard tools. Do you really want to
share passwords for users with probably unneccessary privileges with the whole world?
|
|
top
|
|