Postfix nirvana – Parte II

Ecco la seconda parte della guida al buon server mail. Come preannunciato nella prima parte, qui parleremo dei programmi accessori che permettono di creare facilmente mailbox virtuali e di rendere la posta (e non solo) disponibile all’utente tramite una interfaccia web avanzata. Voglio anche qui ringraziare Manuel per il decisivo contributo alla realizzazione della guida.

Sommario

Postfixadmin

È giunto il momento di installare Postfixadmin, che permette di gestire domini virtuali, mailboxes e alias tramite una interfaccia web costruita in PHP. Postifxadmin è pacchettizzato in Debian Etch, quindi l’installazione dei file avviene con un semplice “apt-get install postfixadmin“.

L’operazione successiva è la creazione del database e dell’utente amministratore. È possibile farlo semplicemente con phpMyAdmin, oppure direttamente tramite il prompt di MySQL con i comandi:

CREATE DATABASE postfix;
CREATE USER 'postfix'@'localhost' IDENTIFIED BY 'choose_a_password';
GRANT ALL PRIVILEGES ON `postfix` . * TO 'postfix'@'localhost';

sostituendo gli opportuni valori, ed inserendo poi gli stessi valori nel file di configurazione /etc/postfixadmin/config.inc.php. Nello stesso file, oltre ai dati del database, è necessario cambiare il valore di $CONF['configured'] da false a true per poter inizializzare l’applicazione. Io preferisco avere le varie maidir degli utenti suddivise in directory separate per dominio, per cui imposto:

$CONF['domain_path'] = 'YES';

A questo punto imposto un VirtualHost sul server web che punti alla directory del programma, nel caso di Debian /usr/share/postfixadmin/, dirigo il browser su http://INDIRIZZO_DI_POSTFIXADMIN/setup.php e, dopo la creazione delle tabelle, mi appare una lista di ‘OK’ e il form per la creazione dell’utente amministratore. Lo inserisco e posso eseguire il login.

Postfixadmin offre all’utente la possibilità di impostare gli inoltri automatici dei messaggi e un autorisponditore (Vacation). Mentre il primo è già abilitato, per abilitare il secondo dobbiamo effettuare alcune modifiche.

Creo innanzitutto un utente ed un gruppo vacation, aggiungendo a /etc/passwd la riga:

vacation:*:65501:65501::0:0:Virtual Vacation:/nonexistent:/usr/sbin/nologin

ed a /etc/group la riga:

vacation:*:65501:

Quindi creo una directory di base per l’autorisponditore, vi copio il file vacation.pl, che in Debian si trova in /usr/share/doc/postfixadmin/VIRTUAL_VACATION/, e cambio i permessi di tutto:

# mkdir /var/spool/vacation
# cd /usr/share/doc/postfixadmin/VIRTUAL_VACATION/
# cp vacation.pl /var/spool/vacation/
# chown vacation:vacation -R /var/spool/vacation

Nel file vacation.pl devo inserire gli estremi del database modificando le righe:

my $db_type = 'mysql';
my $db_username = 'postfix';
my $db_password = 'password';
my $db_name     = 'postfix';

ed infine abilitare il modulo modificando nel file
/etc/postfixadmin/config.inc.php le righe:

$CONF['vacation'] = 'YES';
$CONF['vacation_domain'] = 'vacation.nomedominio';

Per far funzionare l’autorisponditore sono necessari tre moduli Perl. Due di questi li posso installare con:

apt-get install libemail-valid-perl libmail-sendmail-perl

mentre il terzo non è incluso nei repository di Debian Etch. È però possibile scaricare il pachetto dai repository di Debian Lenny (testing) ed installarlo senza incontrare problemi di dipendenze con:

# wget http://ftp.it.debian.org/debian/pool/main/libm/libmime-encwords-perl/libmime-encwords-perl_1.010.101-1_all.deb
# dpkg -i libmime-encwords-perl_1.010.101-1_all.deb

In ultimo dobbiamo definire il servizio vacation e fare in modo che i messaggi indirizzari al domino vacation.nomedominio vi siano girati. Per fare questo aggiungo al file /etc/postfix/master.cf le righe:

vacation    unix  -       n       n       -       -       pipe
  flags=Rq user=vacation argv=/var/spool/vacation/vacation.pl -f ${sender} -- ${recipient}

