Virtuelles Hosting mit Proftpd und MySQL (inkl. Quota) auf Fedora 7

Version 1.0
Author: Falko Timme


Diese Anleitung veranschaulicht, wie man einen Proftpd Server installiert, der virtuelle Benutzer einer MySQL Datenbank verwendet anstelle von wirklichen Benutzern. Dies ist um einiges leistungsfähiger und ermöglicht es, Tausende von ftp Benutzern auf nur einer Maschine zu haben. Weiterhin werde ich die Anwendung von Quota in diesem Setup beschreiben.

Zur Administration der MySQL Datenbank kannst Du web-basierte Tools wie phpMyAdmin verwenden, das in dieser Anleitung ebenfalls installiert wird. phpMyAdmin ist eine angenehme grafische Oberfläche, was bedeutet, dass Du nicht mit der Kommandozeile rumbasteln musst.

Diese Anleitung basiert auf Fedora 7. Du solltest ein Fedora 7 Basissystem bereits installiert haben, was in den ersten vier Kapiteln dieser Anleitung beschrieben wird: http://www.howtoforge.com/perfect_server_fedora7
Diese Anleitung ist ein praktischer Leitfaden; theoretisches Hintergrundwissen wird nicht abgedeckt. Dies wird in zahlreichen anderen Dokumenten im Netz behandelt.

Diese Anleitung ist ohne jegliche Gewähr! Ich möchte an dieser Stelle darauf hinweisen, dass dies nicht der einzige Weg ist, ein solches System einzurichten. Es gibt viele Möglichkeiten ans Ziel zu kommen - dies ist der Weg, den ich gewählt habe. Ich übernehme keine Garantie, dass dies auch bei Dir funktioniert!

1 Vorbemerkung

In dieser Anleitung verwende ich den Hostnamen server1.example.com mit der IP Adresse 192.168.0.100. Diese Einstellungen werden von Deinen abweichen, Du musst sie also an entsprechender Stelle ersetzen.

2 Installation von MySQL und phpMyAdmin

Das kann alles mit nur einem Befehl installiert werden:

yum install mysql mysql-server phpMyAdmin httpd

Danach müssen wir die Datei /etc/httpd/conf.d/phpMyAdmin.conf bearbeiten, damit auf phpMyAdmin von allen IP Adressen aus zugegriffen werden kann. Es ist standardmäßig nur von 127.0.0.1. aus zugreifbar. Kommentiere diesen Bereich aus:

<Directory /usr/share/phpMyAdmin/>
order deny,allow
deny from all
allow from 127.0.0.1
</Directory>

so dass die Datei wie folgt aussieht:

vi /etc/httpd/conf.d/phpMyAdmin.conf


# phpMyAdmin - Web based MySQL browser written in php
# # Allows only localhost by default # # But allowing phpMyAdmin to anyone other than localhost should be considered # dangerous unless properly secured by SSL Alias /phpMyAdmin /usr/share/phpMyAdmin #<Directory /usr/share/phpMyAdmin/> # order deny,allow # deny from all # allow from 127.0.0.1 #</Directory> # This directory does not require access over HTTP - taken from the original # phpMyAdmin upstream tarball # <Directory /usr/share/phpMyAdmin/libraries> Order Deny,Allow Deny from All Allow from None </Directory> # This configuration prevents mod_security at phpMyAdmin directories from # filtering SQL etc. # <IfModule mod_security.c> <LocationMatch "/phpMyAdmin/(.+)"> SecFilterInheritance Off </LocationMatch> </IfModule>
Dann erstellen wir die System Startup Links für MySQL und Apache (so dass beide automatisch starten wenn das System hochfährt) und starten beide Dienste:

chkconfig --levels 235 mysqld on
/etc/init.d/mysqld start

chkconfig --levels 235 httpd on
/etc/init.d/httpd start

Richte ein Password für den MySQL Benutzer root ein (ersetze yourrootsqlpassword mit einem Passwort Deiner Wahl):

mysqladmin -u root password yourrootsqlpassword
mysqladmin -h server1.example.com -u root password yourrootsqlpassword

3 Installation von Proftpd mit MySQL Unterstützung

Für Fedora ist ein vorkonfiguriertes proftpd-mysql Paket verfügbar. Installiere es wie folgt:

yum install proftpd-mysql

Dann erstellen wir eine ftp Gruppe (ftpgroup) und einen Benutzer (ftpuser), unter denen unsere virtuellen Benutzer laufen werden. Ersetze die Gruppen- und Benutzer-id 2001 mit einer Nummer, die auf Deinem System frei ist:

