Index

The following document is originally based on Dovecot, Postfix with PAM authentication page written by J.W. Janssen. This Italian translation is written and maintained by Alfredo Amontagna. All copyrights on the mentioned documents belong to their rightful owners.

Introduzione

In questo documento descriverò le modalità per far autenticare Dovecot e Postfix via PAM e PostgreSQL. Questa pagina si basa sui contenuti del wiki di Dovecot e di L'Xtreme. Ho deciso di scriverlo in quanto ho dovuto modificare la configurazione proposta nei documenti originali per meglio adattarsi alla configurazione del mio server.

Software utilizzato

Questo documento è stato scritto ed è stato testato su un PC con Debian/Linux Sarge poi aggiornato ad Etch con il seguente software installato:

Debian Sarge:

Debian Etch:

Inoltre sono stati scritti alcuni script in Bash ed in Perl per l'amministrazione del server. L'utilizzo di questi script è caldamente consigliato.

Configurazione di PostgreSQL

Dobbiamo prima di tutto permetter i client che si connettono il locale di poter accedere al database di PostgreSQL utilizzando l'autenticazione basata su password. Avendo già alcuni database attivi che accettano già connessioni con metodo ident sameuser ho modificato il file /etc/postgresql/pg_hba.conf aggiungendo la seguente riga

host    all         all         192.168.0.1       255.255.255.255   password

e modificando la segeunte riga in postgresql.conf:

client_encoding = UTF8

Creiamo il database (mail_miodominio) per immagazzinare varie informazioni su utenti e transport. Inoltre creiamo un utente (mailreader) con privilegi limitati a cui permettiamo accessi a sola lettura allle informazioni memorizzate.

[localhost]$ su - postgres
[localhost]$ createdb -E UTF8 mail_miodominio
[localhost]$ createuser -A -D -P -E mailreader
[localhost]$ psql mail_miodominio

Ora creiamo le diverse tabelle:

CREATE TABLE domains
(
        gid       INTEGER UNIQUE NOT NULL,
        domain    VARCHAR(128) NOT NULL,
        transport VARCHAR(64) NOT NULL DEFAULT 'virtual:',
        PRIMARY KEY ( gid )
);

La tabella domains fornisce l'elenco dei domini che sono mappati in modo numerico in group id e fornisce informazioni sul trasporto da utilizzare a Postfix.

CREATE TABLE user_accounts
(
        username  VARCHAR(12) UNIQUE NOT NULL,
        uid       INTEGER NOT NULL,
        gid       INTEGER REFERENCES domains ( gid ),
        password  VARCHAR(32),
        email     VARCHAR(128) NOT NULL,
        mailbox   VARCHAR(128) NOT NULL,
        quota     INTEGER NOT NULL DEFAULT 25,
        active    INTEGER NOT NULL DEFAULT 1,
        PRIMARY KEY ( uid, gid )
);

Nella tabella user_account vengono memorizzate le informazioni sugli utenti. In questo modo si permette di raggruppare in modo simile agli utenti UNIX "convenzionali". I uids/gids utilizzati devono rispecchiare le proprietà delle directory delle mailbox, altrimenti agli utenti verrà negato l'accesso alle loro mailbox. Il campo mailbox è relativo al parametro di configurazione assegnato a virtual_mailbox_base utilizzato da Postfix. Il campo password contiene la password criptata dell'utente. L'algoritmo utilizzato è (lo standard UNIX) crypt. Il campo email corrisponde all'indirizzo email dell'utente.

CREATE TABLE user_addresses
(
        username  VARCHAR(12) REFERENCES user_accounts ( username ),
        alias     VARCHAR(128) UNIQUE NOT NULL,
        PRIMARY KEY ( username, alias )
);

La tabella user_addresses contiene tutti gli indirizzi email riconosciuti dal server per gli utenti. Deve essere incluso anche l'indirizzo reale di ogni utente.

CREATE VIEW postfix_mailboxes AS
        SELECT alias AS address, mailbox||'/' AS mailbox
        FROM user_accounts RIGHT JOIN user_addresses
        ON user_accounts.username = user_addresses.username;

CREATE VIEW postfix_aliases AS
        SELECT email AS address, alias
        FROM user_accounts RIGHT JOIN user_addresses
        ON user_accounts.username = user_addresses.username;

Le viste postfix_mailboxes e postfix_aliases forniscono un semplice accesso a Postfix sulle informazioni degli utenti. Il campo mailbox è concatenato con un "/". In questo modo Postfix invierà tutte le email degli utenti in stile Maildir, utilizzato da IMAP.