creo poi un file /etc/postfix/transport contenente la riga:

vacation.nomedominio        vacation:

compilo il database con:

#postmap /etc/postfix/transport

ed aggiungo a /etc/postfix/main.cf la riga:

transport_maps = hash:/etc/postfix/transport

Il tutto è ora pronto a funzionare, ma per utilizzarlo devo modificare la configurazione di Postfix.

Postfix: domini e mailbox virtuali

Per fare in modo che Postfix veda i domini virtuali creati da Postfixadmin devo aggiungere le seguenti righe in /etc/postfix/main.cf:

virtual_alias_maps = mysql:/etc/postfix/mysql_virtual_alias_maps.cf
virtual_mailbox_domains = mysql:/etc/postfix/mysql_virtual_domains_maps.cf
virtual_mailbox_maps = mysql:/etc/postfix/mysql_virtual_mailbox_maps.cf
virtual_mailbox_base = /home/mail
virtual_uid_maps = static:6000
virtual_gid_maps = static:6000

che indicano rispettivamente gli indirizzi delle mappe del database, l’indirizzo della directory dove verrannno create le mailbox virtuali, e l’utente e gruppo proprietari delle mailbox. L’utente e il gruppo devono esistere nel file /etc/passwd:

vmail:x:6000:6000::/home/mail:/bin/sh

e in /etc/group:

vmail:x:6000:

e devo creare la directory con i giusti permessi

# mkdir /home/mail
# chown vmail:vmail /home/mail

Le mappe sono file di testo composti come segue:

mysql_virtual_alias_maps.cf:

user = postfix
password = password
hosts = 127.0.0.1
dbname = postfix
table = alias
select_field = goto
where_field = address

mysql_virtual_domains_maps.cf:

user = postfix
password = password
hosts = 127.0.0.1
dbname = postfix
table = domain
select_field = description
where_field = domain

mysql_virtual_mailbox_maps.cf:

user = postfix
password = password
hosts = 127.0.0.1
dbname = postfix
table = mailbox
select_field = maildir
where_field = username

Ora sono pronto a inserire, tramite l’interfaccia di Postfixadmin, il mio primo dominio virtuale e i relativi alias e mailboxes. Dopo averlo riavviato Postfix è pronto a ricevere mail per gli account impostati. Posso testare il tutto in locale con telnet:

# telnet localhost 25
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
220 nomemacchina.nomedominio ESMTP Postfix (Debian/GNU)

ehlo nomemacchina.nomedominio
250-nomemacchina.nomedominio
250-PIPELINING
250-SIZE 10240000
250-VRFY
250-ETRN
250-STARTTLS
250-AUTH PLAIN LOGIN
250-AUTH=PLAIN LOGIN
250-ENHANCEDSTATUSCODES
250-8BITMIME
250 DSN

mail from:<jimmi@server.com>
250 2.1.0 Ok

rcpt to:<jimmi@nomedominio>
250 2.1.5 Ok

data
354 End data with <CR><LF>.<CR><LF>

prova mail
.
250 2.0.0 Ok: queued as 718BE15DF78

quit
221 2.0.0 Bye
Connection closed by foreign host.

Se tutto è a posto troverò la mail nell’Inbox dell’utente.

Dovecot

Passo ad occuparmi ora del server IMAP. Anche Dovecot è pacchettizato da Debian, e si installa con:

apt-get install dovecot-imapd dovecot-pop3d

È possibile attivare facilmente i server imap, imaps, pop3 e pop3s aggiungendo a /etc/dovecot/dovecot.conf:

protocols = imap imaps pop3 pop3s

ed eventualmente modificando le sezioni dedicate nello stesso file. Per fare in modo che Dovecot utilizzi le mailbox virtuali modifico seguenti righe di
/etc/dovecot/dovecot.conf:

mail_location = maildir:/home/mail/%d/%n
auth default {
mechanisms = plain login
passdb sql {
args = /etc/dovecot/dovecot-mysql.conf
}
userdb sql {
args = /etc/dovecot/dovecot-mysql.conf
}
user = postfix
client {
path = /var/spool/postfix/private/auth
mode = 0660
user = postfix
group = postfix
}
}

La sezione “client” serve per abilitare l’autenticazione SASL in postfix, che si attiva aggiungendo le seguenti righe in /etc/postfix/main.cf:

