vsftpd i MySQL - tworzymy idealną parę

Każdy administrator ma swoje zdanie na temat przechowywania użytkowników w bazie danych. Jedni będą twierdzić, że to bardzo głupi pomysł, ponieważ wprowadzamy dodatkową warstwę pomiędzy klientem a serwerem, natomiast drudzy zobaczą w tym wygodę i automatyzację. Wyobraźmy sobie taką sytuację, nasi klienci czy znajomi posiadają na naszym serwerze konta WWW, my im podpieliśmy domenę, założyliśmy konto shell, uruchomiliśmy serwer FTPd i podaliśmy im namiary. Każdy korzysta z konta na swój sposób, ale przychodzi moment, kiedy ktoś musi zmienić hasło... dzwoni więc do nas i prosi o zmianę hasła, my logujemy się, wpisujemy passwd $user i wszystko jest fajnie. Kolejnego dnia dzwoni ktoś inny i mówi, że wygasła mu domena, a nie chciał jej przedłużać bo udało mu się zarejestrować inną i prosi nas o zmianę wpisów w serwerze DNS, znów logujemy się na serwer i edytujemy pliki named'a... Wytrzymamy to, jeśli takich telefonów nie będzie 10 dziennie. Administratorzy to leniwy naród ;-) i automatyzują/upraszczają wszystko co się da. Tak naprawdę idealnym rozwiązaniem tej sytuacji jest posiadania centralnej bazy danych użytkowników/klientów/znajomych, w której będą umieszczone zarówno domeny, hasła i wszystko inne co może nam się przydać w przyszłości. Spróbujmy więc na początek uruchomić serwer FTPd działający w oparciu o autoryzację użytkowników bezpośrednio z bazy danych MySQL.

Osobiście preferuję do prostszych zastosowań serwer vsftpd, posiada wszystko co jest mi niezbędne, wsparcie SSL/TLS, chroot, umask, dodatkowo wykorzystam bazę danych MySQL, chyba najbardziej popularną wśród darmowych rozwiązań.

Instalacja VSFTPd (Ubuntu)

root@iDev:/home/jamzed# apt-get install vsftpd libpam-mysql mysql-server mysql-client
Czytanie list pakietów... Gotowe
Budowanie drzewa zależności
Odczyt informacji o stanie... Gotowe
Zostaną zainstalowane następujące dodatkowe pakiety:
libdbd-mysql-perl libdbi-perl libhtml-template-perl libmysqlclient15off libmysqlclient16 libnet-daemon-perl libplrpc-perl mysql-client-5.1 mysql-common
mysql-server-5.1 mysql-server-core-5.1 ssl-cert update-inetd
Sugerowane pakiety:
dbishell libipc-sharedcache-perl tinyca mailx
Zostaną zainstalowane następujące NOWE pakiety:
libdbd-mysql-perl libdbi-perl libhtml-template-perl libmysqlclient15off libmysqlclient16 libnet-daemon-perl libpam-mysql libplrpc-perl mysql-client
mysql-client-5.1 mysql-common mysql-server mysql-server-5.1 mysql-server-core-5.1 ssl-cert update-inetd vsftpd
0 aktualizowanych, 17 nowo instalowanych, 0 usuwanych i 25 nieaktualizowanych.
Konieczne pobranie 24,5MB archiwów.
Po tej operacji zostanie dodatkowo użyte 58,2MB miejsca na dysku.

Prawdopodobnie zostaniemy poproszeni o ustawienie hasła do serwera MySQL (o ile nie był już zainstalowany).

Po instalacji niezbędnych pakietów możemy zalogować się do bazy danych i stworzyć bazę naszych użytkowników.

root@iDev:/home/jamzed# mysql -u root -p

Hasło podajemy te, które było ustawione przed chwilą.

Tworzymy strukturę bazy danych:

CREATE DATABASE vsftpd;

GRANT ALL PRIVILEGES ON vsftpd.* TO 'vsftpd'@'localhost' IDENTIFIED BY 'ftpdpass';

USE vsftpd;

CREATE TABLE tb_users (
id INT NOT NULL AUTO_INCREMENT PRIMARY KEY ,
login VARCHAR (25) NOT NULL ,
password VARCHAR (41) NOT NULL ,
UNIQUE ( login )
) ;

Powinniśmy już mieć stworzoną zarówno bazę danych vsftpd jak i założoną strukturę tabeli tb_users. Następny krok to przygotowanie serwera vsftpd tak by poprawnie współpracował z bazą danych, serwer ten sam w sobie nie potrafi obsługiwać bazy danych MySQL, ale mamy PAM'a (jest to zestaw bibliotek, które umożliwiają korzystanie z różnych metod autoryzacji w programach), którego własnie wykorzystamy.

Konfiguracja serwera vsftpd znajduje się w pliku: /etc/vsftpd.conf, zróbmy jego kopię i stwórzmy nową własną konfigurację:

root@iDev:/home/jamzed# mv /etc/vsftpd.conf /etc/vsftpd.conf.orig
root@iDev:/home/jamzed# vi /etc/vsftpd.conf

Minimalna konfiguracja naszego serwera:

