How to configure directory accessible by both FTP user and a webserver running under Debian?
In order to do this, we will need three things:
- Configure
vsftpd
to work with separate user configurations - Set correct permissions for directories accessible via FTP
- Turn off SSH access for FTP users
You can also jump to working production configuration attached below.
Suppose we have a webserver running under application
user, and one of its directories should be accessible via FTP for external users to upload/change some of the files. That means maintaining proper permissions, chrooting users to directories other than their home, and dealing with some of the vsftpd nuances.
First, we will need to allow external vsftpd configurations, so we can configure every user separately. Add the following lines to the /etc/vsftpd.conf
:
# Turn off anonymous access
anonymous_enable=NO
# Enable separate list of allowed users
userlist_enable=YES
# Switch userlist to whitelisting mode (so every listed user is allowed)
userlist_deny=NO
# Set location of userlist file
userlist_file=/etc/vsftpd/ftpusers
# Specify directory for separate user configs
user_config_dir=/etc/vsftpd/userconf/
Next, we will enable chroot jails, so users cannot access anything outside specified path:
# You may restrict local users to their home directories. See the FAQ for
# the possible risks in this before using chroot_local_user or
# chroot_list_enable below.
chroot_local_user=YES
At last, we will add user configurations, and set allowed list. /etc/vsftpd/ftpusers
contains line by line usernames of allowed guys:
ftpuser1
ftpuser2
Directory /etc/vsftpd/userconf/
contains separate config files for each user:
application@localhost:~$ ls -l /etc/vsftpd/userconf/
-rw-r--r-- 1 root root 105 Jan 13 18:46 ftpuser1
-rw-r--r-- 1 root root 105 Jan 13 18:47 ftpuser2
Each file contains user-specific settings, such as path to the accessible directory:
# Put this file in /etc/vsftpd/userconf/
local_root=/application/path/to/some/dir/
We have to reach several permission-related goals:
- files written by application to FTP dir writable and readable by our FTP users
- files under written by users to FTP dir writable and readable by
application
user - other files in the filesystem should be read-only on inaccessible by FTP users
All uploaded files will be owned by specific FTP user who uploaded them, having 0775
(rwxrwxrw-
) permissions. For group ownership we will create separate usergroup, which will be assigned to application
as a way to access uploaded files.
Every FTP user will belong to that group, too. Let's create our first user and make assignments:
$ adduser ftpuser1
$ groupadd ftpusers
$ usermod -G ftpusers ftpuser1
Now we will application user to the group too:
$ usermod -a -G ftpusers application
Let's now set proper directory ownership and permissions, so it will be accessible both to application and our FTP users:
$ chown -R application:ftpusers /application/path/to/some/dir/
$ chmod -R 0775 /application/path/to/some/dir/
We will also need to make sure files created under that directory all preserve their group ownership. To do this, set the setgid
flag on parent directory - its group assignment will 'stick' to childs then. Check dat s
:
$ chmod -R g+s /application/path/to/some/dir/
$ cd /application/path/to/some/ && ls -l
drwxrwsr-x 2 application ftpusers 4096 Jan 13 19:06 dir
vsftpd uses another security trick - it uses umask to reset default permissions on all uploaded files. Default umask is 077
, and target permission will be a result of removing all permission bits in places marked by 1s in umask. For example, file permission 775
and umask 057
equate to the following result:
775 (rwxrwxr-x) = 111 111 101
057 = 000 101 111
---
result = 111 010 000 (750, or rwxr-x---)
Default umask 077
will clear group and other permissions completely, so let's set more mild restrictions in /etc/vsftpd.conf
:
# Set umask for uploaded file permissions
local_umask=002
We can also set general permissions for files uploaded via FTP, to make sure owners and group owners have equal rights:
# Set default permissions for uploaded files
file_open_mode=0775
This will remove write ability for other users, and preserve full permissions for owner and group.
Using settings above, users will be chrooted inside specified directory. However, as of vsftpd version 3 and above, you are now required to make that directory non-writable by user who accesses it. That was designed with /home
chroots in mind, but in our case we clearly don't want that behavior. Two best options to avoid this (and you can find more all around the internet):
- For systems with fresh vsftpd in repositories, we can simply set the following option in
/etc/vsftpd.conf
:
allow_writeable_chroot=YES
- For Debian Wheezy, which uses vsftpd version 2 with backported writable_root check, we will have to chroot our user to directory above target, so path:
local_root=/application/path/to/some/dir/
becomes:
local_root=/application/path/to/some/
This is obviously a very limited solution, and alternatives (such as backporting option from p.1 to Wheeezy) can be found using links above. However, it works for some of the cases, and proved itself to be the easiest solution. You can further restrict everything that user sees inside /application/path/to/some/
directory using ownership and group permissions.
Make sure FTP users do not have access via SSH. The best way to do it (ensuring future changes among users wont accidentally allow unwanted access) is to whitelist several, and disable the rest. Set the following parameter in the /etc/ssh/sshd_config
:
AllowUsers application