smtpd_sasl_auth_enable = yes
smtpd_sasl_local_domain = $myhostname
smtpd_sasl_security_options = noanonymous
broken_sasl_auth_clients = yes
smtpd_sasl_type = dovecot
smtpd_sasl_path = private/auth

Per ottenere i dati dell’utente dal database aggiungo poi il file
/etc/dovecot/dovecot-mysql.conf:

driver = mysql
password_query = SELECT password FROM mailbox WHERE username = '%u'
user_query = SELECT maildir, 6000 AS uid, 6000 AS gid FROM mailbox WHERE username = '%u'
connect = host=127.0.0.1 port=3306 dbname=postfix user=postfix password=password default_pass_scheme = CRYPT

Al riavvio di Dovecot se tutto funziona posso leggere le seguenti righe nei log:

dovecot: 2008-07-13 19:40:42 Info: Dovecot v1.0.rc15 starting up
dovecot: 2008-07-13 19:40:43 Info: auth-worker(default): mysql: Connected to 127.0.0.1 (postfix)

Dovecot LDA

Dovecot fornisce anche un programma per la consegna dei messaggi agli utenti virtuali, chiamato Dovecot Local Delivery Agent, che può sostituire virtual fornito dal Postfix, con alcune funzionalità aggiuntive, come l’indicizzazione delle mailbox, l’utilizzo di quote utente e di Sieve tramite appositi plugin. Per abilitarlo devo aggiungere al file /etc/dovecot/dovecot.conf le righe:

protocol lda {
..
  # UNIX socket path to master authentication server to find users.
  #auth_socket_path = /var/run/dovecot/auth-master
}
auth default {
..
  socket listen {
    # Note that we're setting a master socket. SMTP AUTH for Postfix uses client sockets.
    master {
      path = /var/run/dovecot/auth-master
      # Auth master socket can be used to look up userdb information for
      # given usernames. This probably isn't very sensitive information
      # for most systems, but still try to restrict the socket access if possible.
      mode = 0600
      user = vmail # User running deliver
      group = vmail # Or alternatively mode 0660 + deliver user in this group
    }
  }
..
}

Posso ora aggiungere il servizio in Postfix, aggiungendo a
/etc/postfix/master.cf:

dovecot   unix  -       n       n       -       -       pipe
    flags=DRhu user=vmail:vmail argv=/usr/lib/dovecot/deliver -d ${recipient}

e indicargli di utilizzarlo inserendo in /etc/postfix/main.cf le righe:

virtual_transport = dovecot
dovecot_destination_recipient_limit = 1

Con queste impostazioni deliver, che funziona da utente non privilegiato, genera un errore. Per evitarlo nella mailing list di Dovecot consigliano di impostare deliver a SUID con il comando:

# chmod u+s /usr/lib/dovecot/deliver

Riavvio Dovecot e Postfix, e alla prima ricezione posso trovare nei log qualcosa di simile a questo:

server postfix/pipe[23496]: 23FD715DF87: to=<utente@nomedominio>, relay=dovecot, delay=0.4, delays=0.07/0.02/0/0.31, dsn=2.0.0, status=sent (delivered via dovecot service)

Horde

Manca ora l’ultimo pezzo, l’interfaccia web per gli utenti tramite Horde, un framework con numerosi moduli in PHP. Anche questa applicazione è pacchettizzata da Debian, e l’installazione è banale se si seguono le indicazioni del Wiki.

Installo per primo il framework con:

# apt-get install horde3

abilito un VirtualHost che punti alla sua directory, aggiungendo ad esempio in /etc/apache2/sites-available/default:

Alias /horde3 /usr/share/horde3
Options FollowSymLinks
AllowOverride Limit
deny from all
allow from TUO_IP

che mi permetterà di accedere localmente, e inizializzo il database. Quest’ultima operazione può avvenire da riga di comando con:

#gunzip < /usr/share/doc/horde3/examples/scripts/sql/create.mysql.sql.gz | mysql -u MYSQL_ADMIN -p

Avendo cura di modificare in create.mysql.sql.gz i dati di accesso dell’amministratore di Horde. Fatto ciò puntando il browser su http://nomemacchina.nomedominio/horde3 compare la maschera iniziale di Horde. Per il debug di eventuali problemi posso puntare il browser su: http://nomemacchina.nomedominio/horde3/test.php

