Installare un server FTP con utenti virtuali su MySQL

Da Guide@Debianizzati.Org.

Debian-swirl.png Versioni Compatibili
Debian 8 "Jessie"
Verificala con Stretch

Indice

Introduzione

Dopo aver installato Apache (Installare un ambiente LAMP: Linux, Apache2, SSL, MySQL, PHP5) e configurato i Virtual Host (Apache e Virtual Hosts: configurare Apache2 per ospitare più siti web) abbiamo adesso bisogno di permettere ai proprietari dei domini ospitati sui Virtual Host di accedere al loro spazio web via FTP senza causare danni agli altri Virtual Host e senza avere la possibilità di gironzolare per il nostro server.
Supponiamo quindi di avere una situazione del genere:

e di voler creare due utenti virtuali, senza accesso alla console:

che possano accedere via FTP solo alle directory del loro sito web.

Installazione di ProFTPD

La scelta sul server FTP da utilizzare è caduta su ProFTPD, che ora dobbiamo configurare in modo opportuno per avere due utenti distinti che gestiscano i due siti. Per fare ciò creeremo due siti FTP virtuali, con l’ausilio di un database dedicato su MySQL.
Installiamo innanzitutto ProFTPD con il supporto per MySQL:

# apt-get install proftpd-basic proftpd-mod-mysql

Per aumentare il tempo massimo prima che una connessione FTP vada in timeout per mancanza di attività possiamo aprire il file di configurazione:

# vi /etc/proftpd/proftpd.conf

e aumentare il valore della direttiva:

TimeoutNoTransfer 1200

Consiglio inoltre di aggiungere le seguenti direttive:

#Abilita resume per upload
AllowStoreRestart on
DeleteAbortedStores off

#Abilita resume per il download
AllowRetrieveRestart on

Ora creiamo un utente e un gruppo di sistema, che useremo per mappare tutti gli utenti virtuali che saranno utilizzati da ProFTPD:

# groupadd -g 2001 ftpgroup
# useradd -u 2001 -s /bin/false -d /bin/null -c "Utente ProFTPD" -g ftpgroup ftpuser

Sostituite ovviamente i numeri UID e GID con due valori che siano liberi sul vostro server.
Ora dobbiamo creare il database per ProFTPD, entrando in MySQL col comando:

$ mysql -u root -p

Creeremo un database chiamato proftpd e un utente MySQL chiamato proftpd, che sarà in seguito utilizzato da ProFTPD per connettersi al database server:

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;

Ovviamente sostituite la stringa password con la password che volete assegnare al vostro utente MySQL.

Già che siamo collegati alla shell di MySQL ne approfittiamo per creare anche tutte le tabelle che ci servono:

USE proftpd;

CREATE TABLE ftpgroup (
groupname varchar(16) NOT NULL default '',
gid smallint(6) NOT NULL default '2001',
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 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'
) 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 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'
) 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 '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 '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;

A questo punto dovremmo essere ritornati alla shell del nostro server.

Configurazione di ProFTPD

La configurazione di ProFTPD per utilizzare MySQL come backend comporta la modifica di alcuni file:

/etc/proftpd/modules.conf

Apriamo il file:

# vi /etc/proftpd/modules.conf

e abilitiamo i moduli seguenti:

[...]
# Install proftpd-mod-mysql or proftpd-mod-pgsql to use this
LoadModule mod_sql.c
[...]
# Install proftpd-mod-mysql to use this
LoadModule mod_sql_mysql.c
[...]
# Install proftpd-mod-pgsql or proftpd-mod-mysql to use this
LoadModule mod_quotatab_sql.c
[...]

/etc/proftpd/proftpd.conf

Apriamo il file:

# vi /etc/proftpd/proftpd.conf

decommentiamo la linea Include /etc/proftpd/sql.conf:

[...]
#<IfModule mod_quotatab.c>
#QuotaEngine off
#</IfModule>
[...]
#
# Alternative authentication frameworks
#
#Include /etc/proftpd/ldap.conf
Include /etc/proftpd/sql.conf
[...]

e cambiamo la linea:

