Setup Virtual Users and Directories in VSFTPd on CentOS 5.x/6.x, RHEL 5/6 (in my case it was CentOS 5.4 x86 32bit).
( based on Virtual Hosting With vsftpd And MySQL On Debian Etch)
Someone might find this useful, so you don't have to lose a day or two for getting it work... (as I did)...
Advantages
1. Storing users and passwords into one database is easier to maintain and you avoid having local accounts for all the users you might need to give them FTP access, so the security risk of hacking user accounts is minimized. All users are located in one directory with user specific settings if needed.
2. MySQL protects databases with user specific permissions granted by MySQL root (a superuser for databases, giving them access, permissions to read, write, modify...)
So the MySQL superuser root should have its own MySQL password (not the same as account 'root') in case of exploits to mysql and hacking the local 'root' account to get access to the server ( some more MySQL basics )
1. Storing users and passwords into one database is easier to maintain and you avoid having local accounts for all the users you might need to give them FTP access, so the security risk of hacking user accounts is minimized. All users are located in one directory with user specific settings if needed.
2. MySQL protects databases with user specific permissions granted by MySQL root (a superuser for databases, giving them access, permissions to read, write, modify...)
So the MySQL superuser root should have its own MySQL password (not the same as account 'root') in case of exploits to mysql and hacking the local 'root' account to get access to the server ( some more MySQL basics )
REQUIREMENTS:
pam_mysql.so library
You will need (if not already installed) VSFTPD and MySQL:pam_mysql.so library
yum install vsftpd mysql-server
Then Start mysqld if not already:
service mysqld restart
and create root password for MySQL (if not already done):
mysqladmin -u root password yourrootsqlpassword
3 Create The MySQL Database For vsftpd
login to mysql:
mysql -u root -penter " yourrootsqlpassword " - Be aware: yourrootsqlpassword IS NOT your user's 'root' password and should be different.
Create database for users:
CREATE DATABASE vsftpd;still in the MySQL shell, create the database table needed (there is only one table with usernames and passwords MD5 encrypted):
GRANT SELECT ON vsftpd.* TO 'vsftpd'@'localhost' IDENTIFIED BY 'vsftpdpassword';
FLUSH PRIVILEGES;
USE vsftpd;then you can
CREATE TABLE `accounts` (
`id` INT NOT NULL AUTO_INCREMENT PRIMARY KEY ,
`username` VARCHAR( 30 ) NOT NULL ,
`pass` VARCHAR( 50 ) NOT NULL ,
UNIQUE ( `username` )
) ENGINE = MYISAM ;
exit;
4 Configure VSFTPD (Very Secure FTP server):
Create a non-privileged user called 'vsftpd' (with the homedir /home/vsftpd) belonging to the group 'users'. Vsftpd will run with this users privileges so risk to the system is minimized and the FTP directories of our virtual users will be in the '/home/vsftpd' directory (e.g. /home/vsftpd/user1, /home/vsftpd/user2, etc.) or as defined in VSFTPD PER USER config file.
useradd -G users -s /sbin/nologin -d /home/vsftpd vsftpdThen make VSFTP config settings (make a backup of the original /etc/vsftpd.conf file):
cp -v /etc/vsftpd/vsftpd.conf /etc/vsftpd/vsftpd.conf-origand make our own needed changes:
First we empty the existing file and then open it for editing:
cat /dev/null > /etc/vsftpd/vsftpd.confvsftpd.conf configuration settings (copy this into file):
vi /etc/vsftpd/vsftpd.conf
# No ANONYMOUS users allowedWith the user_config_dir option you can specify a directory for per-user configuration files that override parts of the global settings. This is totally optional and up to you if you want to use this feature.
anonymous_enable=NO
# Allow 'local' users with WRITE permissions (0755)
local_enable=YES
write_enable=YES
local_umask=022
dirmessage_enable=YES
xferlog_enable=YES
# if you want to LOG vsftpd activity then uncomment this log_ftp_protocol
# log_ftp_protocol=YES
connect_from_port_20=YES
# uncomment xferlog_file and xferlog_std_format if you DIDN'T use the line above
# with log_ftp_protocol - it must be excluding each other
# The name of log file when xferlog_enable=YES and xferlog_std_format=YES
# WARNING - changing this filename affects /etc/logrotate.d/vsftpd.log
#xferlog_file=/var/log/xferlog
#
# xferlog_std_format Switches between logging into vsftpd_log_file and xferlog_file files.
# NO writes to vsftpd_log_file, YES to xferlog_file
# xferlog_std_format=YES
#
# You may change the default value for timing out an idle session (in seconds).
#idle_session_timeout=600
#
# You may change the default value for timing out a data connection (in seconds).
#data_connection_timeout=120
#
# define a unique user on your system which the
# ftp server can use as a totally isolated and unprivileged user.
nopriv_user=vsftpd
chroot_local_user=YES
listen=YES
# here we use the authentication module for vsftpd to check users name and passw
pam_service_name=vsftpd
userlist_enable=YES
tcp_wrappers=YES
# If userlist_deny=YES (default), never allow users in this file
# /etc/vsftpd/user_list , and do not even prompt for a password.
# Note that the default vsftpd pam config also checks /etc/vsftpd/ftpusers
# for users that are denied.
userlist_deny=yes
# here the vsftpd will allow the 'vsftpd' user to login into '/home/vsftpd/$USER directory
guest_enable=YES
guest_username=vsftpd
local_root=/home/vsftpd/$USER
user_sub_token=$USER
virtual_use_local_privs=YES
user_config_dir=/etc/vsftpd/vsftpd_user_conf
force_local_data_ssl=NO
force_local_logins_ssl=NO
# PASV - passive ports for FTP (range 44000 - 44100 ; 100 PASV ports,
# REMEMBER to OPEN FIREWALL FOR ALLOWING FTP Passive CONNECTIONS
# check "how to enable Passive FTP in IPTABLES": here or here
pasv_enable=YES
pasv_min_port=44000
pasv_max_port=44100
However, create that directory now:
mkdir /etc/vsftpd/vsftpd_user_confIf you want to have for example: 'user1' to have different 'home dir' other than '/home/vsftpd/user1' then create
vsftpd PER USER configuration file:
vi /etc/vsftpd/vsftpd_user_conf/user1with configuration settings in it:
dirlist_enable=YESThe 'user1' directory must be created if you want the user to be able to login!
download_enable=YES
# full path to the directory where 'user1' will have access, change to your needs
local_root=/home/users/user1
write_enable=YES
mkdir /home/users/user1and giving 'user1' the permissions to read, write...:
chmod 700 /home/users/user1So now user1 has 'home dir' in '/home/users/user1' instead of '/home/vsftpd/user1' and it can be changed to whatever you need to in the Per user configuration file ...
chown vsftpd.users /home/users/user1
Now you must configure PAM (Password Authentication) so that it uses the MySQL database to authenticate your virtual FTP users instead of /etc/passwd and /etc/shadow.
The PAM configuration for vsftpd is in /etc/pam.d/vsftpd.
Make a backup of the original file and create a new one like this:
cp /etc/pam.d/vsftpd /etc/pam.d/vsftpd-origthe /etc/pam.d/vsftpd contents (note: this should be only 4 lines when you copy it):
cat /dev/null > /etc/pam.d/vsftpd
vi /etc/pam.d/vsftpd
#%PAM-1.0AND MAKE SURE that you replace the MySQL 'vsftpdpassword' password with your own one used before in 3 Create The MySQL Database For vsftpd
session optional pam_keyinit.so force revoke
auth required pam_mysql.so user=vsftpd passwd=vsftpdpassword host=localhost db=vsftpd table=accounts usercolumn=username passwdcolumn=pass crypt=3
account required pam_mysql.so user=vsftpd passwd=vsftpdpassword host=localhost db=vsftpd table=accounts usercolumn=username passwdcolumn=pass crypt=3
Now comes that tricky part for CentOS to make it work !
You need pam_mysql.so library, which is not included in CentOS installation or is not YUM installable, so you have to install from RPM (or EPEL repository ... or whichever method you prefer).Find here (pbone.net) the RPM pam_mysql module to download it (use 'wget' is simple), at this time of writing it was 'pam_mysql-0.7-0.5.rc1.el5.kb.2.i386.rpm' (watch for the right version i386 or x86_64 if you have 64bit system)
and install it:
rpm -Uvh pam_mysql-0.7-0.5.rc1.el5.kb.2.i386.rpmIt should install without warnings or error... else ... I recommend you use search in google to make it work!
When installed, you should find it:
ls -al /lib/security/pam_m*there it is in the last line in this example ! (you can have more, but should be in there)
-rwxr-xr-x 1 root root 8024 Sep 4 00:51 /lib/security/pam_mail.so
-rwxr-xr-x 1 root root 15848 Sep 4 00:51 /lib/security/pam_mkhomedir.so
-rwxr-xr-x 1 root root 3892 Sep 4 00:51 /lib/security/pam_motd.so
-rwxr-xr-x 1 root root 36920 Feb 28 2008 /lib/security/pam_mysql.so
This is critical for use virtual users auth with MySQL database
Now 5 Create The First Virtual UserInsert users to database you can use the MySQL shell:
mysql -u root -penter password ...
USE vsftpd;use the database 'vsftpd'
Now create the virtual user 'user1' with the password 'secret' (which will be stored encrypted using MySQL's MD5 function):
INSERT INTO accounts (username, pass) VALUES('user1', md5('secret'));You should now have one user in database:
mysql> select * from accounts;Now user1's homedir is '/home/vsftpd/user1' , unfortunately vsftpd doesn't create that directory automatically if it doesn't exist. Therefore create it manually now and make it owned by the vsftpd user and group 'users':
+----+-----------+----------------------------------+
| id | username | pass |
+----+-----------+----------------------------------+
| 1 | user1 | 5ebe2294ecd0e0f08eab7690d2a6ee69 |
+----+-----------+----------------------------------+
1 rows in set (0.00 sec)
exit;
mkdir /home/vsftpd/user1
chown vsftpd:users /home/vsftpd/user1
Now restart/start VSFTPD
service vsftpd restartand you should probably be able to login to your FTP server with some of the Windows clients like WS_FTP or SmartFTP or whatever you like...
if not ... I'm sorry, try read again.
How to add more users in the future when you need.. it's easy in 2 steps:
1. add new user ( e.g. 'user12' with passw 'secret12', you can use the full name with email address also if you want, like 'user12@example.com' ) :
mysql -u root -p2. make new 'user12' home dir
USE vsftpd;
INSERT INTO accounts (username, pass) VALUES('user12', md5('secret12'));
exit;
mkdir /home/vsftpd/user12
chown vsftpd:users /home/vsftpd/user12
Or you can use phpMyAdmin if you have a website running on the server (just download from phpMyAdmin site and extract to a subdir at your site - for example /var/www/mysite/phpmyadmin):
1. Login with root account (for now only 'root' has the rights to create/modify the vsFTP table at this time - you can create another user with privileges to modify the tables)
2. On the left side select 'vsftpd' database
3. then select table 'accounts'
4. On top select tab Browse once you have selected the table 'accounts'
5. you should see the list of users in the database:
6. Now to ADD new user: select INSERT tab on top
- in the field 'username' type the user's name for login (ie. 'newuser')
- in the field 'pass' select MD5 from dropdown list and type password for 'newuser' <- type it in plain text as it will be saved as MD5 because of field type selected MD5) Don't enter anything else, just click GO to save 'newuser' to database:
7. you should see the lines:
Inserted rows: 1
Inserted row id: "some number in list order automatically assigned id"
8. To see if you have added 'newuser' click again top tab Browse and the list should show the name and MD5 password for 'newuser'
Then you can repeat the step 6. as many times you need to add users.
9. To end phpMyAdmin session click Log Out / Exit :
Hopefully this is it and I'd be happy to see any comments of success (or fails).
TY for reading it ...
23 comments:
I followed your guide and it worked flawlessly. However, I found that SELinux was preventing the PAM library from connecting to the DB using the socket in /var/lib/mysql/mysql.sock. Here's the log line in /var/log/secure:
Feb 12 08:50:36 linuxbox vsftpd: pam_mysql - MySQL error (Can't connect to local MySQL server through socket '/var/lib/mysql/mysql.sock' (13))
I switched to Permissive mode and it started to work. I have to found the correct setting to configure SELinux.
Thank you for your note.
Personally I disabled SELinux and that didn't happen to me. Unfortunately I don't know SELinux and please try find help for that.
I guess I got it. I issued the following commands:
# setsebool -P ftp_home_dir 1
# setsebool -P ftpd_connect_db 1
I wish this were helpful!
Also check this out, it may be interesting ...
http://gsxbinary.blogspot.com/2010/03/vsftpd-with-pammysql-authentication.html
Another tool...
http://gsxbinary.blogspot.com/2010/04/webvsftpd-web-based-management-tool-for.html
Is there a way to pass the home directory information via pam to vsftpd, rather than have the home directories be assumed from the virtual user name? We have occasion to need to set up more complex tree structures, making it essential that we can set the home directory info explicitly per-user.
When using /etc/passwd, this is clearly the case, so it should be possible to feed this info via pam, somehow. Anyone have a solution for that?
@ds10:
As I understand is that "PER USER CONFIGURATION" is not an option for you?
If it helps, then use this part:
"PER USER configuration file:
vi /etc/vsftpd/vsftpd_user_conf/user1"
as user1 can be any name and inside the file define the path where user will be logged in (for example):
local_root=/home/exampledomain.com/private/users/
you can assign the 'home' dir like above to many users, like 'user@exampledomain.com' and 'joe@otherdomain.net' for which you create the same 'PER USER config file' (I will use the copy):
"cp /etc/vsftpd/vsftpd_user_conf/user1 /etc/vsftpd/vsftpd_user_conf/user@exampledomain.com"
... and so on
With PER USER CONFIGURATION FILE you separate user from others but also that is what "chroot_local_user=YES" does, as it keeps the user in its defined directory not allowing user to go anywhere else.
I hope this is what you want.
EDIT previous post:
you mention "When using /etc/passwd"
giving me a thought you might want to use 'local users' with vsFTPd not 'virtual' in that case try search "vsftpd local users"
Quick "/etc/pam.d/vsftpd" configuration (requires local user account in etc/passwd):
auth required pam_listfile.so item=user sense=deny file=/etc/vsftpd/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
hi
I did all step by step and at last when I tryed to login this was the resualt:
530 Login incorrect.
Login failed.
does any one know why?
what is the problem?
Hi,
unfortunately It can be many reasons of why you can't login.
Probably the cause is in Vsftpd not being able to find the user/password in MYSQL table.
Try adding another user/password and be sure if you used UppERcasE letters because it IS CASE SENSITIVE.
Check /etc/pam.d/vsftpd config file as stated it should be ONLY 4 lines in it:
1. #%PAM-1.0
2. session optional ....
3. auth required pam_mysql.so .....
4. account required pam_mysql.so ...
And try restart Mysql service (# service mysqld restart) and also vsftpd.
Hey hey!!! You're great, thank you thank you :)) i fought with it all day, but only after you post i finally did it :) thanks a lot for your work )
A little while back, I shared a link containing a little tool for managing your virtual users with MySQL backend from the command line. I have updated the tool a little removing a bug and updating other stuff. A RPM package is included now to ease the installation process.
http://gsxbinary.blogspot.com/2010/03/vsftpd-with-pammysql-authentication.html
Thanks!
configuration of an individual user directory was exactly what I was looking for. thanks for that!
Hi, thanks for the guide it was really helpful in getting virtual users setup.
There is one more thing I would like to know though, is there a way to have one user that can see other users' directories but not let the other users see outside there own directories. Any help or pointing in the right direction would be really appreciated.
Hi,
I'm glad to see you find it helpful
About the user which can view all others, the thing is a bit complicated and sometimes impossible.
It can be done if you have a directory structure like:
/var/www/site1
/var/www/site2
/var/www/site3
and each 'site' user is locked into its site, e.g. site1
Then a 'superuser' could be assigned to "/var/www" and thus can have access to all other site1, site2 etc. directories.
Unfortunately vsFTPd does not support links inside the directories to point to some other existing path (see this: http://radu.cotescu.com/vsftpd-and-symbolic-links/).
I'm sorry, the above link again:
vsFTPd symbolic links
good luck.
Hey man, thank you for the post,
I'm getting this error 530 Login incorrect.
Could you help me please?
I just want to say thank you! It didn't work at first (like @genellern) but after a restart of both mysql and vsftpd it worked great! though i think if i restarted vsftpd only it will work since my mysql installation was already working good before vsftpd. [centos 6 x86_64]
Hi,
Thanks for posting the article. It worked fine for me but in my set up I have a small deviation, Lets say I have a virtual user A having home directory as /home/A and I have a virtual user B and I need to map his home directory as /home/A instead of his home directory /home/B. How to do this. Any suggestions will be highly appreciated.
The old set up is based on system based accounts and I have migrated to virtual users using this article. In that they have mapped one home directory for two users. I have to do the same set up in the new implementation.
Thanks in advance
Hello.
I've tried to do everything you'd wrote but now i can connect to ftp server, get banner, ask for username and pass but i get: 530 Login incorrect.
error: critical error
error: could not connect to server
please help.
Hi,
Do you have maybe "SELinux" enabled ?
You can try to execute:
# setenforce 0
This command will temporarily disable SElinux (which you can permanently allow with command:
# setsebool -P "ftp_home_dir" 1
another possible solution is here
or
you maybe don't allow the users to login into their specified directories (vsftpd must be allowed to RWX that directory - check under 5 - create it manually now and make it owned by the vsftpd user and group 'users') This is also written here under section 4. Creation of home directories
I hope it will help you
and don't forget to restart "vsftpd" service !
Thank you very much. Disabling selinux - but only in that way: "edit /etc/selinux/config and change the SELINUX line to SELINUX=disabled"
- was a solution. :)
Have a nice day :)
Another limitation would be that this tool is very fragile and also gets very messy and hard to maintain after a while. Get more information about free database designer on this link.
Post a Comment