listen=YES
anonymous_enable=NO
local_enable=YES
write_enable=YES
local_umask=022
dirmessage_enable=YES
xferlog_enable=YES
connect_from_port_20=YES
nopriv_user=ftp
chroot_local_user=YES
pam_service_name=vsftpd
guest_enable=YES
guest_username=vsftpd
local_root=/home/vsftpd/$USER
user_sub_token=$USER
virtual_use_local_privs=YES

  • listen = YES - oznacza, że nasz serwer będzie działał jako standalone, jeśli damy NO, serwer uruchomi się dopiero jako daemon z inetd/xinetd
  • anonymous_enable = NO - wyłączamy dostęp użytkownikowi anonymous
  • local_enable = YES - zezwalamy na logowanie się lokalnych użytkowników (passwd)
  • write_enable = YES - zezwalamy na zapis, serwer może przyjmować pliki
  • local_umask = 022 - po załadowaniu pliku ustawiane będą uprawnienia 755
  • dirmessage_enable = YES = włączamy powitanie użytkowników (plik podawany określamy poprzez message_file)
  • xferlog_enable = YES - włączamy format logowania wu-ftpd
  • connect_from_port_20 = YES - włączamy połączenia aktywne
  • nopriv_user = ftp - nazwa użytkownika używanego przez vsftpd w momencie kiedy chce zrzucić uprawnienia
  • chroot_local_user = YES - chrootuj użytkowników lokalnych (użytkownik nie wyjdzie wyżej do katalogu niż jego HOME)
  • pam_service_name = vsftpd - nazwa usługi podczas autoryzacji pam.d (/etc/pam.d/vsftpd)
  • guest_enable = YES - włączamy konto gościa
  • guest_username = vsftpd - będzie nim użytkownik vsftpd
  • local_root = /home/vsftpd/$USER - określamy katalog do którego vsftpd będzie robił chdir()
  • user_sub_token = $USER - chrootujemy użytkowników do ich katalogów (przydatne dla wirtualnych użytkowników)
  • virtual_use_local_privs = YES - włączamy identyczne traktowanie użytkowników wirtualnych jak i lokalnych

Przejdźmy teraz do konfiguracji pam.d:

root@iDev:/home/jamzed# mv /etc/pam.d/vsftpd /etc/pam.d/vsftpd.orig
root@iDev:/home/jamzed# vi /etc/pam.d/vsftpd

Minimalna zawartość pam.d/vsftpd:

auth required pam_mysql.so user=vsftpd passwd=ftpdpass host=localhost db=vsftpd table=tb_users usercolumn=login passwdcolumn=password crypt=2
account required pam_mysql.so user=vsftpd passwd=ftpdpass host=localhost db=vsftpd table=tb_users usercolumn=login passwdcolumn=password crypt=2

Pozostaje dodanie użytkownika vsftpd:

# useradd -d /home/vsftpd -g nogroup -m -s /bin/false vsftpd

Po tych zmianach, możemy wystartować/zrestartować nasz serwer vsftpd:

root@iDev:/home/jamzed# /etc/init.d/vsftpd restart

Przed założeniem użytkownika w bazie załóżmy strukturę katalogów na filesystemie i ustawmy uprawnienia:

root@iDev:/home/jamzed# mkdir /home/vsftpd
root@iDev:/home/jamzed# mkdir /home/vsftpd/jamzed
root@iDev:/home/jamzed# chown -R vsftpd:nogroup /home/vsftpd/

Teraz możemy już założyć użytkownika w bazie:

root@iDev:/home/jamzed# mysql -uvsftpd -pftpdpass vsftpd
mysql> INSERT INTO tb_users VALUES('','jamzed',PASSWORD('eftep'));

dla sprawdzenia wykonajmy:

mysql> select * from tb_users;
+----+--------+-------------------------------------------+
| id | login  | password                                  |
+----+--------+-------------------------------------------+
|  1 | jamzed | *483A665E1F29FE18A8DD3C658F812A9FC13C1104 |
+----+--------+-------------------------------------------+
1 row in set (0,00 sec)

Pozostaje generalny test, czyli zalogowanie się:

jamzed@makufka:~$ ncftp -ujamzed 192.168.1.194
NcFTP 3.2.2 (Sep 04, 2008) by Mike Gleason (http://www.NcFTP.com/contact/).
Connecting to 192.168.1.194...
(vsFTPd 2.2.0)
Logging in...
Password requested by 192.168.1.194 for user "jamzed".

Please specify the password.

Password: *****

Login successful.
Logged in to 192.168.1.194.
ncftp / > ls -la
drwxr-xr-x    2 105      114          4096 Mar 02 20:15 .
drwxr-xr-x    2 105      114          4096 Mar 02 20:15 ..
ncftp / >

Wszystko poszło bez problemów, nasz serwer FTPd współpracuje z bazą danych, pozostaje już tylko stworzyć formatkę do zmiany haseł i problem z telefonami znika.

PS. Dziękuję Rafałowi 'gwn' za zgłoszenie błędu w konfiguracji (brak użytkownika vsftpd w systemie oraz włączenie konta gościa).