Installazione di ProFtpd in Debian con gestione Virtual Users in MySQL

From RVM Wiki
Jump to navigation Jump to search

Introduzione

Supponiamo quindi di avere una situazione del genere:

  • /var/www/esempio.it/www

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

  • esempio_it

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 login FTP virtuali, con l’ausilio di un database dedicato su MySQL.

  • Installiamo innanzitutto ProFTPD con il supporto per MySQL:
sudo 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 e aumentare il valore della direttiva TimeoutNoTransfer:
sed -i -e 's/TimeoutNoTransfer.*600/TimeoutNoTransfer 1200/'  /etc/proftpd/proftpd.conf
  • Consiglio inoltre di aggiungere le seguenti direttive:
echo "AllowStoreRestart on" >> /etc/proftpd/proftpd.conf
echo "DeleteAbortedStores off" >> /etc/proftpd/proftpd.conf
echo "AllowRetrieveRestart on" >> /etc/proftpd/proftpd.conf


  • 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)
) 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'
);

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'
);

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)
) COMMENT='ProFTP user table';

quit;


Configurazione di ProFTPD

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

/etc/proftpd/modules.conf

Abilitiamo i moduli seguenti:

sed -i -e 's/#LoadModule mod_sql.c/LoadModule mod_sql.c/'  /etc/proftpd/modules.conf 
sed -i -e 's/#LoadModule mod_sql_mysql.c/LoadModule mod_sql_mysql.c/'  /etc/proftpd/modules.conf 
sed -i -e 's/#LoadModule mod_quotatab_sql.c/LoadModule mod_quotatab_sql.c/'  /etc/proftpd/modules.conf


/etc/proftpd/proftpd.conf

  • Decommentiamo la linea Include /etc/proftpd/sql.conf:
sed -i -e 's_#Include /etc/proftpd/sql.conf_Include /etc/proftpd/sql.conf_'  /etc/proftpd/proftpd.conf
  • Cambiamo la linea:
 sed -i -e 's/^# AuthOrder.*/AuthOrder mod_sql.c/'  /etc/proftpd/proftpd.conf 

/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ì:
  • CAMBIARE LA PASSWORD:
cat <<EOFile > /etc/proftpd/sql.conf
#
# 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@localhost proftpd password
#
# Describes both users/groups tables
#
#SQLUserInfo users userid passwd uid gid homedir shell
#SQLGroupInfo groups groupname gid members
#
#
#</IfModule>

<IfModule mod_sql.c>
DefaultRoot ~

SQLBackend              mysql
SQLAuthTypes            Crypt Plaintext
SQLAuthenticate         users groups
SQLConnectInfo proftpd@localhost proftpd password
SQLUserInfo     ftpuser userid passwd uid gid homedir shell
SQLGroupInfo    ftpgroup groupname gid members
SQLMinID        100
CreateHome on
SQLLog PASS updatecount
SQLNamedQuery updatecount UPDATE "count=count+1, accessed=now() WHERE userid='%u'" ftpuser
SQLLog  STOR,DELE modified
SQLNamedQuery modified UPDATE "modified=now() WHERE userid='%u'" ftpuser

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>
EOFile

  • Controllate che SQLMinID sia superiore all'id dello user FTP
  • 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. Creeremo:

  • un gruppo chiamato ftp;
  • un utente chiamato example_com con password passwordcom e home directory /var/www/example.com/www;
  • un utente chiamato example_it con password passwordit e home directory /var/www/example.it/www.
  • Verifica l'id del gruppo ftp:
id ftp
uid=110(ftp) gid=118(ftp) groups=118(ftp)
  • Verifica id users:
id www-exacom 
uid=999(www-exacom) gid=999(www-exacom) groups=999(www-exacom)
id www-exait
uid=998(www-exait) gid=998(www-exait) groups=998(www-exait)

Dobbiamo creare questi userid

username     uid gid
example_com  110 999
example_it   110 998

Perchè i files dovranno avere permission

filename ftp example_com
filename ftp example_it
  • Colleghiamoci alla shell di MySQL:
mysql -u root -p
  • impartiamo le seguenti istruzioni:
USE proftpd;

INSERT INTO `ftpgroup` (`groupname`, `gid`, `members`) VALUES ('example_com', 999, 'example_com');
INSERT INTO `ftpgroup` (`groupname`, `gid`, `members`) VALUES ('example_it',  998, 'example_it');

INSERT INTO ftpuser (userid, passwd, uid, gid, homedir, shell, count, accessed, modified) VALUES 
('example_com', ENCRYPT('passwordcom'), 110, 999, '/var/www/example.com/www', '/sbin/nologin', 0, '', '');

INSERT INTO ftpuser (userid, passwd, uid, gid, homedir, shell, count, accessed, modified) VALUES 
('example_it', ENCRYPT('passwordit'), 110, 999, '/var/www/example.it/www', '/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 NON 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.

Descrizione campi

  • Le tabelle; quelle che ci interessano nella creazione e nella gestione degli utenti sono però solo due:
  • ftpquotalimits
  • ftpuser

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!):

  • userid: il nome dell'utente FTP virtuale (es: esempio-it)
  • passwd: la password dell'utente
  • uid: il valore userid dell'utente di sistema ftp creato in precedenza (2001)
  • gid: il valore groupid dell'utente di sistema ftp creato in precedenza (2001)
  • homedir: il percorso della home directory dell'utente FTP virtuale (/var/www/www.esempio.it). Se non esiste sarà creata al momento della connessione. L'utente virtuale sarà chrooted in questa directory e non potrà uscirne
  • shell: la shell di sistema assegnata all'utente. Dato che non vogliamo permettere accesso al server, lasciamo il valore di default

ftpquotalimits

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

  • name: il nome dell'utente FTP virtuale (es: esempio-it)
  • quota_type: user o group. Normalmente useremo user
  • per_session: true o false. true significa che la quota limite è valida per una singola sessione: se l'utente effettua un logout e un nuovo login la quota si azzera. false significa che l'utente ha a disposizione la quota stabilita
  • limit_type: hard o soft. Un hard quota limit non permette eccezioni, mentre un soft quota limit può temporaneamente essere superato. Normalmente viene usato hard
  • bytes_in_avail: limite di upload in bytes. 0 significa senza limite
  • bytes_out_avail: limite di download in bytes. 0 significa senza limite
  • bytes_xfer_avail: limite di transfer bytes. È la quantità massima di bytes che un utente può uploadare o downloadare. 0 significa senza limite
  • files_in_avail: numero limite di file uploadabili. 0 significa senza limite
  • files_out_avail: numero limite di file scaricabili. 0 significa senza limite
  • files_xfer_avail: numero limite di file trasferibili. 0 significa senza limite

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:

  • Host: ftp.esempio.it
  • Utente: esempio-it
  • Password: passwordit
  • Porta: 21

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:

  • scaricare i file messi in /var/www/anonymous_ftp
  • caricare i file nella directory /var/www/anonymous_ftp/incoming

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.

Riferimenti