Einleitung:
In diesem Tutorial möchte ich die Konfiguration eines FTP-Servers (ProFTPd)
mit einem MySQL-Backend erklären. Dazu werden wir einen ProFTPd-Server konfigurieren
der die Verifizierung des Benutzers anhand eines MySQL-Backends durchführt. Dabei werden alle Logindaten
sowie Quotadaten (Speicherplatzgröße) in Einträgen einer MySQL-Datenbank hinterlegt.
Dabei wird ledeglich nur ein weiterer System-Benutzer erfordert für alle Daten die via den FTP-Server
vom jeweiligen Client übertragen werden. Für die jeweiligen HomeDirectorys für die entsprechenden FTP-Benutzer
werden die Logindaten im MySQL-Backend hinterlegt. Diese Benutzer sind virtuelle Benutzer.
Vorteile:
– FTP-Benutzer lassen sich frei erweitern ohne weitere System-Benutzer zu hinterlegen
– Einrichtung eines Webinterface wie z.B. proftpd-adm (http://proftpd-adm.sourceforge.net/)
[AdSense-A]
Installation von ProFTPd mit MySQL-Unterstützung:
Zu beginn müssen wir über den Paket-Manager (sofern nicht selbstkompiliert) die jeweiligen
Binarys holen und installieren.
apt-get install proftpd proftpd-mod-mysql
Anlegen von Benutzern für ProFTPd:
Als nächstes sollten wir für den FTP-Server den benötigen Benutzer anlegen, sowie eine Gruppe zu dem FTP-Benutzer:
groupadd -g 2001 ftpgroup useradd -u 2001 -s /bin/false -d /bin/null -g ftpgroup ftpuser
Damit legen wir als erstes eine Benutzergruppe an mit dem Namen “ftpgroup” mit der ID 2001.
Dazu legen wir dann einen neuen User an mit dem Namen “ftpuser”, der sich nicht via ssh einloggen darf
und dessen HomeDirectory das /dev/null Verzeichnis ist sprich “Blackhole”.
Anlegen von Tabellen für ProFTPd:
Als erstes müssen wir eine neue MySQL-Datenbank für ProFTPd anlegen. Dies kann via PhpMyAdmin geschehen
(sofern installiert) oder über die Kommandozeile.
Sollte eine Datenbank via die Kommandozeile angelegt werden sollten Sie sich zunächst einmal über die
Kommandozeile in das DBMS (Database Management System) einloggen.
Danach müssen Sie eine weitere Datenbank anlegen sowie einen Benutzer der auf diese Datenbank zugreifen
darf. Dies tun Sie mit:
CREATE DATABASE proftpd; GRANT SELECT, INSERT, UPDATE, DELETE ON proftpd.* TO 'proftpd'@'localhost' IDENTIFIED BY '<password>'; GRANT SELECT, INSERT, UPDATE, DELETE ON proftpd.* TO 'proftpd'@'localhost.localdomain' IDENTIFIED BY '<password>'; FLUSH PRIVILEGES;
Hierbei sollten Sie natürlich die Variable gegen ein Passwort Ihrer Wahl ersetzen.
Ich empfehle hier mind. ein 10 Zeichen langes Passwort zu wählen aus kleinen Buchstaben, großen Buchstaben und
Zahlen.
Anschließend müssen Sie die jeweiligen Tabellen für den FTP-Server einrichten bzw. Erstellen ob Sie dies
über PhpMyAdmin tätigen oder über die Kommandozeile ist Ihnen überlassen:
CREATE TABLE ftpgroup ( groupname varchar(16) NOT NULL default '', gid smallint(6) NOT NULL default '5500', members varchar(16) NOT NULL default '', KEY groupname (groupname) ) ENGINE=MyISAM COMMENT='ProFTP group table'; CREATE TABLE ftpquotalimits ( name varchar(30) default NULL, quota_type enum('user','group','class','all') NOT NULL default 'user', per_session enum('false','true') NOT NULL default 'false', limit_type enum('soft','hard') NOT NULL default 'soft', bytes_in_avail bigint(20) unsigned NOT NULL default '0', bytes_out_avail bigint(20) unsigned NOT NULL default '0', bytes_xfer_avail bigint(20) unsigned NOT NULL default '0', files_in_avail int(10) unsigned NOT NULL default '0', files_out_avail int(10) unsigned NOT NULL default '0', files_xfer_avail int(10) unsigned NOT NULL default '0' ) ENGINE=MyISAM; CREATE TABLE ftpquotatallies ( name varchar(30) NOT NULL default '', quota_type enum('user','group','class','all') NOT NULL default 'user', bytes_in_used bigint(20) unsigned NOT NULL default '0', bytes_out_used bigint(20) unsigned NOT NULL default '0', bytes_xfer_used bigint(20) unsigned NOT NULL default '0', files_in_used int(10) unsigned NOT NULL default '0', files_out_used int(10) unsigned NOT NULL default '0', files_xfer_used int(10) unsigned NOT NULL default '0' ) ENGINE=MyISAM; CREATE TABLE ftpuser ( id int(10) unsigned NOT NULL auto_increment, userid varchar(32) NOT NULL default '', passwd varchar(32) NOT NULL default '', uid smallint(6) NOT NULL default '2001', gid smallint(6) NOT NULL default '2001', homedir varchar(255) NOT NULL default '', shell varchar(16) NOT NULL default '/sbin/nologin', count int(11) NOT NULL default '0', accessed datetime NOT NULL default '1000-00-00 00:00:00', modified datetime NOT NULL default '1000-00-00 00:00:00', PRIMARY KEY (id), UNIQUE KEY userid (userid) ) ENGINE=MyISAM COMMENT='ProFTP user table';
Konfiguration von ProFTPd für ein MySQL-Backend:
Als aller erstes müssen wir folgende Konfigurationsdatei bearbeiten “/etc/proftpd/modules.conf”:
Dies tun Sie beispielsweise über den Editor nano.
nano /etc/proftpd/modules.conf
Dort kommentieren Sie folgende Zeilen ein:
# Install one of proftpd-mod-mysql, proftpd-mod-pgsql or any other # SQL backend engine to use this module and the required backend. # This module must be mandatory loaded before anyone of # the existent SQL backeds. LoadModule mod_sql.c [...] # Install proftpd-mod-mysql and decomment the previous # mod_sql.c module to use this. LoadModule mod_sql_mysql.c [...] # Install one of the previous SQL backends and decomment # the previous mod_sql.c module to use this LoadModule mod_quotatab_sql.c
Hierbei ist es wichtig dass die Module “mod_sql”, “mod_sql_mysql” sowie “mod_quotatab_sql” geladen werden.
Als nächstes bearbeiten Sie bitte die File “/etc/proftpd/proftpd.conf”:
Dort tätigen Sie folgende Änderungen:
#<IfModule mod_quotatab.c> #QuotaEngine off #</IfModule>
Diese Sektion müssen Sie komplett auskommentieren.
Ebenfalls in der selben Datei fügen Sie zu dem Part “Alternative authentication frameworks” folgendes hinzu:
# # Alternative authentication frameworks # #Include /etc/proftpd/ldap.conf #Include /etc/proftpd/sql.conf DefaultRoot ~ SQLBackend mysql # The passwords in MySQL are encrypted using CRYPT SQLAuthTypes Plaintext Crypt SQLAuthenticate users groups # used to connect to the database # databasename@host database_user user_password SQLConnectInfo proftpd@localhost proftpd <password> # Here we tell ProFTPd the names of the database columns in the "usertable" # we want it to interact with. Match the names with those in the db SQLUserInfo ftpuser userid passwd uid gid homedir shell # Here we tell ProFTPd the names of the database columns in the "grouptable" # we want it to interact with. Again the names match with those in the db SQLGroupInfo ftpgroup groupname gid members # set min UID and GID - otherwise these are 999 each SQLMinID 500 # create a user's home directory on demand if it doesn't exist CreateHome on # Update count every time user logs in SQLLog PASS updatecount SQLNamedQuery updatecount UPDATE "count=count+1, accessed=now() WHERE userid='%u'" ftpuser # Update modified everytime user uploads or deletes a file SQLLog STOR,DELE modified SQLNamedQuery modified UPDATE "modified=now() WHERE userid='%u'" ftpuser # User quotas # =========== QuotaEngine on QuotaDirectoryTally on QuotaDisplayUnits Mb QuotaShowQuotas on SQLNamedQuery get-quota-limit SELECT "name, quota_type, per_session, limit_type, bytes_in_avail, bytes_out_avail, bytes_xfer_avail, files_in_avail, files_out_avail, files_xfer_avail FROM ftpquotalimits WHERE name = '%{0}' AND quota_type = '%{1}'" SQLNamedQuery get-quota-tally SELECT "name, quota_type, bytes_in_used, bytes_out_used, bytes_xfer_used, files_in_used, files_out_used, files_xfer_used FROM ftpquotatallies WHERE name = '%{0}' AND quota_type = '%{1}'" SQLNamedQuery update-quota-tally UPDATE "bytes_in_used = bytes_in_used + %{0}, bytes_out_used = bytes_out_used + %{1}, bytes_xfer_used = bytes_xfer_used + %{2}, files_in_used = files_in_used + %{3}, files_out_used = files_out_used + %{4}, files_xfer_used = files_xfer_used + %{5} WHERE name = '%{6}' AND quota_type = '%{7}'" ftpquotatallies SQLNamedQuery insert-quota-tally INSERT "%{0}, %{1}, %{2}, %{3}, %{4}, %{5}, %{6}, %{7}" ftpquotatallies QuotaLimitTable sql:/get-quota-limit QuotaTallyTable sql:/get-quota-tally/update-quota-tally/insert-quota-tally RootLogin off RequireValidShell off
Unter dem Punkt SQLConnectInfo fügen Sie ihr definiertes Kennwort für den ProFTPd MySQL-User ein. Dies muss exakt das selbe sein wie, dass welches Sie bei dem
Erstellungsvorgang für den MySQL-Benutzer gewählt haben sein.
Anschließend um alle Änderungen zu übernehmen starten Sie den FTP-Server neu:
/etc/init.d/proftpd restart
Soweit sollte nun die Kommunikation zwischen der Datenbank und dem FTP-Server stehen.
Einrichten der FTP-User:
Nun sind wir an der stelle wo wir die FTP-Benutzer anlegen müssen.
Als aller erstes legen wir eine neue Benutzergruppe in unserer Datenbank an:
INSERT INTO `ftpgroup` (`groupname`, `gid`, `members`) VALUES ('ftpgroup', 2001, 'ftpuser');
Damit teilen wir dem FTP-Server mit welchen System-Benutzer er nutzen soll und in welcher Gruppe dieser sich befindet.
Diesen Benutzer haben wir vor der Konfiguration unseres FTP-Servers angelegt.
Als nächstes wir einen neuen FTP-Benutzer an der dieser Gruppe zugeteilt wird:
INSERT INTO `ftpquotalimits` (`name`, `quota_type`, `per_session`, `limit_type`, `bytes_in_avail`, `bytes_out_avail`, `bytes_xfer_avail`, `files_in_avail`, `files_out_avail`, `files_xfer_avail`) VALUES ('example', 'user', 'true', 'hard', 15728640, 0, 0, 0, 0, 0);
Hierbei bekommt der neue FTP-Benutzer den Usernamen “example” und wird dem quotatype “user” zugeordnet, hier legen wir bloß den Quota für den neuen Benutzer an.
Die maximale Quotagröße (Speicherplatz) beträgt 300 MB ausgedrückt in Kilobyte.
Nun müssen wir als nächstes en richtigen FTP-Benutzer anlegen. dies tun wir mit:
INSERT INTO `ftpuser` (`userid`, `passwd`, `uid`, `gid`, `homedir`, `shell`, `count`, `accessed`, `modified`) VALUES ('example', '<password>', 2001, 2001, '/home/www.example.com', '/sbin/nologin', 0, '', '');
Hierbei legen wir einen Benutzer an mit dem Usernamen “example” und einem Passwort ersetzen Sie hier gegen das Passwort das Sie sich für den Benutzer wünschen.
Außerdem bekommt der User das HomeDirectory “/home/www.example.com/” welches ebenfalls dann jailed ist. Sowie die Shell “/sbin/nlogin” zugewiesen, womit sich der User nicht
via SSH einloggen darf.
Rechteverwaltung:
Bestimmen Sie ein Verzeichnis für alle FTP-User bestenfalls schon im Vorfeld und geben Sie diesem die Besitzrechte für das gesamte Verzeichnis.
chown -R ftpuser:ftpgroup <verzeichnis>
Verzeichnis ersetzen Sie gegen das Verzeichnis in dem alle FTP-Verzeichnisse liegen.
Hi Ilya Beliaev,
vielen Dank für den detaillierten Beitrag. Vor allem die Foramtierung ist hervorragend.
Aufgefallen ist mir aber, dass bei CREATE TABLE ftpuser (
…
accessed datetime NOT NULL default ‘0000-00-00 00:00:00’,
modified datetime NOT NULL default ‘0000-00-00 00:00:00’,
die Sache erst funktioniert wenn man die values z.B. auf ‘1000-00-00 00:00:00’ setzt. Sonst zeigt phpmyadmin einen Fehler an.
Bitte in deinem Script aktualisieren damit andere nicht über diese Sache stolpern.
Huhu Florian,
Danke für den Hinweis, der Beitrag wird von mir in den kommenden Tagen noch einmal ergänzt werden.
Hallo Florian,
den “Fehler” wird durch den STRICT-Mode erzeugt, der bei einigen Datentypen keinen Standardwert = zulässt. Das kannst Du ausschalten mit sql_mode=” in der Config.
Besten Gruß
Super Tut. Danke.
Eine Frage:
Ich möchte, das user2 nur lesen/downloaden kann.
User1 kann alles, wobei beide User im gleichen Verzeichnis sind und dieses an User1 gehört.
Wie kann ich das bewerkstelligen? Wenn ich an User2 eine andere UID oder GID gebe, kommt “Login incorrect”.
auch wenn das ganze Thema bzgl. der Authentifizierung in die Datenbank ausgelagert ist, gelten normale Linux-Systemrechte. Für lesenden Zugriff müsste dahingehend auch ein weiterer System-Benutzer angelegt werden, mit den entsprechenden Leserechten. Anschließend müsste der Benutzer gelinked werden am FTP-Benutzer in der Datenbank, anhand der uid und gid.
Hi Ilya,
vielen Dank für die ausführliche Anleitung. Ich hab es soweit hin bekommen, dass ich eine Datenbank mit zwei Benutzer habe. Auch die Änderungen im proftp scheinen soweit zu funktionieren, da der proftpd beim Start keinen Fehler ausgibt.
Nun habe ich allerdings das Problem, dass wenn ich im Browser die IP adresse (ftp://192.168.X.X) eingebe, kein Login Menü erscheint. Ich habe nur eine leere Firefox Seite. Ich hab wohl irgendwas falsch gemacht, oder vergessen. Hast Du vielleicht eine Idee was da schief geht. Ich würde mich freuen, wenn Du mir da irgendwie helfen könntest
Hallo,
Der FTP Server ist in erster Linie ein eigenständiger standalone Service, der mit dem Webserver nichts am Hut hat. Wenn es gewünscht ist den ftp Zugang auch über einen Webserver zur Verfügung zu stellen sind weitere Konfigurationen nötig. Stichwort Apache und mod_ftp (https://httpd.apache.org/mod_ftp/)