Datenbank-Setup · 6 min read · Dec 17, 2025

PostgreSQL und Proftpd

So Sie einen FTP-Server einrichten möchten, benötigen Sie erweiterte Funktionen und wissen nicht, wo Sie sich hinwenden sollen? Versuchen Sie es mit proftpd.

Teil 1: Einrichtung von proftpd mit einem PostgreSQL-Backend

Dieses Tutorial ist sehr speziell, ich werde nur proftpd behandeln und nur insoweit, um es mit Postgres betriebsbereit zu machen. Ein grundlegendes Verständnis von proftpd und Postgres wird vorausgesetzt. Dieses Tutorial wird Ihnen helfen, proftpd ziemlich schnell zum Laufen zu bringen und es eine Datenbank nutzen zu lassen; wenn diese Datenbank Trigger hat, sind die Möglichkeiten dieser Konfiguration nahezu endlos.

Proftpd erhalten

Zuerst benötigen Sie proftpd, ich werde Ubuntus Dapper verwenden; es gibt ein Meta-Paket, das dank Francesco Paolo Lovergine mit dem Titel “proftpd-pgsql” vorbereitet wurde, das eine Kopie von proftpd mit den folgenden Modulen einrichtet. Als Anmerkung, während proftpd mit den Mods geliefert wird, ist die Konfigurationsdatei das Standard-proftpd-Boilerplate. Ich empfehle Ihnen dringend, die mod_sql-Dokumentation zu überprüfen, die zwar suboptimal ist, aber dennoch nützlich – die Dokumentation auf der proftpd-Website ist sehr alt, verwenden Sie stattdessen diese: Link zu den Dokumenten. Seien Sie auch vorsichtig mit der Version, proftpd ist jetzt bei 1.3, obwohl ich 1.2.10 verwenden werde – die Version, die in Dapper verwendet wird.

Die in dieser Version von proftpd kompilierten Mods sind wie folgt

  mod_core.c  
  mod_xfer.c  
  mod_auth_unix.c  
  mod_auth_file.c  
  mod_auth.c  
  mod_ls.c  
  mod_log.c  
  mod_site.c  
  mod_auth_pam.c  
  mod_quotatab.c  
  mod_sql.c  
  mod_sql_postgres.c  
  mod_quotatab_sql.c  
  mod_ratio.c  
  mod_tls.c  
  mod_rewrite.c  
  mod_radius.c  
  mod_wrap.c  
  mod_quotatab_file.c  
  mod_delay.c  
  mod_readme.c  
  mod_ifsession.c  
  mod_cap.c

Fahren Sie fort und geben Sie den Befehl ein, um proftpd-pgsql zu installieren:

apt-get install proftpd-pgsql

Berechtigungen einrichten.

Für meinen Zweck (denken Sie daran, ich bin das Zentrum des Universums) benötigte ich nur eine eindimensionale Struktur, da Gruppen auf einer anderen Ebene gespeichert werden, anstatt Unix-Berechtigungen. Daher sollten alle Dateien mit statischen Berechtigungen eingehen – ich kümmere mich nur um den Eigentümer und die Gruppe des Eigentümers. Mein Plan war es, den Standardbenutzer von proftpd, ftp, seiner eigenen treffend benannten Gruppe zuzuordnen, die ich erstellen wollte – ‘ftp’. Dann wollte ich Postgres Mitglied dieser Gruppe machen, siehe Teil 2 für die Begründung. Ich benötigte beide als Mitglieder derselben Gruppe, und ich benötigte, dass der proftpd chroot-Ordner 775 ist, damit die gesamte Gruppe Dateien hinzufügen (verschieben) kann, ich machte auch den Ordner im Besitz des Benutzers ‘ftp’, mit der Gruppe ‘ftp’. Ich erreichte dies mit dem folgenden Skript.

groupadd ftp
usermod -G ftp ftp
usermod -G ftp,postgres postgres
chown ftp:ftp ./ftp_directory/
chmod 775 ./ftp_directory/

Postgres einrichten