Ora che le tabelle sono state create, limitiamo gli accessi ai nostri dati:

GRANT SELECT ON domains, user_accounts, user_addresses,
        postfix_mailboxes, postfix_aliases TO mailreader;

Se tutto è andato per il verso giusto, ora possiamo inserire qualche dato:

INSERT INTO domains ( gid, domain ) VALUES ( 10001, 'miodominio.it' );

INSERT INTO user_accounts ( username, uid, gid, password, email, mailbox, active )
        VALUES ( 'albertot', 10001, 10001, 'passwd-criptata', 'alfredo@miodominio.it',
                'miodominio.it/alfredo', '1' );
INSERT INTO user_accounts ( username, uid, gid, password, email, mailbox, active )
        VALUES ( 'carlol', 10002, 10001, 'altra-passwd-criptata', 'carlo@miodominio.it',
                'miodominio.it/carlo', '1' );

INSERT INTO user_addresses ( username, alias )
        VALUES ( 'albertot', 'postmaster@miodominio.it' );
INSERT INTO user_addresses ( username, alias )
        VALUES ( 'albertot', 'info@miodominio.it' );
INSERT INTO user_addresses ( username, alias )
        VALUES ( 'albertot', 'webmaster@miodominio.it' );
INSERT INTO user_addresses ( username, alias )
        VALUES ( 'albertot', 'hostmaster@miodominio.it' );
INSERT INTO user_addresses ( username, alias )
        VALUES ( 'albertot', 'alberto@linuxfan.it' );
INSERT INTO user_addresses ( username, alias )
        VALUES ( 'albertot', 'albertot@linuxfan.it' );
INSERT INTO user_addresses ( username, alias )
        VALUES ( 'albertot', 'alberto.tuonomeinventato@miodominio.it' );
INSERT INTO user_addresses ( username, alias )
        VALUES ( 'carlol', 'carlo@miodominio.it' );

Da notare che la password deve essere criptata con l'algoritmo (standard) crypt. J.W. Janssen ha scritto un semplice script in perl che chiede una password (testo in chiaro) e la restituisce in forma criptata (leggere la documentazione nel file).

Configurazione di Postfix

Postfix fornisce diverse direttive per interrogare sorgenti esterne per recuperare informazioni su come consegnare. Queste sorgenti esterne sono chiamate maps da Postfix, e possono essere raffigurate come tabelle di ricerca (consultazione).

In questo documento definiremo ed utilizzeremo le seguenti direttive:

Postfix utilizza una sintassi simile agli URI per utilizzare una sorgente esterna per una determinata mappa. Per esempio per utilizzare un database di PostgreSQL come sorgente, si utilizzerà il seguente URI: pgsql:/path/to/query_file, in cui "query_file" contiene la query di ricerca per PostgreSQL.

Inseriamo le seguenti entry nel file main.cf di Postfix:

transport_maps = pgsql:/etc/postfix/pg_transport.cf
virtual_minimum_uid = 10000
virtual_uid_maps = pgsql:/etc/postfix/pg_uids.cf
virtual_minimum_gid = 10000
virtual_gid_maps = pgsql:/etc/postfix/pg_gids.cf
virtual_alias_maps = pgsql:/etc/postfix/pg_virtual.cf
virtual_mailbox_domains = pgsql:/etc/postfix/pg_transport.cf
virtual_mailbox_base = /var/mail
virtual_mailbox_maps = pgsql:/etc/postfix/pg_mailboxes.cf
virtual_mailbox_limit = 51200000
mydestination = $myhostname

In questo estratto possiamo vedere che PostgreSQL è utilizzato in maniera estensiva pe la ricerca di qualsiasi tipo di informazione. Inoltre vediamo che tutte le mailbox sono memorizzate in /var/mail con un limite massimo e impostato a circa 50 megabyte. Ci sono le direttive che indicano a Postix che i uid ed i gid partono da 10000 in su.

Senza entrare nello specifico (i dettagli sono qui), ecco i file utilizzati:

Sintassi specifica per Debian Sarge

pg_transport.cf

# domain transport information
hosts = 192.168.0.1
user = mailreader
password = secret
dbname = mail_miodominio
table = domains
select_field = transport
where_field = domain

pg_uids.cf

# user id information
hosts = 192.168.0.1
user = mailreader
password = secret
dbname = mail_miodominio
table = user_accounts
select_field = uid
where_field = email

pg_gids.cf

# group id information
hosts = 192.168.0.1
user = mailreader
password = secret
dbname = mail_miodominio
table = user_accounts
select_field = gid
where_field = email