La configurazione di Horde3 avviene creando nelle directory sotto /etc/horde/horde3 i file config.php e config.php.bak con maschera dei permessi 777, configurando poi tramite intefaccia web le opzioni nella maschera in Amministrazione-->Impostazione-->Horde, salvando e riportando i permessi dei due file a 644 e 700 rispettivamente.

Per un corretto funzionamento è indispensabile impostare correttamente i parametri nelle maschere Database, Authentication e Preference System

Horde mette a disposizione, tra gli altri, i seguenti moduli:

  • IMP – Cliente Webmail
  • Ingo – Filtro per le mail
  • Turba – Gestione rubrica
  • Kronolith – Calendario
  • Nag – Gestione attività
  • Mnemo – Gestione note
  • Passwd – Gestione password
  • MIMP – Interfaccia per dispositivi mobili

Tutti questi moduli sono presenti nei repository Debian ad eccezione di MIMP, che può essere facilmente installato per Debian con le seguenti operazioni:

# wget http://ftp.horde.org/pub/mimp/mimp-h3-1.1.tar.gz
# tar -xvzf mimp-h3-1.1.tar.gz
# mv mimp-h3-1.1/config /etc/horde/mimp
# mv mimp-h3-1.1 /usr/share/horde3/mimp
# cd /usr/share/horde3/mimp
# ln -s /etc/horde/mimp config

La configurazione dei vari moduli avviene, analogalmente a quella del framework, in tre operazioni:

  • Creo nelle directory sotto /etc/horde/[nomemodulo] i file config.php e config.php.bak con maschera dei permessi 777
  • Configuro e salvo tramite intefaccia web le opzioni nella maschera in Amministrazione-->Impostazione-->[nomemodulo]
  • Cambio i permessi dei due file a 644 e 700 rispettivamente.

Ovviamente le operazioni dovranno essere ripetute per ogni modulo.

Oltre alle impostazioni più banali possono essere importanti le seguenti impostazioni per i vari moduli:

Horde

Maschera General:

Determines how we generate full URLs (for location headers and such)

Assume that we are using SSL and always generate https URLs

What port number is the webserver running on?

443

Questo mi serve perchè la mia webmail è disponibile su una connessione criptata https

Maschera Authentication:

What backend should we use for authenticating users to Horde?

Let a Horde application handle authentication

The application which is providing authentication

imp

Queste due scelte permettono di autenticarsi con le credenziali create in Postfixadmin ed effettualre il Login una sola volta anzichè dover inserire due volte i dati per leggere la posta. In questo caso è importante creare un utente amministratore e inserire il suo nome nella prima casella.

IMP

Modifico il file /etc/horde/imp4/servers.php inserendo i dati del o dei server mail. Nel file originale sono contenuti diversi esempi, ricordatevi di commentare o cancellare quelli non necessari.

Nel file /etc/horde/imp4/mime_drivers.php modifico la linea:

$mime_drivers['imp']['html']['inline'] = true;

Questo mi permette di vedere in linea le mail composte in HTML, anche se non meriterebbero 😉 È una scelta giustamente sconsigliata, ma altrimenti le mail HTML vengono formattate in modo impossibile da leggere.

Ingo

Nel file /etc/horde/ingo1/backends.php specifico quale backend utilizzare per i filtri. Le scelte possibili sono null (applica le regole su richiesta), o regole per Maildrop, Procmail o Sieve. La scelta più semplice è:

/* IMAP Example */
$backends['imap'] = array(
    'driver' => 'null',
    'preferred' => 'example.com',
    'hordeauth' => true,
    'params' => array(),
    'script' => 'imap',
    'scriptparams' => array()
);

Anche in questo caso le altre scelte vanno commentate o cancellate.

Turba

Nel file /etc/horde/turba2/sources.php specifico quale backend utilizzare. Per utilizzare MySQL la configurazione tipica è:

$cfgSources['localsql'] = array(
    'title' => _("My Address Book"),
    'type' => 'sql',
    'params' => array_merge($conf['sql'], array('table' => 'turba_objects')),
    'map' => array(
        '__key' => 'object_id',
        '__owner' => 'owner_id',
        '__type' => 'object_type',
        '__members' => 'object_members',
        '__uid' => 'object_uid',
        'name' => 'object_name',
        'email' => 'object_email',
        'alias' => 'object_alias',
        'homeAddress' => 'object_homeaddress',
        'workAddress' => 'object_workaddress',
        'homePhone' => 'object_homephone',
        'workPhone' => 'object_workphone',
        'cellPhone' => 'object_cellphone',
        'fax' => 'object_fax',
        'title' => 'object_title',
        'company' => 'object_company',
        'notes' => 'object_notes',
        'pgpPublicKey' => 'object_pgppublickey',
        'smimePublicKey' => 'object_smimepublickey',
        'freebusyUrl' => 'object_freebusyurl'
    ),
    'search' => array(
        'alias',
        'email'
    ),
    'strict' => array(
        'object_id',
        'owner_id',
        'object_type',
    ),
    'export' => true,
    'browse' => true,
    'use_shares' => true,
);

ed è inoltre necessario creare la tabella in MySQL, utilizzando il comando:

# mysql -u MYSQL_ADMIN -p DATABASE < /usr/share/doc/turba2/examples/scripts/sql/turba_objects.mysql.sql

Kronolith

Se si sceglie il driver SQL è necessario creare la tabella con il comando:

# mysql -u MYSQL_ADMIN -p DATABASE < /usr/share/doc/kronolith2/examples/scripts/sql/kronolith.mysql.sql

Nag

Se si sceglie il driver SQL è necessario creare la tabella con il comando:

# mysql -u MYSQL_ADMIN -p DATABASE < /usr/share/doc/nag2/examples/scripts/sql/nag.sql

Passwd
Nel file /etc/horde/passwd3/backends.php ho modificato le linee:

driver' => 'sql',
'params' => array(
'phptype'    => 'mysql',
'hostspec' => '127.0.0.1',
'port' => '3306',
'protocol' => 'tcp',
'username'   => 'postfix',
'password'   => 'password',
'encryption' => 'crypt-md5',
'database'   => 'postfix',
'table'      => 'mailbox',
'user_col'   => 'username',
'pass_col'   => 'password',
'show_encryption' => false)

Per poter modificare la password nel database creato da Postfixadmin.

Fetchmail e Gmail server relay

Vi sono altri due add-ons non strettamente collegati alla configurazione di un server mail ma molto utili specialmente per server fatti in casa.

Fetchmail

È un ottimo programma per ritirare mail da server POP3 o IMAP e consegnarla al server locale. Sia Postfixadmin che Horde hanno dei plugin che gestiscono fetchmail in modi leggermente diversi. Con Horde l’utente inserisce i dettagli del server remoto e scarica la posta mentre è collegato, mentre con Postfixadmin in base ai dati inseriti dall’amministratore nel database vengono creati dei file ~/.fetchmailrc al volo che possono essere usati inserendo in crontab lo script fetchmail.pl.

Purtroppo entrambi hanno due limitazioni che me ne impediscono l’utilizzo: non implementano Freepops e non permettono l’uso di autenticazioni SSL. Freepops è un programmino che permette di scaricare le mail diretamente dalla webmail, aggirando la limitazione all’uso del server POP per gli abbonamenti free adottato, ad esempio, da Libero e Inwind. L’uso del protocollo SSL è indispensabile invece per scaricare mail dai server di Gmail o Autistici/Inventati.

La versione di Fetchmail pacchettizzata da Debian ci permette di avviare il programma in modalità demone con il tipico script /etc/init.t/fetchmail. Il pacchetto di Freepops purtroppo fa riferimento ad una versione troppo datata e non più funzionante, e bisogna quindi installare la versione offerta dai Backports. Una volta installati entrambi avremo il demone freepopsd in ascolto alla porta 2000 (di default), e possiamo modificare il file /etc/fetchmailrc aggiungendo le sezioni relative ai vari server. Alcuni utilizzi tipici sono:

Server POP3

poll SERVER_POP with proto pop3 auth password
user "NOMEUTENTE.REMOTO" there
with password "password"
is NOMEUTENTE.LOCALE here options fetchall

Server che richiedono Freepops

poll SERVER_POP with proto pop3 port 2000
user "NOMEUTENTE.REMOTO" there
with password "password"
is NOMEUTENTE.LOCALE here options fetchall