groupadd -g 2001 ftpgroup
useradd -u 2001 -s /bin/false -d /bin/null -c "proftpd user" -g ftpgroup ftpuser

4 Die MySQL Datenbank für Proftpd erstellen

Nun erstellen wir eine Datenbank namens ftp und einen MySQL Benutzer namens proftpd, den der proftpd Daemon später verwenden wird um sich mit der ftp Datenbank zu verbinden:

mysql -u root -p


create database ftp;
GRANT SELECT, INSERT, UPDATE, DELETE ON ftp.* TO 'proftpd'@'localhost' IDENTIFIED BY 'password';
GRANT SELECT, INSERT, UPDATE, DELETE ON ftp.* TO 'proftpd'@'localhost.localdomain' IDENTIFIED BY 'password';
FLUSH PRIVILEGES;

Ersetze die Zeichenfolge password mit einem Passwort, welches Du für den MySQL Benutzer proftpd verwenden möchtest. Immer noch in der MySQL Kommandozeile, erstellen wir die Dantenbanktabellen, die wir benötigen:

USE ftp;


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)
) TYPE=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 int(10) unsigned NOT NULL default '0',
bytes_out_avail int(10) unsigned NOT NULL default '0',
bytes_xfer_avail int(10) 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'
) TYPE=MyISAM;

CREATE TABLE ftpquotatallies (
name varchar(30) NOT NULL default '',
quota_type enum('user','group','class','all') NOT NULL default 'user',
bytes_in_used int(10) unsigned NOT NULL default '0',
bytes_out_used int(10) unsigned NOT NULL default '0',
bytes_xfer_used int(10) 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'
) TYPE=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 '5500',
gid smallint(6) NOT NULL default '5500',
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 '0000-00-00 00:00:00',
modified datetime NOT NULL default '0000-00-00 00:00:00',
PRIMARY KEY (id),
UNIQUE KEY userid (userid)
) TYPE=MyISAM COMMENT='ProFTP user table';

quit;

Wie Dir vielleicht aufgefallen ist, haben wir mit dem quit; Befehl die MySQL Kommandozeile verlassen und befinden uns wieder in der Linux Kommandozeile.

Übrigens kannst Du auf (ich gehe davon aus, dass der Hostname für Dein ftp Server System server1.example.com ist) phpMyAdmin unter http://server1.example.com/phpMyAdmin/ (Du kannst anstelle von server1.example.com dieIP Adresse verwenden) in einem Browser zugreifen und Dich als proftpd anmelden. Dann kannst Du Dir die Datenbank ansehen. Später kannst Du phpMyAdmin verwenden, um Deinen Proftpd Server zu verwalten.

5 Konfiguriere Proftpd

Öffne /etc/proftpd.conf und kommentiere die AuthPAMConfig und AuthOrder Zeilen aus:

vi /etc/proftpd.conf


[...]
# Use pam to authenticate (default) and be authoritative #AuthPAMConfig proftpd #AuthOrder mod_auth_pam.c* mod_auth_unix.c [...]
Weiter unten in der gleichen Datei, füge folgende Zeilen direkt unter der <IfModule mod_dso.c>...</IfModule> Zeile an:
[...]
# SQL authentication Dynamic Shared Object (DSO) loading # See README.DSO and howto/DSO.html for more details. #<IfModule mod_dso.c> # LoadModule mod_sql.c # LoadModule mod_sql_mysql.c # LoadModule mod_sql_postgres.c #</IfModule> LoadModule mod_sql.c LoadModule mod_sql_mysql.c LoadModule mod_quotatab.c LoadModule mod_quotatab_sql.c # 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 ftp@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 SQLHomedirOnDemand 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 [...]
Pass auf, dass Du die Zeichenfolge password mit dem richtigen Passwort für den MySQL Benutzer proftpd in der Zeile SQLConnectInfo ersetzt!

Dann erstellen wir die System Startup Links für Proftpd und starten es:

chkconfig --levels 235 proftpd on
/etc/init.d/proftpd start

6 Die Datenbank füllen und testen

Um die Datenbank zu füllen, kannst Du die MySQL Kommandozeile verwenden:

mysql -u root -p

USE ftp;

Zuerst erstellen wir einen Eintrag in der Tabelle ftpgroup. Sie enthält den Gruppennamen, die Gruppen-id und den Benutzernamen der ftp Gruppe/des Benutzers, die wir am Ende von Schritt zwei angelegt haben (ersetze die Gruppen-id an entsprechender Stelle, falls Du etwas anderes als 2001 verwendest):

INSERT INTO `ftpgroup` (`groupname`, `gid`, `members`) VALUES ('ftpgroup', 2001, 'ftpuser');