pg_virtual.cf

# email address (real+virtual) information
hosts = 192.168.0.1
user = mailreader
password = secret
dbname = mail_miodominio
table = postfix_aliases
select_field = address
where_field = alias

pg_mailboxes.cf

# user information
hosts = 192.168.0.1
user = mailreader
password = secret
dbname = mail_miodominio
table = postfix_mailboxes
select_field = mailbox
where_field = address

Sintassi specifica per Debian Etch

pg_transport.cf

# domain transport information
hosts = 192.168.0.1
user = mailreader
password = secret
dbname = mail_miodominio
query = SELECT transport FROM domains WHERE domain='%s'

pg_uids.cf

# user id information
hosts = 192.168.0.1
user = mailreader
password = secret
dbname = mail_miodominio
query = SELECT uid FROM user_accounts WHERE email='%s'

pg_gids.cf

# group id information
hosts = 192.168.0.1
user = mailreader
password = secret
dbname = mail_miodominio
query = SELECT gid FROM user_accounts WHERE email='%s'

pg_virtual.cf

# email address (real+virtual) information
hosts = 192.168.0.1
user = mailreader
password = secret
dbname = mail_miodominio
query = SELECT address FROM postfix_aliases WHERE alias='%s'

pg_mailboxes.cf

# user information
hosts = 192.168.0.1
user = mailreader
password = secret
dbname = mail_miodominio
query = SELECT mailbox FROM postfix_mailboxes WHERE address='%s'

Directory e owner dello spool

Ora accertiamoci che la directory virtual_mailbox_base esista e che abbia i permessi corretti. Dovrebbe essere leggibile scrivibile e browseable da Postfix. Qualsiasi dominio virtuale posizionato all'interno di virtual_mailbox_base dovrebbe essere di proprietò dell'utente di postfix ed avere i corretti gid numerici. Gli utenti virtuali dovrebbero avere i corretti uid e gid. Ecco un esempio di permessi corretti:

[localhost]$ ls -al /var/mail/miodominio.it/
drwxr-sr-x    5 mail     mail         4096 Jun 19 02:59 .
drwxrwsr-x    3 root     mail         4096 Jun 19 18:25 ..
drwxr-sr-x    6 10001    10001        4096 Jun 19 16:24 alberto
drwxr-sr-x    2 10002    10001        4096 Jun 19 02:59 carlo

Configurazione di Dovecot

Le impostazioni di default di Dovecot sono perfettamente ragionevoli, per cui modificheremo solo le variabili indicate di seguito.

Sintassi specifica per Debian Sarge

/etc/dovecot/dovecot.conf

default_mail_env = maildir:/var/mail/%d/%n
auth_userdb = pgsql /etc/dovecot-pgsql.conf
auth_passdb = pgsql /etc/dovecot-pgsql.conf
# Tell Dovecot more about the used uids/gids.
first_valid_uid = 10000
last_valid_uid = 60000
first_valid_gid = 10000
last_valid_gid = 60000

In questo modo abbiamo comunicato a Dovecot dove trovare le mailbox degli utenti ed il metodo per verificare gli utenti e le loro password utilizzando il seguente file /etc/dovecot/dovecot-pgsql.conf:

# Dovecot queries
connect = host=192.168.0.1 dbname=mail_miodominio user=mailreader password=secret
default_pass_scheme = CRYPT
password_query = SELECT password FROM user_accounts WHERE username='%u'
user_query = SELECT '/var/mail/'||mailbox AS mail, uid, gid FROM
        user_accounts WHERE username='%u'

Sintassi specifica per Debian Etch

/etc/dovecot/dovecot.conf

mail_location = maildir:/var/mail/%d/%n
first_valid_gid = 10000
last_valid_gid = 60000

  #passdb pam {
  #}

  passdb sql {
    args = /etc/dovecot/dovecot-sql.conf
  }

  #userdb passwd {
  #}

  userdb sql {
    # Path for SQL configuration file, see /etc/dovecot/dovecot-sql.conf for example
    args = /etc/dovecot/dovecot-sql.conf
  }

In questo modo abbiamo comunicato a Dovecot dove trovare le mailbox degli utenti ed il metodo per verificare gli utenti e le loro password utilizzando il seguente file /etc/dovecot/dovecot-sql.conf:

driver = pgsql
connect = host=192.168.0.1 dbname=mail_miodominio user=mailreader password=secret
default_pass_scheme = CRYPT
password_query = SELECT password FROM user_accounts WHERE username='%u'
user_query = SELECT '/var/mail/'||mailbox AS mail, uid, gid FROM user_accounts WHERE username='%u'