Server Gmail

poll SERVER_POP with proto pop3 port 995
user "NOMEUTENTE.REMOTO" there
with password "password"
is NOMEUTENTE.LOCALE here options ssl sslcertck fetchall

Gmail Server Relay

Normalmente le mail spedite da un server casalingo con IP dinamico vengono rifiutate per motivi di sicurezza, e si è quindi costretti ad usare un server che vi faccia da relay, che vi permetta cioè di spedire mail attraverso il suo servizio. Vi dovesse capitare di non avere a disposizione un relay, o di volerne utilizzare uno alternativo, potete usufruire del servizio offerto da Gmail, il quale però richiede un’autenticazione sicura via SSL. Per implementarla aggiungo o modifico le seguenti righe di /etc/postfix/main.cf:

smtpd_tls_CAfile = /etc/postfix/cacert.pem
smtpd_tls_cert_file=/etc/postfix/gmail.pem
smtpd_tls_key_file=/etc/postfix/gmail.key
smtpd_sasl_application_name = smtpd
smtp_tls_per_site = hash:/etc/postfix/smtp_tls_per_site
smtp_use_tls=yes
smtp_tls_CAfile = /etc/postfix/cacert.pem
smtp_tls_cert_file=/etc/postfix/gmail.pem
smtp_tls_key_file=/etc/postfix/gmail.key
smtp_sasl_auth_enable = yes
smtp_sasl_password_maps = hash:/etc/postfix/sasl_passwd
smtp_sasl_security_options = noanonymous
smtp_sasl_tls_security_options = noanonymous
relayhost = [smtp.gmail.com]:587

creo il file /etc/postfix/sasl_passwd, vi aggiungo le righe:

# Contents of sasl_passwd
#
[smtp.gmail.com]              NOMEUTENTE@gmail.com:PASSWORD

e lo compilo con:

# postmap /etc/postfix/sasl_passwd

Infine, se non li possiedo già, creo il mio certificato auto firmato con i seguenti passaggi:

# /usr/local/ssl/misc/CA.pl -newca
  CA certificate filename (or enter to create)
   Making CA certificate ...
  Generating a 1024 bit RSA private key
  .......++++++
  ...................++++++
  writing new private key to './demoCA/private/cakey.pem'
  Enter PEM pass phrase: password
  Verifying - Enter PEM pass phrase: password
  -----
  You are about to be asked to enter information that will be incorporated
  into your certificate request.
  What you are about to enter is what is called a Distinguished Name or a DN.
  There are quite a few fields but you can leave some blank
  For some fields there will be a default value,
  If you enter '.', the field will be left blank.
  -----
  Country Name (2 letter code) [US]:IT
  State or Province Name (full name) [Pennsylvania]:Italia
  Locality Name (eg, city) []:Bergamo
  Organization Name (eg, company) [Internet Widgits Pty Ltd]:Casa
  Organizational Unit Name (eg, section) []:Server
  Common Name (eg, YOUR name) []:nomemacchina.nomedominio
  Email Address []:mioindirizzoposta
  Please enter the following 'extra' attributes
  to be sent with your certificate request
  A challenge password []:
  An optional company name []:
  Using configuration from /usr/lib/ssl/openssl.cnf
  Enter pass phrase for ./demoCA/private/cakey.pem:password
  ...
  # openssl req -new -nodes -subj '/CN=nomemacchina.nomedominio/O=Casa/C=IT/ST=Italia/L=Bergamo/emailAddress=mioindirizzoposta' -keyout gmail.key -out gmail.req -days 3650
  # openssl ca -out gmail.pem -infiles gmail.req
  Using configuration from /usr/lib/ssl/openssl.cnf
  Enter pass phrase for ./demoCA/private/cakey.pem:password
  ...

Al riavvio di Postfix dovrei poter inviare messaggi tramite Gmail, che risulterà dai log con un messaggio di questo tipo:

Jul 25 11:36:52 server postfix/smtp[28745]: 8C31415DF79: to=<pippo@pippo.com>, relay=smtp.gmail.com[64.233.183.109]:587, delay=6.5, delays=0.0 5/0.05/3.8/2.7, dsn=2.0.0, status=sent (250 2.0.0 OK 1216978613 i4sm31861110nfh.1)