Jetzt werden wir unsere SQL-Tabellen vorbereiten. Ich entwerfe unter Verwendung von Schemata, und dafür ist das Präfix ‘ftp.’ bei den Tabellen gedacht. Ich habe alle meine Tabellen in ein ftp-Schema gelegt, es gibt eine Sache, die erwähnenswert ist, ich war extrem restriktiv bei den Berechtigungen für dieses Projekt, weil ich mir nicht sicher bin, wie sicher mod_sql ist. Dabei habe ich einen speziellen Benutzer, namens proftp, für proftpd in meiner Datenbank erstellt (die mehr Anwendungen als proftpd nutzen), dieser Benutzer ist auf Auswahlen in der auth_table und Einfügungen in der file_log-Tabelle beschränkt. Ich empfehle dringend, eine Form dieser Richtlinie zu übernehmen. Zumindest verhindert dies ein gewisses Maß an verheerenden SQL-Injection-Angriffen oder Informationslecks, falls der mod_sql-Code nicht so sicher ist, wie wir gerne denken würden. Eine schnelle Google-Suche zeigt ein vorheriges Sicherheitsproblem mit dem mod_sql-Code. Jede Abfrage, die mod_sql an die DB sendet, wird mit einer “LIMIT 1”-Klausel ergänzt, und mit mod_delay, das standardmäßig ebenfalls konfiguriert ist, finde ich dies für dieses Projekt ausreichend.

Mein SQL-Init-Skript ist wie folgt.

ALTER USER proftp UNENCRYPTED PASSWORD 'dealermadeftp';
CREATE SCHEMA ftp;
GRANT USAGE ON SCHEMA ftp TO proftp;

CREATE TABLE ftp.users (
        pkid      serial      PRIMARY KEY,
        userid    text        NOT NULL UNIQUE,
        passwd    text,
        uid       int,
        gid       int,
        homedir   text,
        shell     text
);
GRANT SELECT ON ftp.users TO proftp;
INSERT INTO ftp.users ( userid, passwd ) VALUES ( 'ecarroll', 'adm1n' );
INSERT INTO ftp.users ( userid, passwd ) VALUES ( 'jgallagher', 'adm1n' );

CREATE TABLE ftp.file_log (
        pkid               serial      PRIMARY KEY,
        userid             text        REFERENCES ftp.users(userid),
        abs_path           text,
        file               text,
        dns                text,
        time_transaction   text,
        ts_in              timestamp with time zone   NOT NULL DEFAULT CURRENT_TIMESTAMP
);
GRANT INSERT ON ftp.file_log TO proftp;
GRANT UPDATE ON TABLE ftp.file_log_pkid_seq TO proftp;

Verbinden Sie sich mit Ihrer Datenbank und führen Sie das mit aus:

\i script_name

oder Sie können ‘–file script_name’ als Befehlszeilenargument an psql senden.

Diejenigen, die mit weniger leistungsfähigen Datenbanken (dieses Tutorial mit MySQL verwenden), möchten möglicherweise text durch varchar ersetzen; aber aufgrund des Designs von Postgres gibt es keinen Vorteil dabei.

Proftpd einrichten

Dieser Teil ist knifflig und variiert leicht, wenn Sie 1.3 verwenden – nochmals, dieses Tutorial ist für 1.2.10.

Ich habe diesen Teil zu meinem Standard-proftpd-Boilerplate-Konfigurationsdatei, die sich unter /etc/proftpd.conf befindet, hinzugefügt:

AuthOrder            mod_sql.c
SQLAuthTypes         Plaintext Empty
SQLAuthenticate      users
SQLConnectInfo       proftpd@localhost proftp dealermadeftp

SQLDefaultUID        110   # ÄNDERN SIE FÜR IHRE FTP-BENUTZER UID, DIE IN /etc/passwd GEFUNDEN WURDE
SQLDefaultGID        1001  # ÄNDERN SIE FÜR IHRE FTP-BENUTZER GID, DIE IN /etc/groups GEFUNDEN WURDE
SQLDefaultHomedir    /home/ftp
RequireValidShell    off

SQLUserInfo          ftp.users userid passwd uid gid homedir shell

SQLNegativeCache     off
SQLLogFile           /var/log/proftpd-sql
SQLLog               STOR newfile
SQLNamedQuery        newfile FREEFORM "INSERT INTO ftp.file_log(userid,abs_path,file,dns,time_transaction) VALUES ('%U','%f','%J','%V','%T')"