Primo test: consegna della posta ed accesso

Sia Postfix che Dovecot possono essere riavviati per poter testare la configurazione. Spiegazioni dettaglate su come effettuare i test sono al di fuori dello scopo di questo documento. Comunque controllate il seguente elenco (potrebbe essere incompleto):

Se tutti i test vengono passati, possiamo procedere alla fase successiva: permettere il relay agli utenti in hosting ed aumentare la sicurezza.

Alcuni degli errori ricorrenti:

Permettere il relay agli utenti in hosting

Nella maggior parte dei casi non si vuole che Postfix si comporti come "open relay". Comunque vogliamo permettere agli utenti in hosting di inviare email attraverso il nostro server utilizzando il loro mailreader preferito da casa. Dobbiamo mettere al corrente Postfix su chi può e chi non può inviare email attraverso il server. Postfix di default permette l'invio di email solo alle macchine presenti nella rete locale, come impostato da mynetworks in main.cf.

La soluzione al problema è di utilizzare l'autenticazione SMTP descritta in RFC 2554. Utilizzando questo metodo di autenticazione, poi restringiamo l'accesso al nostro server SMTP a tutti coloro che hanno un account.

Abilitazione del supporto SASL di Postfix

Postfix usa SASL (RFC 2222, implementazione SASL2 di Cyrus) per fornire l'autenticazione SMTP ai suoi client.

Per abilitare l'autenticazione SMTP utilizzando SASL, dobbiamo inserire le seguenti entry in main.cf.

# Enable SMTP authentication support
smtp_sasl_auth_enable = no
smtpd_sasl_auth_enable = yes
smtpd_sasl_security_options = noanonymous
smtpd_sasl_local_domain = $mydomain
unknown_local_recipient_reject_code = 450
smtpd_recipient_restrictions =
        permit_mynetworks,
        permit_sasl_authenticated,
        reject_unauth_destination

In parole semplici abbiamo detto a Postfix di richiedere l'autenticazione SMTP non anonima per qualsiasi destinatario non conosciuto in locale. Email da parte di client non autorizzati verso destinatari non conosciuti in locale saranno respinte.

Configurazione di SASL2

Il daemon SASL per l'autenticazione (saslauthd) utilizza gli socket UNIX per comunicare con altri programmi. Siccome Postfix viene eseguito in ambiente chroot'ed, abbiamo bisogno di essere certi che il daemon SASL e Postfix siano in grado di comunicare tra loro. In altre parole dobbiamo forzare SASL a creare uno socket UNIX in un punto all'interno dell'ambiente chroot'ed. Per fare ciò dobbiamo creare (o modificare) il file di configurazione di saslauthd /etc/default/saslauthd:

Sintassi specifica per Debian Sarge

START=yes
MECHANISMS=pam
PARAMS="-m /var/spool/postfix/etc"

Sintassi specifica per Debian Etch

START=yes
MECHANISMS=pam
MECH_OPTIONS=""
THREADS=10
PARAMS="-c -m /var/spool/postfix/etc"

Inoltre dobbiamo dire al layer SASL di Postfix che può comunicare col daemon saslauthd via socket UNIX. Notate che il parametro saslauthd_path è relativo alla directory chroot! Creiamo il file /etc/postfix/sasl/smtpd.conf:

pwcheck_method: saslauthd
saslauthd_path: /etc/mux
mech_list: login plain

L'ultima opzione restringe i meccanismi di autenticazione a login o plain.

Configurazione di PAM

Debian utilizza in modo estensivo PAM per tutti i generi di autenticazione. In /etc/default/saslauthd noi impostiamo SASL ad utilizzare PAM come meccanismo di autenticazione. Quindi visto che tutte le password degli utenti sono immagazzinate in un database di PostgreSQL, dobbiamo abilitare PAM per effettuare lì le ricerche. Il modulo pam_pgsql è configurato in /etc/pam_pgsql.conf:

database = mail_miodominio
host = 192.168.0.1
user = mailreader
password = secret
table = user_accounts
user_column = username
pwd_column = password
pw_type = crypt

Questo semplice file di configurazione dice al modulo pam_pgsql di utilizzare la tabella user_accounts del database mail_miodominio. In questa tabella controllerà lo user name e la password corrispondenti alle colonne username e password.

PAM deve inoltre comunicare quali programmi devono utilizzare quel metodo di autenticazione. Questo avviene creando il file /etc/pam.d/smtp:

