Vsftpd supports virtual users with PAM (pluggable authentication modules). A virtual user is a user login which does not exist as a real login on the system in /etc/passwd and /etc/shadow file. Virtual users can therefore be more secure than real users, because a compromised account can only use the FTP server but cannot login to system to use other services such as ssh or smtp.
Required software
- Berkeley DB (version 4) databases
- pam_userdb.so
Install Berkeley DB And Utilities Under RHEL / CentOS
Type the following command:
# yum install db4-utils db4
Create The Virtual Users Database
To create a “db4” format file, first create a plain text files with the usernames and password on alternating lines. For e.g. create user called “vivek” with password called “vivekpass” and sayali with password “sayalipass”:
# cd /etc/vsftpd
# cat > vusers.txt
Sample output:
vivek vivekpass sayali sayalipass
Next, create the actual database file like this:
# db_load -T -t hash -f vusers.txt vsftpd-virtual-user.db
# chmod 600 vsftpd-virtual-user.db
# rm vusers.txt
Configure VSFTPD for virtual user
Edit the vsftpd configuration file. Add or correct the following configuration options:
anonymous_enable=NO local_enable=YES # Virtual users will use the same privileges as local users. # It will grant write access to virtual users. Virtual users will use the # same privileges as anonymous users, which tends to be more restrictive # (especially in terms of write access). virtual_use_local_privs=YES write_enable=YES # Set the name of the PAM service vsftpd will use # RHEL / centos user should use /etc/pam.d/vsftpd pam_service_name=vsftpd.virtual # Activates virtual users guest_enable=YES # Automatically generate a home directory for each virtual user, based on a template. # For example, if the home directory of the real user specified via guest_username is # /home/virtual/$USER, and user_sub_token is set to $USER, then when virtual user vivek # logs in, he will end up (usually chroot()'ed) in the directory /home/virtual/vivek. # This option also takes affect if local_root contains user_sub_token. user_sub_token=$USER # Usually this is mapped to Apache virtual hosting docroot, so that # Users can upload files local_root=/home/vftp/$USER # Chroot user and lock down to their home dirs chroot_local_user=YES # Hide ids from user hide_ids=YES
Save and close the file.
Create a PAM File Which Uses Your New Database
The following PAM is used to authenticate users using your new database. Create /etc/pam.d/vsftpd.virtual:
# cat > /etc/pam.d/vsftpd.virtual
Append the following:
#%PAM-1.0 auth required pam_userdb.so db=/etc/vsftpd/vsftpd-virtual-user account required pam_userdb.so db=/etc/vsftpd/vsftpd-virtual-user session required pam_loginuid.so
Create The Location Of The Files
You need to set up the location of the files / dirs for the virtual users. Type the following command:
# mkdir /home/vftp
# mkdir -p /home/vftp/{vivek,sayali}
# chown -R ftp:ftp /home/vftp
Restart The FTP Server
Type the following command:
# service vsftpd restart
Test Your Setup
Open another shell session and type:
$ ftp ftp.nixcraft.net
Sample output:
Connected to ftp.nixcraft.net.in. Name (localhost:root): vivek 331 Please specify the password. Password: 230 Login successful. Remote system type is UNIX. Using binary mode to transfer files. ftp>
Sample log from /var/log/secure:
# tail -f /var/log/secure
Output
May 21 16:54:28 xentest vsftpd: pam_userdb(vsftpd.virtual:auth): user 'vivek' granted access
🐧 Get the latest tutorials on Linux, Open Source & DevOps via:
- RSS feed or Weekly email newsletter
- Share on Twitter • Facebook • 50 comments... add one ↓
Category | List of Unix and Linux commands |
---|---|
File Management | cat |
Firewall | Alpine Awall • CentOS 8 • OpenSUSE • RHEL 8 • Ubuntu 16.04 • Ubuntu 18.04 • Ubuntu 20.04 |
Network Utilities | dig • host • ip • nmap |
OpenVPN | CentOS 7 • CentOS 8 • Debian 10 • Debian 8/9 • Ubuntu 18.04 • Ubuntu 20.04 |
Package Manager | apk • apt |
Processes Management | bg • chroot • cron • disown • fg • jobs • killall • kill • pidof • pstree • pwdx • time |
Searching | grep • whereis • which |
User Information | groups • id • lastcomm • last • lid/libuser-lid • logname • members • users • whoami • who • w |
WireGuard VPN | Alpine • CentOS 8 • Debian 10 • Firewall • Ubuntu 20.04 |
Okay but about the right of the virtual USer …
how to create or make a directory or a file by a virtual user …. ??????
Oops. That should say “scripts”, and then in the chown line there shouldn’t be an http:// in there, but hopefully people will figure that out.
Not sure if anyone’s made better scritps for dealing with users.. I looked at the perl script someone pointed to but it didn’t write out in the correct format, or it didn’t work for me at least. Since I’m no good at perl, I made these…
addftpuser.sh:
and
delftpuser.sh:
Thanks for the document. It really helped me lot. Very nicely written.
I can’t login with user and pass in vusers.txt.
Can you help me
hey tim
maybe a bit late but you need to set the permissions (chmod) for the files/folders so that the ftp user can work with them
rs
With this type of configuration, has anyone tested or expect the ability to delete files from the FTP directory?
The clients attempt RMD “file or folder name” and the server responds with “550 Permission Denied”.
Any help would be appreciated!
unable to create virtual users in cenot6 .. im new to this …when i give this command # cd /etc/vsftpd
# cat > vusers.txt
empty no users ….
how to create virtual users
Dear All, Currently I have VSFTPD running with Virtual users and PAM bases authentication.
Now, I want to convert the authentication method, from Virtual PAM based to LDAP bases authentication. I do have a LDAP server, and I access it using the url: ldap://ldap..com.
Could any one can tell me how to convert this authentication.
Dilip
very good job ! but… How can i edit PAM DB..add user, detele user, change user password ?
Jan 24 18:05:38 mann vsftpd[1804]: pam_unix(vsftpd:auth): check pass; user unknown
Jan 24 18:05:38 mann vsftpd[1804]: pam_unix(vsftpd:auth): authentication failure; logname= uid=0 euid=0 tty=ftp ruser=anonymous rhost=192.168.0.198
Jan 24 18:05:38 mann vsftpd[1804]: pam_succeed_if(vsftpd:auth): error retrieving information about user anonymous
Jan 24 18:05:59 mann vsftpd[1806]: pam_unix(vsftpd:auth): check pass; user unknown
Jan 24 18:05:59 mann vsftpd[1806]: pam_unix(vsftpd:auth): authentication failure; logname= uid=0 euid=0 tty=ftp ruser=vivek rhost=192.168.0.198
Jan 24 18:05:59 mann vsftpd[1806]: pam_succeed_if(vsftpd:auth): error retrieving information about user vivek
Edit the vsftpd configuration file.
virtual_use_local_privs=YES
pam_service_name=vsftpd.virtual
This did not work for me. Any ideas?
C:Documents and Settingssam>ftp 50.17.xxx.xxx
Connected to 50.17.xxx.xxx.
220 (vsFTPd 2.2.2)
User (50.17.xxx.xxx:(none)): sam
331 Please specify the password.
Password:
500 OOPS: cannot change directory:/home/vftp/samConnection closed by remote host.
C:Documents and Settingssam>
Were you ever able to get this figured out? I’m having the same issue.
Command: USER john
Response: 331 Please Specify the password.
Command: PASS ************************
Response: 500 OOPS: cannot change directory:/home/vftp/john
Error: Critical Error
Error: Could not connect to server
At this time, no I have not. I just let it go.
Check your SELinux settings:
getsebool -a | grep ftp
If you see the following:
ftp_home_dir –> off
Use this to enable it:
setsebool -P ftp_home_dir on
An alternative option is to disable SELinux altogether, however I don’t recommend that for a public facing server.
Thanks for the great document. Though, i have one question.
how to enable local user along with the virtual user?
hi ,me also met with the same error while uploading the file “553 Could not create file.” but thing s that when i change my se linux context selinux to “permissive mode ,” uploading s data is possible,since i can’t compromise on security of server, i changed selinux context to enfoceing mode. in that context i can’t upload the file… what might be the reason im using Redhat 6
Hello, in case you are running ubuntu the path for pam db are different:
auth required /lib/i386-linux-gnu/security/pam_userdb.so db=/etc/vsftpd_login
account required /lib/i386-linux-gnu/security/pam_userdb.so db=/etc/vsftpd_login
now it works! cheers
Thanks so much – this was the bit I was stuck on!
Thanks a lot dude !
I did it, myself 🙂 Thank you again for the awesome post, it helps me, so much:)
Sincerely,
Ismayilov Ali
Awesome post! It was all going so well until I came up to a world of pain, I’ve managed to get the system working with virtual users, but as soon as I start trying to write to the ftp server I get “553 Could not create file”.
I’ve looked everywhere, and I know it has to do with permissions, but I can’t get my head around it without compromising the security of the server. Do you have any tips? Is that something you came accross?
Cheers,
Guy
Thank you for great post.
However, I have the problem when I install OS via pxe. Can I allow any virtual user to install OS via pxe?
Thank you for the answer
There is a simple perl script for managing pam_userdb / virtual vsftpd accounts available at:
http://dist.epipe.com/perl/pam_userdb_admin.pl
I thought it might be helpful starting point for people who do not like db_load.
Very thanks!
You saved me some time.
You also have to add
guest_username=virtual
in vsftpd.conf file otherwise you will get the error
> May 21 16:54:28 xentest vsftpd: pam_userdb(vsftpd.virtual:auth): user ‘vivek’ granted access
I noticed that that line doesn’t list the IP of the user. I recently had someone trying to access one of my servers repeatedly and I’d like to know the IP address of the person that did that, is there any way?
I found the information I was looking for in /var/log/audit/audit.log.
Great guide! I can not thank you enough for it!!
I had done something wrong originally, but cleaning everything and starting over i have a working TLS / SSL based FTP server running under CentOS 5.5 with Virtual users.
Question, is using:
Explicit SSL with (Auth SSL)
different then
Explicit SSL with (Auth TSL)
since the server is allowing either one to log in successfully, is this normal?
Also, i was now curious as to how i can set permissions for specific people, this vsftpd is very new to me, as is most things CentOS over the last 3 weeks!
i plan to have users who have access to the apache doc root for website modification, but i do want to limit some things like what they can and can not delete or access.
Hello, can you advice how to delete users and manage the db4 database?
Thanks,
Is it possible to enable UTF8 in the log file? Currently, the high characters are replaced as question marks though they appear in the file lists correctly.
Hi Vivek, awesome guide. Managed to go through all the way except that when I try and FTP in, it authenticates successfully but gets stuck at :
Response: 227 Entering Passive Mode (IP address here)
Command: LIST
Error: Connection timed out
Error: Failed to retrieve directory listing
Check your local or remote firewall settings.
GunFlak,
First, try to connect to the server with Passive mode turned OFF, if it works, then you need to set vsftpd to use a specific passive mode port range
https://www.redhat.com/docs/manuals/enterprise/RHEL-3-Manual/ref-guide/s1-ftp-vsftpd-conf.html
see the options if you search for Passive on the site starting at pasv_address
then you need to open the same ports on your firewall to access the server externally.
Im installing the vsftpd with PAM as you show in this excellent article. but im stucked with
227 Entering Passive Mode (50,57,88,197,91,107)
LIST
Error: Cannot retrieve directory list.
Im already
/sbin/iptables -I RH-Firewall-1-INPUT 1 -p tcp –dport ftp -j ACCEPT
/sbin/iptables -I RH-Firewall-1-INPUT 1 -p tcp –dport ftp-data -j ACCEPT
/sbin/service iptables save
/sbin/service iptables restart
Howhever i think could be the firewall???
After some working around this issue ive abled to loggin successfully with the following commands
/sbin/modprobe ip_conntrack
/sbin/modprobe ip_conntrack_ftp
Was the firewall(iptables) that need to follow the ftp data!!
Hi Vivek,
Thanks for the guide! I wish I have read this before during my previous deployment without the use of MySQL, anyways is it possible to add new users by re-creating the virtual users text file containing new users and passwords respectively and then run db_load all over again?
TIA.
is it possible to use multiple pam? i mean is it ok to use the virtualdb pam and the local users pam?
To add to that.
I think I am suddenly able to list the directory now… however I still cannot upload anything.
Is there any special thing I need to do to allow users to upload?
Great article, however I’m having a very frustrating problem (been working on it all day) where I can login just fine, but then cannot list the directory, nor can I upload any files. I can’t for the life of me figure out whats wrong. I’ve done everything by the book and read several different articles on setting this up. Here is my vsftpd.conf (minus comments).
local_enable=YES
write_enable=YES
local_umask=022
dirmessage_enable=YES
xferlog_enable=YES
connect_from_port_20=YES
xferlog_file=/var/log/xferlog
xferlog_std_format=NO
listen=YES
pam_service_name=vsftpd
userlist_enable=YES
tcp_wrappers=YES
log_ftp_protocol=YES
anonymous_enable=NO
local_enable=YES
virtual_use_local_privs=YES
write_enable=YES
guest_enable=YES
user_sub_token=$USER
local_root=/home/clients/$USER
chroot_local_user=YES
hide_ids=YES
Also, is there any way to get any useful debug output from vsftpd so I can try to trouble-shoot what is actually going wrong? The vsftpd.log doesn’t tell me anything that I don’t already get from the ftp-client end.
Thanks for any help.
I think you should turn off the iptables and then take a try again!
Great article and thanks for putting it out there!
One little addition that you may need is if you are running SELinux it may prevent the users from locating their home dir. To correct this you can turn SELinux off if you wish or tweak it with /usr/sbin/setsebool -P ftp_home_dir 1
I’m really looking forward to the rest of the series especially the management of users and data.
One question though – how could you set up multiple users to use the same home dir? for example say I’m working on a project (Project456) and I want one place for all the data but have to issue external parties with their own user accounts.
hi Gents,
does anybody know this error msg? Fatal error: gnutls_record_recv: A record packet with illegal version was received.
waititng for above inquary 😉
It will be added to this page automatically, bookmark this page.
Good.. and thanks… please send me the link to that article..
@Krishantha,
I will add another entry to this series to manage users after vsftpd is configured, such as deleting users, changing passwords and so on.
it is working.. fine. but I have problem. How to delete user or how to edit user from PAM DB
Thanks for the helpful article. When running vsftpd on CentOS 5, one small correction I had to make on the configuration of vsftpd.virtual was to add crypt=hash to end of the auth and account lines.
#%PAM-1.0
auth required pam_userdb.so db=/etc/vsftpd/vsftpd-virtual-user crypt=hash
account required pam_userdb.so db=/etc/vsftpd/vsftpd-virtual-user crypt=hash
session required pam_loginuid.so