# %U => userid
# %D => --Nichts,
# %f => abs_path
# %J => file
# %h => dns_remote, %V => dns_local
# %a => remote_ip, %L => local_ip
# %t => localtime
# %T => transfer_time
  • Die Vorlagenvariablen sind kommentiert und nur zu Ihrer eigenen Referenz. Eine kurze Zusammenfassung der Konfiguration wie folgt:
  1. Hier setzen wir die AuthOrder auf mod_sql.c, wodurch mod_sql aktiviert wird.
  2. Ich habe mich entschieden, Klartext-Passwörter zu verwenden, oder im Falle, dass ich kein Passwort zuweise, leere Passwörter zuzulassen. (Ich werde später einen Trigger implementieren, um die Passwörter in der Datenbank zu SHA1 zu verschlüsseln.)
  3. Ich habe dann SQLAuthenticate auf users gesetzt, ich habe mich entschieden, keine Gruppen für dieses Projekt zu verwenden, wenn Sie Gruppen benötigen, finden Sie weitere Informationen zu diesen Tabellen auf: Diese Website für Dokumente zu Gruppen.
  4. SQLConnectInfo ist die DSN im Format “Datenbank@Host Benutzer Passwort,”.
  5. SQLDefaultUID, SQLDefaultGID, SQLDefaultHomedir konfigurieren die Standardwerte, wobei die Mehrheit meiner Spalten NULL bleibt, ich werde dies selten überschreiben.
  6. RequireValidShell ist ebenfalls auf aus gesetzt, wenn Sie es auf ein setzen und eine ungültige Shell eingeben, wird die Authentifizierung fehlschlagen.
  7. Die SQLUserInfo entspricht den Postgres-Tabellen, es ist eine wörtliche Zuordnung, erneut gibt das “ftp.” das Schema für die Authentifizierungstabelle an.
  8. SQLNegativeCache speichert Authentifizierungsfehler.
  9. SQLLogFile für ausführliches Logging während der Konfiguration Ihres Servers. Ich werde es deaktivieren, wenn ich in die Produktion gehe.
  10. SQLLog gibt an, welche FTP-Aktion Sie protokollieren möchten, da meine Benutzer nur hochladen können, protokolliere ich nur STOR, das Format ist ‘ftpaction query_to_execute’.
  11. SQLNamedQuery Überprüfen Sie die Syntax in den Dokumenten zu diesem Punkt für eine bessere Erklärung, das Format, das ich verwende, ist ‘qryname FREEFORM custom_query_here’, ich mache dies hauptsächlich, weil ich viele der Template-Variablen von proftpd erfassen möchte, es gibt andere einfachere Syntaxen.

Das war’s. Wenn alles nach Plan läuft, sollten Sie betriebsbereit sein. Jetzt, wenn jemand eine Datei hochlädt, sollte dies das Ergebnis sein:

proftpd=# select * from ftp.file_log;
 pkid |  userid  |        abs_path        |     file      |  dns  | time_transaction |             ts_in 
------+----------+------------------------+---------------+-------+------------------+-------------------------------
    1 | ecarroll | /home/ftp/foo/testfile | /foo/testfile | AMD64 | 0.000            | 2006-06-11 20:49:12.623375-05
(1 row)

Teil II: Über “funktionierend”

… Aber funktionierend ist nie genug, oder? Lassen Sie uns die folgende Frage beantworten, die im Konfigurations-FAQ für proftpd gestellt wurde:
Kann ich Dateien nach dem Hochladen aus einem Upload-Verzeichnis rotieren?

Und die Antwort ist, das können Sie sicher. Ich werde dies durch eine gespeicherte Prozedur erreichen, damit die Dateien auf die richtige Weise – im laufenden Betrieb – ohne einen Daemon verschoben werden.

Sie müssen zuerst untrusted plperlu auf dem System installieren, dies kann erreicht werden mit

apt-get install postgresql-plperl-8.1

Dann müssen Sie plperlu in der Datenbank installieren

createlang plperlu your_database_here

Als nächstes müssen wir einen schnellen Perl-Skript-Trigger erstellen, der bei jedem Einfügen in unsere ftp_log-Tabelle ausgelöst wird

CREATE OR REPLACE FUNCTION ftp_file() RETURNS TRIGGER AS $$
        use warnings;
        use Cwd;
        use File::Basename;
        use File::Spec;
        use File::Copy;
        move (
                $_TD->{new}{abs_path},
                File::Spec->catfile( '/home/ftp/', basename($_TD->{new}{file}) )
        );
        return;
$$ LANGUAGE 'plperlu' VOLATILE;

CREATE TRIGGER ftp_file
        BEFORE INSERT
        ON ftp.file_log
        FOR EACH ROW
        EXECUTE PROCEDURE ftp_file()
;

Dieses SQL-Skript kann auf die gleiche Weise installiert werden wie das vorherige, (das zum Erstellen der Tabellen verwendet wurde)

Share: X/Twitter LinkedIn

Erhalte neue Beiträge in deinem Posteingang.

Kein Spam. Jederzeit abmelden.