Nun sind wir mit der Tabelle ftpgroup fertig. Wir müssen hier keine weiteren Einträge erstellen. Immer wenn Du einen neuen virtuellen Benutzer anlegst, machst Du das in den Tabellen ftpquotalimits und ftpuser. Lass uns also jetzt unseren ersten Benutzer exampleuser mit einer Quota von 15MB und dem Passwort secret erstellen (immer noch in der MySQL Kommandozeile):

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 ('exampleuser', 'user', 'true', 'hard', 15728640, 0, 0, 0, 0, 0);

INSERT INTO `ftpuser` (`id`, `userid`, `passwd`, `uid`, `gid`, `homedir`, `shell`, `count`, `accessed`, `modified`) VALUES (1, 'exampleuser', 'secret', 2001, 2001, '/home/www.example.com', '/sbin/nologin', 0, '', '');

quit;

(Vergiss nicht die Gruppen- und Benutzer-id 2001 an entsprechender Stelle im letzten INSERT Statement zu ersetzen, falls Du andere Werte als in dieser Anleitung verwendest!)

Öffne nun Dein FTP Client Programm an Deinem Arbeitsplatz (etwas wie WS_FTP oder SmartFTP wenn Du Dich auf einem Windows System befindest oder gFTP auf einem Linux Desktop) und versuche Dich zu verbindent. Als Hostnamen verwendest Du server1.example.com (oder die IP Adresse Deines Systems), der Benutzername ist exampleuser und das Passwort ist secret.

Wenn Du in der Lage bist, Dich zu verbinden - Herzlichen Glückwunsch! Wenn nicht, ist etwas schief gelaufen.

Wenn Du nun Folgendes ausführst

ls -l /home/

müsstest Du feststellen, dass das Verzeichnis /home/www.example.com (exampleusers Home Verzeichnis) automatisch erstellt wurde und im Besitz von ftpuser und ftpgroup (der Benutzer/die Gruppe, die wir am Ende von Schritt zwei angelegt haben) ist:

[root@server1 ~]# ls -l /home/
total 4
drwxr-xr-x 2 ftpuser ftpgroup 4096 2007-08-06 16:11 www.example.com
[root@server1 ~]#

7 Administration der Datenbank

