446 lines
12 KiB
Markdown
446 lines
12 KiB
Markdown
# Vsftpd Setup
|
|
|
|
## Contents
|
|
|
|
- [Overview](#overview)
|
|
- [Installation](#installation)
|
|
- [Configuration Files](#configuration-files)
|
|
- [Configuration Basics](#configuration-basics)
|
|
- [TCP Wrappers](#tcp-wrappers)
|
|
- [Login Banner](#login-banner)
|
|
- [Directory Message](#directory-message)
|
|
- [Logging](#logging)
|
|
- [Local Users](#local-users)
|
|
- [Chroot Security](#chroot-security)
|
|
- [Access Control](#access-control)
|
|
- [Anonymous FTP](#anonymous-ftp)
|
|
- [Connection Restrictions](#connection-restrictions)
|
|
- [SSL Connections](#ssl-connections)
|
|
- [Active vs. Passive](#active-vs-passive)
|
|
- [Virtual chroot Users](#virtual-chroot-users)
|
|
- [vsftpd.conf](#vsftpdconf)
|
|
- [PAM ftp](#pam-ftp)
|
|
- [SELinux](#selinux)
|
|
- [Adding a User](#adding-a-user)
|
|
- [Reloading Users](#reloading-users)
|
|
- [Updating a User](#updating-a-user)
|
|
- [Removing a User](#removing-a-user)
|
|
- [References](#references)
|
|
|
|
|
|
## Overview
|
|
|
|
[vsftpd](https://security.appspot.com/vsftpd.html) is a GPL licensed FTP server for UNIX systems, including Linux. It is the default FTP server daemon as installed and taught by Red Hat, and as such enjoys the status of being the most popular FTP daemon in modern use with most Linux distributions. As a precursor, it's recommended to fully understand Active vs. Passive FTP mode:
|
|
|
|
- <http://slacksite.com/other/ftp.html>
|
|
|
|
This document will cover the basic installation and configuration of vsftpd; more options are available in the *vsftpd.conf* man page.
|
|
|
|
|
|
## Installation
|
|
|
|
The vsftpd daemon is included in the core distribution repositories:
|
|
|
|
```
|
|
## RHEL / CentOS
|
|
yum -y install vsftpd
|
|
service vsftpd start && chkconfig vsftpd on
|
|
|
|
## Debian / Ubuntu
|
|
apt-get update && apt-get -y install vsftpd
|
|
mkdir /etc/vsftpd /var/ftp
|
|
```
|
|
|
|
**NOTE**: on Ubuntu the _vsftpd_ service is controlled by Upstart; it's automatically started and enabled by default. On Debian the `insserv` command must be used to enable it.
|
|
|
|
|
|
## Configuration Files
|
|
|
|
There's one key difference between the distributions:
|
|
|
|
| **RHEL / CentOS** | **Debian / Ubuntu** |
|
|
| ------------------------- | ------------------- |
|
|
| `/etc/vsftpd/vsftpd.conf` | `/etc/vsftpd.conf` |
|
|
| `/etc/vsftpd/ftpusers` | `/etc/ftpusers` |
|
|
|
|
This also extends into the entire `/etc/vsftpd/` subdirectory and a default directory for anonymous users in `/var/ftp/` which are only present on a RHEL-style installations from the package install. The Ubuntu package comes with both a systemd and upstart service that are not present on Debian; creating an `/etc/vsftpd/` to work in on these distributions is preferred to allow for cross-distro compatibility in setup below.
|
|
|
|
|
|
## Configuration Basics
|
|
|
|
All options refer to the `vsftpd.conf` configuration file and are detailed in the man page; other options exist than the ones listed herein.
|
|
|
|
### TCP Wrappers
|
|
|
|
```
|
|
# Disable TCP Wrappers
|
|
tcp_wrappers=NO
|
|
```
|
|
|
|
### Login Banner
|
|
|
|
```
|
|
# Set a direct banner (hide name, version, etc.)
|
|
ftpd_banner=FTP server ready.
|
|
|
|
# Overrides 'ftpd_banner' by specifying a filename
|
|
banner_file=/etc/vsftpd/banner.txt
|
|
```
|
|
|
|
### Directory Message
|
|
|
|
```
|
|
# Shown when changing into the directory
|
|
message_file=.message
|
|
dirmessage_enable=YES
|
|
```
|
|
|
|
### Logging
|
|
|
|
```
|
|
# Log all uploads and downloads
|
|
xferlog_enable=YES
|
|
|
|
# Log all FTP commands
|
|
log_ftp_protocol=YES
|
|
xferlog_std_format=NO
|
|
|
|
# Log transfers to both /var/log/xferlog and /var/log/vsftpd.log
|
|
dual_log_enable=YES
|
|
```
|
|
|
|
### Local Users
|
|
|
|
```
|
|
# Disable 'write' (upload)
|
|
write_enable=NO
|
|
|
|
# Disable local users
|
|
local_enable=NO
|
|
```
|
|
|
|
### Chroot Security
|
|
|
|
By default users are **not** in a chroot upon login.
|
|
|
|
```
|
|
# Basic Local user login chroot to home directory
|
|
chroot_local_user=YES
|
|
chroot_list_enable=NO
|
|
|
|
# Enable list of users ONLY to chroot
|
|
chroot_local_user=NO
|
|
chroot_list_enable=YES
|
|
chroot_list_file=/etc/vsftpd/chroot_list
|
|
|
|
# Enable list of users NOT to chroot
|
|
chroot_local_user=YES
|
|
chroot_list_enable=YES
|
|
chroot_list_file=/etc/vsftpd/chroot_list
|
|
```
|
|
|
|
### Access Control
|
|
|
|
By default, User ACLs are enabled in `/etc/pam.d/vsftpd` using the `/etc/ftpusers` / `/etc/vsftpd/ftpusers` file:
|
|
|
|
```
|
|
auth required pam_listfile.so item=user sense=deny file=/etc/vsftpd/ftpusers onerr=succeed
|
|
```
|
|
|
|
To also allow manipulation by Group, a line can be added right below it using a (new) group file:
|
|
|
|
```
|
|
auth required pam_listfile.so item=group sense=deny file=/etc/vsftpd/ftpgroups onerr=succeed
|
|
```
|
|
|
|
Within `vsftpd.conf` are parameters determining how the ACLs are used:
|
|
|
|
```
|
|
# Should be configured already by upstream packagers
|
|
pam_service_name=vsftpd
|
|
|
|
# Enable list of users ONLY allowed to log in
|
|
userlist_enable=YES
|
|
userlist_deny=NO
|
|
userlist_file=/etc/vsftpd/ftpusers
|
|
|
|
# Enable list of users NEVER allowed to log in
|
|
userlist_enable=YES
|
|
userlist_deny=YES
|
|
userlist_file=/etc/vsftpd/ftpusers
|
|
```
|
|
|
|
### Anonymous FTP
|
|
|
|
```
|
|
# Enable anonymous FTP w/password (email address, usually)
|
|
ftp_username=ftp
|
|
anonymous_enable=YES
|
|
anon_root=/var/ftp
|
|
anon_max_rate=0 # bytes/second, 0 = unlimited
|
|
anon_umask=077
|
|
|
|
# Enable only anon users who specify a certain email as password
|
|
no_anon_password=NO
|
|
secure_email_list_enable=YES
|
|
email_password_file=/etc/vsftpd/email_passwords
|
|
|
|
# Reverse the above, deny these emails when used as anon password
|
|
deny_email_enable=YES
|
|
banned_email_file=/etc/vsftpd/banned_emails
|
|
|
|
# Allow anon users to upload/delete/etc. (requires write_enable=YES)
|
|
anon_mkdir_write_enable=YES
|
|
anon_other_write_enable=YES
|
|
anon_upload_enable=YES
|
|
anon_world_readable_only=YES
|
|
chown_uploads=YES
|
|
chown_username=ftp
|
|
```
|
|
|
|
### Connection Restrictions
|
|
|
|
```
|
|
# Change limits and umask
|
|
connect_timeout=60 # in seconds
|
|
data_connection_timeout=300
|
|
idle_session_timeout=300
|
|
max_clients=2000
|
|
max_per_ip=10
|
|
max_login_fails=3
|
|
delay_failed_login=1 # in seconds
|
|
local_max_rate=0 # bytes/second, 0 = unlimited
|
|
local_umask=077
|
|
```
|
|
|
|
It's preferred to use `iptables` to perform restrictions at the IP level; however, if required TCP Wrappers can be used:
|
|
|
|
```
|
|
# Enable TCP Wrappers
|
|
tcp_wrappers=YES
|
|
|
|
# Deny a subnet
|
|
echo 'vsftpd:192.168.1.0/255.255.255.0:twist /bin/cat /etc/vsftpd/denied_message' >> /etc/hosts.deny
|
|
```
|
|
|
|
Using `iptables` is preferred.
|
|
|
|
### SSL Connections
|
|
|
|
```
|
|
# General SSL Options
|
|
ssl_enable=YES
|
|
ssl_request_cert=YES
|
|
validate_cert=NO # breaks self-signed certs
|
|
ca_certs_file=/path/to/ca-bundle.crt
|
|
rsa_cert_file=/path/to/server.crt # can be a PEM
|
|
rsa_private_key_file=/path/to/server.key # can be a PEM
|
|
ssl_ciphers=HIGH:!ADH
|
|
ssl_sslv2=NO
|
|
ssl_sslv3=NO
|
|
ssl_tlsv1=YES
|
|
debug_ssl=NO
|
|
|
|
# Always expect a SSL handshake (not normal - use TLS instead)
|
|
implicit_ssl=NO
|
|
|
|
# Force various SSL options
|
|
require_cert=NO # client SSL cert, not server
|
|
force_local_data_ssl=NO
|
|
force_local_logins_ssl=NO
|
|
require_ssl_reuse=YES
|
|
strict_ssl_read_eof=NO
|
|
strict_ssl_write_shutdown=NO
|
|
|
|
# SSL options for Anonymous FTP
|
|
allow_anon_ssl=YES
|
|
force_anon_ssl=NO
|
|
force_anon_data_ssl=NO
|
|
force_anon_logins_ssl=NO
|
|
force_local_data_ssl=NO
|
|
```
|
|
|
|
|
|
## Active vs. Passive
|
|
|
|
Configuration options exist to facilitate setting of Active ("PORT") and Passive ("PASV") FTP to work around various firewall restrictions. One of the most common techniques is to use the kernel netfilter modules `nf_nat_ftp` and `nf_conntrack_ftp` (aliased internally to `ip_nat_ftp` and `ip_conntrack_ftp` for compatibility) which will track the FTP connections and attempt to maintain a data connection to the client dynamically.
|
|
|
|
```
|
|
# RHEL / CentOS == /etc/sysconfig/iptables-config
|
|
IPTABLES_MODULES="ip_nat_ftp ip_conntrack_ftp"
|
|
|
|
# Debian / Ubuntu == /etc/modules
|
|
ip_nat_ftp
|
|
ip_conntrack_ftp
|
|
```
|
|
|
|
These can be loaded immediately using `modprobe` (`modprobe ip_nat_ftp ip_conntrack_ftp`) instead of rebooting.
|
|
|
|
Additionally, vsftpd includes a number of variables which can also be used to set the behaviour of the static/dynamic ports used in either mode:
|
|
|
|
```
|
|
# Enable PORT (active) mode FTP and force 20 for data
|
|
port_enable=YES
|
|
connect_from_port_20=YES
|
|
ftp_data_port=20
|
|
|
|
# Set a specific range of data ports in PASV (passive) mode
|
|
pasv_enable=YES
|
|
pasv_addr_resolve=NO
|
|
pasv_min_port=23000 # 0 = use any port
|
|
pasv_max_port=23100 # 0 = use any port
|
|
```
|
|
|
|
|
|
## Virtual chroot Users
|
|
|
|
This section is a description of the general method used in this article (but not exactly):
|
|
|
|
- <http://wiki.centos.org/HowTos/Chroot_Vsftpd_with_non-system_users>
|
|
|
|
The scripts on that page can be used to perform a majority of this work, however those scripts are missing a few items outlined below based on using the ftp system user to own files rather than the virtual user - use those scripts with caution.
|
|
|
|
The account user/pass are stored in a Berkeley DB format file, so the proper package must be installed to provide the `db_load` command:
|
|
|
|
```
|
|
## RHEL / CentOS
|
|
yum -y install db4-utils
|
|
|
|
## Debian / Ubuntu
|
|
apt-get update && apt-get -y install db-util
|
|
```
|
|
|
|
### vsftpd.conf
|
|
|
|
The configuration can be built to use virtual users based on the `user_config_dir` variable combined with the others; the key settings for vsftpd.conf:
|
|
|
|
```
|
|
vsftpd.conf
|
|
|
|
# These are in addition to any other normal config (SSL, etc.)
|
|
anon_world_readable_only=NO
|
|
anonymous_enable=NO
|
|
chroot_local_user=YES
|
|
guest_enable=YES
|
|
guest_username=ftp
|
|
hide_ids=YES
|
|
local_enable=YES
|
|
nopriv_user=ftp
|
|
pam_service_name=ftp
|
|
user_config_dir=/etc/vsftpd/users
|
|
userlist_enable=YES
|
|
userlist_file=/etc/vsftpd/denied_users
|
|
anon_umask=022
|
|
local_umask=022
|
|
dirlist_enable=NO
|
|
download_enable=NO
|
|
virtual_use_local_privs=YES
|
|
```
|
|
|
|
Create the core virtual chroot parent directory as listed above:
|
|
|
|
```
|
|
mkdir -p /var/ftp/virtual_users
|
|
```
|
|
|
|
Create the plain text file to store user/pass information imported to a DB:
|
|
|
|
```
|
|
# This is the input to create a DB hash file
|
|
# - for ultimate security it would not be left on the server
|
|
touch /etc/vsftpd/accounts.tmp
|
|
chmod 0600 /etc/vsftpd/accounts.tmp
|
|
```
|
|
|
|
### PAM ftp
|
|
|
|
The above config specifies an alternate PAM configuration; create the file `/etc/pam.d/ftp` with the required config to use an alternate database:
|
|
|
|
```
|
|
/etc/pam.d/ftp
|
|
|
|
auth required pam_userdb.so db=/etc/vsftpd/accounts
|
|
account required pam_userdb.so db=/etc/vsftpd/accounts
|
|
```
|
|
|
|
### SELinux
|
|
|
|
If required, enable SELinux anonymous writes:
|
|
|
|
```
|
|
setsebool -P allow_ftpd_anon_write 1
|
|
```
|
|
|
|
### Adding a User
|
|
|
|
First, the core login config for a user has to be created under the directory outlined by `user_config_dir` which matches the login name. The name _testuser_ will be used as an example:
|
|
|
|
```
|
|
/etc/vsftpd/users/testuser
|
|
|
|
dirlist_enable=YES
|
|
download_enable=YES
|
|
local_root=/var/ftp/virtual_users/testuser
|
|
write_enable=YES
|
|
```
|
|
|
|
Next, add the user to the core denied users specified by `userlist_file` above:
|
|
|
|
```
|
|
echo "testuser" >> /etc/vsftpd/denied_users
|
|
```
|
|
|
|
Create their system level user and chown their virtual user to _ftp_ instead due to the `virtual_use_local_privs` setting above:
|
|
|
|
```
|
|
useradd -d /var/ftp/virtual_users/testuser -s /sbin/nologin testuser
|
|
chmod 0750 /var/ftp/virtual_users/testuser
|
|
chown ftp:ftp /var/ftp/virtual_users/testuser
|
|
|
|
# If SELinux is active
|
|
chcon -t public_content_rw_t /var/ftp/virtual_users/testuser
|
|
```
|
|
|
|
Add their account/password to the text DB import file and create the DB:
|
|
|
|
```
|
|
echo "testuser" >> /etc/vsftpd/accounts.tmp
|
|
echo "testpass" >> /etc/vsftpd/accounts.tmp
|
|
db_load -T -t hash -f /etc/vsftpd/accounts.tmp /etc/vsftpd/accounts.db.new
|
|
mv -f /etc/vsftpd/accounts.db.new /etc/vsftpd/accounts.db
|
|
chmod 0600 /etc/vsftpd/accounts.db
|
|
```
|
|
|
|
### Reloading Users
|
|
|
|
The daemon needs reloaded after user changes:
|
|
|
|
```
|
|
service vsftpd reload
|
|
```
|
|
|
|
### Updating a User
|
|
|
|
The Update process is changing the same info used during Add:
|
|
|
|
1. Use `usermod` to alter the system user info as needed
|
|
2. Update the user/pass in `/etc/vsftpd/accounts.tmp` and rebuild `/etc/vsftpd/accounts.db`
|
|
|
|
Typically in this scenario the password is being updated.
|
|
|
|
### Removing a User
|
|
|
|
The process is an exact reverse of the Add process:
|
|
|
|
1. Remove the 2 lines in `/etc/vsftpd/accounts.tmp` for their user/pass and rebuild `/etc/vsftpd/accounts.db`
|
|
2. Remove the user from the system using `userdel`
|
|
3. Remove the user from `/etc/vsftpd/denied_users`
|
|
4. Remove the user config from `/etc/vsftpd/users/` directory
|
|
|
|
Parts of the steps can be left – for example, if the content of the old `$HOME` directory is to be preserved, do not run userdel.
|
|
|
|
|
|
## References
|
|
|
|
- <https://security.appspot.com/vsftpd.html>
|
|
- <http://slacksite.com/other/ftp.html>
|