auth        required    pam_pgsql.so
account     required    pam_pgsql.so
password    required    pam_pgsql.so

Provare l' autenticazione

Ora dovremo essere in grado di verificare se l'autenticazione SMTP funziona correttamente. Per prima cosa dobbiamo riavviare i daemon saslauthd e postfix:

/etc/init.d/saslauthd restart
/etc/init.d/postfix restart

Controllate i processi ed i file di log per verificare che i daemon funzionino correttamente.

Se tutto e in ordine, l'invio di email senza autenticazione dovrebbe fallire. Effettuate la prova su una macchina che non è riconosciuta da Postfix, per esempio non elencata in mynetworks.

Ora modificate la configurazione del mailreader per utilizzare l' autenticazione SMTP (SMTP AUTH) per l'invio dei email attraverso il vostro server. Nuovamente provate ad inviare una email attraverso il vostro server. Questa volta dovrebbe aver successo. Altrimenti controllate /var/log/auth.log e /var/log/mail.log per capire dove sia il problema.

Rendere più stretta la configurazione di Postfix

A questo punto dovreste avere una configurazione di Postfix funzionante, in grado di autenticare gli utenti autorizzati e di prevenire il relay da parte degli spammer. Ora possiamo restringere gli accessi ed aumentare la sicurezza del mail server. Quello che vogliamo fare è rendere difficoltoso per gli spammer utilizzare il nostro sistema come relay e di restringere gli accessi da parte di host blacklistati. Modificate il file /etc/postfix/main.cf come segue (ma solo se avete una configurazione corretta di Postfix. Evitate di esffettuare le seguenti modifiche mentre effettuate il debugging della configurazione):

disable_vrfy_command = yes
smtpd_helo_required = yes
smtpd_recipient_restrictions =
        permit_mynetworks,
        permit_sasl_authenticated,
        reject_unauth_pipelining,
        reject_unknown_recipient_domain,
        reject_non_fqdn_sender,
        reject_non_fqdn_recipient,
        reject_unauth_destination
        reject_unknown_sender_domain
smtpd_client_restrictions =
        permit_mynetworks,
        reject_rbl_client relays.ordb.org,
        reject_rbl_client ipwhois.rfc-ignorant.org,
        permit_sasl_authenticated
smtpd_sender_restrictions =
        permit_mynetworks,
        reject_rhsbl_sender dsn.rfc-ignorant.org,
        permit_sasl_authenticated,
        reject_sender_login_mismatch
# Setup a spam tarpit...
smtpd_error_sleep_time = 60
smtpd_soft_error_limit = 60
smtpd_hard_error_limit = 10
default_process_limit = 3

Monitoraggio e manutenzione di Postfix

La maggior parte del tempo, la coda del vostro mail server si svuoterà dopo aver iviato l'email. Potrebbe anche accadere che delle email restino a lungo nella coda, per esempio a causa del fatto che il destinatario non esiste. Se l'indirizzo email del mittente esiste, questo problema si risolverà da solo nel momento in qui Postfix invierà un messaggio di errore al mittente. Viceversa se l'indirizzo del mittente non esiste, Postfix non sarà in grado di inviare un messaggio di errore e manterrà l'email nella coda per un tempo indefinito. La presenza di molte email "deferred" possono fare degradare le performance del server. Dobbiamo quindi rimuoverle utilizzando il seguente cronjob:

mailq | grep MAILER-DAEMON | awk '{printf $1} {print " deferred"}' | \
        tr -d '*!' | xargs -n 2 postsuper -d >/dev/null 2>&1

C'è la remota possibilità che il precedente script cancelli una email errata a causa del riutilizzo dell'ID delle coda di postfix. Questa possibilità è remota e necessitò di un carico veramente elevato di email per poter far si che accada.

Se state seguendo questo howto per configurare il vostro mailserver, potete ricavare alcuve statistiche interessanti con questo ottimo script di Jim Seymour.

J.W. Janssen ha scritto questo script wrapper che invia una email con l'output di pflogsummary all'utente postmaster del server. Deve essere eseguito in un cron-job ogni notte:

PATH=/bin:/usr/bin:/usr/local/sbin
LOG_FILE=/var/log/mail.log.0*
PFLOGSUMM=/usr/local/sbin/pflogsummary.pl
$PFLOGSUMM -d yesterday --problems_first `ls -rt $LOG_FILE*` | \
        mail -s "Postfix :: report" postmaster

ItCompOsLinuxIniziare: PostfixSaslDovecotPostgresql (last edited 2009-02-11 20:06:13 by )