Für die Meisten ist es einfacher, wenn sie ein grafisches Frontend zu MySQL haben; dazu kannst Du ebenfalls phpMyAdmin verwenden (in diesem Beispiel unter http://server1.example.com/phpMyAdmin/) um die ftp Datenbank zu verwalten.


Immer wenn Du einen neuen Benutzer anlegst, musst Du lediglich Einträge in den Tabellen ftpquotalimits und ftpuser erstellen, also werde ich die Spalten dieser Tabellen hier erklären:

ftpuser Tabelle:

Die wichtigen Spalten sind folgende (die anderen werden von MySQL oder Proftpd automatisch bedient, füll diese also nicht manuell aus!):
  • userid: Der Name des virtuellen Proftpd Benutzers (z.B. exampleuser).
  • passwd: Das unverschlüsselte (d.h. Klartext) Passwort des Benutzers.
  • uid: Die Benutzer-id des ftp Benutzers, den Du am Ende von Schritt zwei angelegt hast (z.B. 2001).
  • gid: Die Gruppen-id der ftp Gruppe, die Du am Ende von Schritt zwei angelegt hast (z.B. 2001).
  • homedir: Das Home Verzeichnis des virtuellen Proftpd Benutzers (z.B. /home/www.example.com). Wenn es nicht existiert, wird es erstellt, wenn sich der neue Benutzer zum ersten Mal via FTP anmeldet. Der virtuelle Benutzer wird in dieses Home Verzeichnis gesperrt, d.h. er kann auf andere Verzeichnisse außerhalb des Home Verzeichnisses nicht zugreifen.
  • shell: Es ist in Ordnung wenn Du hier /sbin/nologin standardmäßig ausfüllst.

ftpquotalimits Tabelle:

Die wichtigen Spalten sind folgende (die anderen werden von MySQL oder Proftpd automatisch bedient, füll diese also nicht manuell aus!):
  • name: Der Name des virtuellen Proftpd Benutzers (z.B. exampleuser).
  • quota_type: user oder group. Normalerweise verwenden wir hieruser.
  • per_session: true oder false. true bedeutet, dass die Quota-Limits nur für eine Session gültig sind. Wenn der Benutzer zum Beispiel eine Quota von 15 MB hat und er während der derzeitigen Session 15 MB hochgeladen hat, dann kann er nicht mehr hochladen. Wenn er sich aber abmeldet und wieder neu anmeldet, stehen ihm wieder 15 MB zur Verfügung. false bedeutet, dass der Benutzer 15 MB hat, egal ob er sich ab- und wieder anmeldet.
  • limit_type: hard oder soft. Ein hard Quota-Limit ist ein Limit, das nicht überschritten werden kann, während ein soft Quota-Limit vorübergehend überschritten werden kann. Normalerweise verwendet man hier hard.
  • bytes_in_avail: Upload-Limit in Bytes (z.B. 15728640 für 15 MB). 0 bedeutet unbegrenzt.
  • bytes_out_avail: Download-Limit in Bytes. 0 bedeutet unbegrenzt.
  • bytes_xfer_avail: Transfer-Limit in Bytes. Die Summe der Uploads und Downloads, die ein Benutzer tätigen darf. 0 bedeutet unbegrenzt.
  • files_in_avail: Upload-Limit in Dateien. 0 bedeutet unbegrenzt.
  • files_out_avail: Download-Limit in Dateien. 0 bedeutet unbegrenzt.
  • files_xfer_avail: Tranfer-Limit in Dateien. 0 bedeutet unbegrenzt.
Die ftpquotatallies Tabelle wird von Proftpd intern verwendet um Quotas zu verwalten, Du musst dort keine Einträge vornehmen!

8 Anonyme FTP

Wenn Du ein anonymes ftp Konto einrichten möchtest (ein ftp Konto, in das sich jeder ohne Passwort einloggen kann), führst Du Folgendes aus:

Zuerst erstellen wir einen Benutzer und ein Gruppe mit dem Namen anonymous_ftp. Der Benutzer hat das Home Verzeichnis /home/anonymous_ftp:

groupadd -g 2002 anonymous_ftp
useradd -u 2002 -s /bin/false -d /home/anonymous_ftp -m -c "Anonymous FTP User" -g anonymous_ftp anonymous_ftp

(Ersetze 2002 mit einer Gruppen-/Benutzer-id, die auf Deinem System frei ist.)

Es wurden mit dem letzten Befehl (useradd) einige Dateien im /home/anonymous_ftp Verzeichnis erstellt, die mit . beginnen. Wir brauchen diese nicht, also löschen wir sie:

cd /home/anonymous_ftp
rm -fr *

Dann erstellen wir das Verzeichnis /home/anonymous_ftp/incoming das anonymen Benutzern erlaubt, Dateien hochzuladen:

mkdir /home/anonymous_ftp/incoming
chown anonymous_ftp:nobody /home/anonymous_ftp/incoming

Öffne /etc/proftpd.conf und fügen die folgenden Direktiven ein (ganz am Ende, nach allem anderen):

vi /etc/proftpd.conf


[...]
<Anonymous ~anonymous_ftp> User anonymous_ftp Group nobody # We want clients to be able to login with "anonymous" as well as "ftp" UserAlias anonymous anonymous_ftp # Cosmetic changes, all files belongs to ftp user DirFakeUser on anonymous_ftp DirFakeGroup on anonymous_ftp RequireValidShell off # Limit the maximum number of anonymous logins MaxClients 10 # We want 'welcome.msg' displayed at login, and '.message' displayed # in each newly chdired directory. DisplayLogin welcome.msg DisplayFirstChdir .message # Limit WRITE everywhere in the anonymous chroot <Directory *> <Limit WRITE> DenyAll </Limit> </Directory> <Directory incoming> # Umask 022 is a good standard umask to prevent new files and dirs # (second parm) from being group and world writable. Umask 022 022 <Limit READ WRITE> DenyAll </Limit> <Limit STOR> AllowAll </Limit> </Directory> </Anonymous>
Starte Proftpd schließlich neu:

/etc/init.d/proftpd restart

Nun können sich anonyme Benutzer anmelden und Dateien von /home/anonymous_ftp runter laden, Uploads auf /home/anonymous_ftp/incoming sind allerdings begrenzt (und wenn eine Datei einmal in /home/anonymous_ftp/incoming hochgeladen ist, kann es von dort aus nicht gelesen oder runter geladen werden; der Server Administrator muss sie zuerst in /home/anonymous_ftp setzen, um sie anderen zugänglich zu machen).

(Bitte Merke: Du kannst nur ein anonymes ftp Konto pro IP Adresse haben!)

9 Referenzen

Mandrake 10.1 - Proftpd + MySQL Authentifizierung + Quotas Anleitung: http://www.khoosys.net/single.htm?ipg=848

10 Links

0 Kommentar(e)

Zum Posten von Kommentaren bitte