AuthOrder                       mod_auth_pam.c mod_auth_unix.c

in:


#AuthOrder                      mod_auth_pam.c mod_auth_unix.c
AuthOrder                       mod_sql.c

/etc/proftpd/sql.conf

Di questo file, in particolare, notiamo la riga SQLConnectInfo (in cui vanno inseriti i parametri di connessione al database)che, se utilizziamo un database MySQL configurato come descritto in precedenza, va scritta così:

SQLConnectInfo proftpd@localhost proftpd password

Apriamo quindi il file:

# vi /etc/proftpd/sql.conf

e modifichiamolo come segue:

#
# Proftpd sample configuration for SQL-based authentication.
#
# (This is not to be used if you prefer a PAM-based SQL authentication)
#

<IfModule mod_sql.c>
#
# Choose a SQL backend among MySQL or PostgreSQL.
# Both modules are loaded in default configuration, so you have to specify the backend
# or comment out the unused module in /etc/proftpd/modules.conf.
# Use 'mysql' or 'postgres' as possible values.
#
#SQLBackend        mysql
#
#SQLEngine on
#SQLAuthenticate on
#
# Use both a crypted or plaintext password
#SQLAuthTypes Crypt Plaintext
#
# Use a backend-crypted or a crypted password
#SQLAuthTypes Backend Crypt
#
# Connection
#SQLConnectInfo proftpd@sql.example.com proftpd_user proftpd_password
#
# Describes both users/groups tables
#
#SQLUserInfo users userid passwd uid gid homedir shell
#SQLGroupInfo groups groupname gid members
#
DefaultRoot ~

SQLBackend              mysql
# The passwords in MySQL are encrypted using CRYPT
#SQLAuthTypes            Plaintext Crypt
SQLAuthTypes            Crypt Plaintext
SQLAuthenticate         users groups


# used to connect to the database
# databasename@host database_user user_password
#SQLConnectInfo  ftp@localhost proftpd 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

</IfModule>

Controllate di aver inserito la corretta password di connessione a MySQL e riavviate il servizio FTP:

# /etc/init.d/proftpd restart

Creazione degli utenti FTP

Giunti fino a qui, dobbiamo ora inserire gli utenti virtuali FTP nel database MySQL.
Nell’inserimento vero e proprio degli utenti nel database proftpd in MySQL, dobbiamo prestare attenzione ad indicare la home directory su cui verrà rimbalzato l’utente che si autentica su ProFTPD; in particolare, facendo riferimento all’articolo riguardante l’hosting virtuale con Apache, creeremo:

Per popolare il database abbiamo due strade.

1) shell mysql>

Colleghiamoci alla shell di MySQL:

mysql -u root -p

e impartiamo le seguenti istruzioni:

USE proftpd;

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

INSERT INTO ftpuser (userid, passwd, uid, gid, homedir, shell, count, accessed, modified) VALUES 
(’esempio-it’, ENCRYPT(’passwordit’), 2001, 2001, ‘/var/www/www.esempio.it’, ‘/sbin/nologin’, 0, ”, ”);

INSERT INTO ftpuser (userid, passwd, uid, gid, homedir, shell, count, accessed, modified) VALUES 
(’esempio-org’, ENCRYPT(’passwordorg’), 2001, 2001, ‘/var/www/www.esempio.org’, ‘/sbin/nologin’, 0, ”, ”);

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

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

quit;

Si noti che insieme agli utenti sono state create due regole per lo spazio su disco, con una quota impostata a 15MB.
Da notare che per inserire la password è stata usata la funzione di MySQL ENCRYPT, che utilizza la chiamata di sistema crypt() presente sul sistema operativo, quindi di fatto utilizza lo stesso metodo di cifratura utilizzato da Linux per cifrare le password degli utenti di sistema.

2) phpMyAdmin

In alternativa alla linea di comando, possiamo creare i nostri utenti collegandoci all'interfaccia web phpMyAdmin e aprendo il database proftpd.
Una volta aperto, troveremo al suo interno alcune tabelle; quelle che ci interessano nella creazione e nella gestione degli utenti sono però solo due:

Vediamone il contenuto.

ftpuser

I campi da riempire sono i seguenti (i restanti campi sono utilizzati da ProFTPD e/o da MySQL, quindi non riempiteli!):

ftpquotalimits

I campi da riempire sono i seguenti (i restanti campi sono utilizzati da ProFTPD e/o da MySQL, quindi non riempiteli!):

Altre tabelle

La tabella ftpquotatallies è utilizzata da Proftpd per gestire le quotas e non va modificata.

Impostazione dei permessi corretti

Ora rimangono da impostare i permessi sulle directory dei due siti web, per far sì che gli utenti FTP possano scrivere al loro interno, dando l’autorizzazione in scrittura all’utente ftpuser creato in precedenza:

# chown -R ftpuser:www-data /var/www/www.esempio.it
# chown -R ftpuser:www-data /var/www/www.esempio.org
# chmod -R 775 /var/www/www.esempio.it
# chmod -R 775 /var/www/www.esempio.org

Test di connessione

Aprite il vostro client FTP preferito e connettetevi al vostro server utilizzando le credenziali seguenti:

Provate a caricare un file e controllate eventuali messaggi di errore.

Una volta completato l'upload, fate login come root sulla console del server e spostatevi nella DocumentRoot del sito www.esempio.it:

# cd /var/www/www.esempio.it
# ls -la

Dovreste trovare listato anche il file che avete appena caricato.

FTP anonimo

È possibile creare anche un account ftp anonimo, cioè un account ftp che chiunque possa usare senza una password, in questo modo.
Creiamo innanzitutto un utente, un gruppo di sistema e una home directory:

# mkdir /var/www/anonymous_ftp
# groupadd -g 2002 anonymous_ftp
# useradd -u 2002 -s /bin/false -d /var/www/anonymous_ftp -m -c "Anonymous FTP User" -g anonymous_ftp anonymous_ftp

Poi creiamo la directory /home/anonymous_ftp/incoming dove gli utenti anonimi potranno caricare i file:

# mkdir /var/www/anonymous_ftp/incoming
# chown anonymous_ftp:nogroup /var/www/anonymous_ftp/incoming

Infine apriamo il file di configurazione /etc/proftpd/proftpd.conf e aggiungiamo le direttive:

# vi /etc/proftpd/proftpd.conf
[...]
<Anonymous /var/www/anonymous_ftp>
  User                                anonymous_ftp
  Group                               nogroup
  # 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
  DisplayChdir                        .message

  # Limit WRITE everywhere in the anonymous chroot
  <Directory *>
    <Limit WRITE>
      DenyAll
    </Limit>
  </Directory>

  # Uncomment this if you're brave.
  <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>

Riavviamo il servizio:

# /etc/init.d/proftpd restart

e verifichiamo che gli utenti anonimi possano ora effettuare il login.
L'impostazione data prevede che gli utenti anonimi possano:

Una volta che un file è stato caricato, nessuno può leggerlo o scaricarlo prima che un amministratore lo sposti nella directory /var/www/anonymous_ftp per renderlo disponibile a tutti.

Configurazione del Firewall

Se il server FTP è protetto da un firewall iptables occorre abilitare la direttiva PassivePorts:

# nano /etc/proftpd/proftdp.conf

in questo modo:

PassivePorts 60000 65000

In questo modo abbiamo istruito ProFTPD a utilizzare uno specifico range di porte dinamiche per le transazioni FTP. Lo stesso range va abilitato nello script del nostro firewall:

-A INPUT -m state --state NEW -m tcp -p tcp --dport 60000:65000 -j ACCEPT

Un riavvio del demone FTP e dello script del firewall completerà l'opera.




Guida scritta da: Ferdybassi 19:40, 8 nov 2010 (CET)

Swirl-auth40.png Debianized 40%

Estesa da:
Verificata da:
lula 19:00, 29 dec 2016 (CEST)

Verificare ed estendere la guida | Cos'è una guida Debianized

Strumenti personali
Namespace
Varianti
Azioni
Navigazione
Risorse
Strumenti