Postfix per ISP

Da Guide@Debianizzati.Org.
Vai alla navigazione Vai alla ricerca
Internet Service Provider con Debian Wheezy

Prerequisiti

Server email

Sconfiggere lo SPAM

Integrazione con altro software



Introduzione

In questo caso abbiamo deciso di configurare Postfix:

  • con un backend Mysql per la gestione dei domini, alias e account email
  • dovecot per lo smistamento delle email

Prerequisiti

Per procedere è necessario avere installato mysql e apache.

Installazione

Incominciamo con l'installare il server Postfix con la sua estensione per il supporto a MySQL:

# aptitude install postfix postfix-mysql

Configurazione Mysql

L'obiettivo è avere in mysql la gestione di:

  • virtual_domains
  • virtual_users
  • virtual_alias

Pertanto creeremo tali tre tabelle in modo tale da avere in un sistema in funzione le seguenti tabelle e contenuti:

-----------------
virtual_domains
-----------------
id 	|	name
1	|	example.com
2	|	foobar.org


---------------------------------
virtual_users
---------------------------------
id	|	domain_id	|	email			|	password
1	|	1		|	john@example.com	|	14cbfb845af1f030e372b1cb9275e6dd
2	|	1		|	steve@example.com	|	a57d8c77e922bf756ed80141fc77a658
3	|	2		|	kerstin@foobar.org	|	5d6423c4ccddcbbdf0fcfaf9234a72d0


-----------------------------------
virtual_aliases
-----------------------------------
id	|	domain_id	|	source			|	destination
1	|	1		|	steve@example.com	|	devnull@workaround.org
2	|	2		|	kerstin@foobar.org	|	kerstin42@yahoo.com
3	|	2		|	kerstin@foobar.org	|	kerstin@mycompany.com

Database e utenti

L'obiettivo è ottenere la seguente configurazione:

  • Database: mailserver
  • Utente: mailuser (con permessi limitati)
  • Utente: mailadmin (con permessi in scrittura e lettura). Non è obbligatorio ma IMO consigliato per la gestione via interfaccia web degli account.

Creiamo il database:

mysqladmin -u root -p create mailserver

Creiamo l'utente per postfix (con permessi limitati):

# mysql -u root -p

mysql> GRANT SELECT ON mailserver.*
       TO 'mailuser'@'127.0.0.1'
       IDENTIFIED BY 'mailuser2009';
Query OK, 0 rows affected (0.00 sec)
mysql> flush privileges;
Query OK, 0 rows affected (0.00 sec)
mysql> exit
Bye

Creazione Tabelle

# mysql -p mailserver

mysql>
CREATE TABLE `virtual_domains` (
  `id` int(11) NOT NULL auto_increment,
  `name` varchar(50) NOT NULL,
  PRIMARY KEY  (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

mysql>
CREATE TABLE `virtual_users` (
  `id` int(11) NOT NULL auto_increment,
  `domain_id` int(11) NOT NULL,
  `password` varchar(32) NOT NULL,
  `email` varchar(100) NOT NULL,
  PRIMARY KEY  (`id`),
  UNIQUE KEY `email` (`email`),
  FOREIGN KEY (domain_id) REFERENCES virtual_domains(id) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

mysql>
CREATE TABLE IF NOT EXISTS `virtual_aliases` (
  `id` int(11) NOT NULL auto_increment,
  `domain_id` int(11) NOT NULL,
  `source` varchar(100) NOT NULL,
  `destination` varchar(100) NOT NULL,
  PRIMARY KEY  (`id`),
  FOREIGN KEY (domain_id) REFERENCES virtual_domains(id) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

Sono state impostate alcune foreign keys: servono per collegare i record delle tabelle virtual_aliases e virtual_users con i record nella tabella virtual_domains. Questo ci permetterà di mantenere consistenti i dati nel database, perchè non potremo creare utenti virtuali o alias virtuali non collegati ad alcun dominio virtuale.
Il suffisso ON DELETE CASCADE significa che rimuovendo un dominio virtuale saranno cancellate anche tutti gli utenti virtuali e gli alias collegati al dominio, evitando di lasciare nel database dei record orfani.

Popolamento di Mysql

Creiamo e popoliamo in mysql le tre tabelle di cui sopra.

# mysql -p mailserver
mysql> INSERT INTO virtual_domains (id, name) VALUES (1, 'example.com');
mysql> INSERT INTO virtual_users (id, domain_id, email, password)
VALUES (1, 1, 'john@example.com', MD5('summersun'));
mysql> INSERT INTO virtual_aliases (id, domain_id, source, destination)
VALUES (1, 1, 'john@example.com', 'john@example.com'),
       (2, 1, 'devnull@example.com', 'john@workaround.org');

Configurazione POSTFIX

Domini locali e virtuali

Normalmente Postfix lavora con i cosiddetti Domini Locali, configurati nella direttiva mydestination del suo file di configurazione, e con gli utenti di sistema, elencati nel file /etc/passwd.
Questo comporta che ogni utente possa ricevere la posta di tutti i domini. Supponiamo di avere la direttiva:

mydestination = example1.com, example2.com, example3.com

Questo semplice setup fa sì che l'utente di sistema johndoe riceva le email indirizzate a:

johndoe@example1.com
johndoe@example2.com
johndoe@example3.com

Non è possibile impedire la ricezione della posta indirizzata a un singolo dominio e questo, unitamente al fatto che gestire molti utenti in questa maniera è inefficiente, rende il sistema poco pratico.

Questi problemi possono essere evitati facendo uso dei cosiddetti Domini Virtuali, che a loro volta gestiranno utenti virtuali e alias virtuali di posta. Nel corso della guida vedremo come questa tecnica sarà implementata attraverso alcune direttive Postfix e con il supporto di un database MySQL.

Preparazione del sistema

Controlliamo che il nostro /etc/hosts sia impostato correttamente:

  • Sbagliato:
20.30.40.50   mailserver42 mailserver42.example.com
  • Corretto:
20.30.40.50   mailserver42.example.com mailserver42

Mappatura di Postfix verso MySQL

(ossia come configurare i virtual domains)

virtual_domains, virtual_users e virtual_alias

Supponendo di avere già popolato il database come da esempio precedente, configuriamo la mappatura di postfix verso mysql e testiamola. Fatto questo avremo postfix configurato con i virtual domains e gestito nella configurazione via mysql.

Creiamo i seguenti file:

/etc/postfix/mysql-virtual-mailbox-domains.cf
user = mailuser
password = mailuser2009
hosts = 127.0.0.1
dbname = mailserver
query = SELECT 1 FROM virtual_domains WHERE name='%s'
/etc/postfix/mysql-virtual-mailbox-maps.cf
user = mailuser
password = mailuser2009
hosts = 127.0.0.1
dbname = mailserver
query = SELECT 1 FROM virtual_users WHERE email='%s'
/etc/postfix/mysql-virtual-alias-maps.cf
user = mailuser
password = mailuser2009
hosts = 127.0.0.1
dbname = mailserver
query = SELECT destination FROM virtual_aliases WHERE source='%s'


Info.png NOTA
Potrebbe venirvi la tentazione di scrivere "localhost" al posto di "127.0.0.1" nel file precedente. Non va fatto!! "localhost" farà sì che Postfix cerchi il file socket MySQL, non trovandolo perchè gira in una chroot hail. Al contrario "127.0.0.1" utilizzerà una connessione TCP sulla porta 3306, che risponderà anche se Postfix funziona all'interno di una gabbia chroot


Configuriamo postfix affinché utilizzi i parametri appena specificati per collegarsi a mysql:

postconf -e virtual_mailbox_domains=mysql:/etc/postfix/mysql-virtual-mailbox-domains.cf
postconf -e virtual_mailbox_maps=mysql:/etc/postfix/mysql-virtual-mailbox-maps.cf
postconf -e virtual_alias_maps=mysql:/etc/postfix/mysql-virtual-alias-maps.cf

Test

Effettuiamo su una shell il seguente test per verificare la correttezza della configurazione:

postmap -q example.com mysql:/etc/postfix/mysql-virtual-mailbox-domains.cf
postmap -q john@example.com mysql:/etc/postfix/mysql-virtual-mailbox-maps.cf
postmap -q john@example.com mysql:/etc/postfix/mysql-virtual-alias-maps.cf

Se tutto è andato a buon fine, con i comandi di cui sopra, otterremo:

1
1
john@example.com

email-to-email mapping

Prima di configurare Postfix per la mappatura virtual_alias_maps c'è ancora una cosa di cui dobbiamo preoccuparci. C'è uno particolare tipo di email forward chiamato catchall alias. Il catchall alias cattura tutte le email di un dominio per le quali non è definito un account.
Creiamo l'ultimo file di mappatura necessario:

# nano /etc/postfix/mysql-email2email.cf

e diamogli come contenuto:

user = mailuser
password = mailuser2009
hosts = 127.0.0.1
dbname = mailserver
query = SELECT email FROM virtual_users WHERE email='%s'

Verifichiamo che gli utenti con un account valido non vedano le loro email trattate come catchall alias:

# postmap -q john@example.com mysql:/etc/postfix/mysql-email2email.cf

Il risultato dovrebbe essere lo stesso indirizzo email: john@example.com
A questo punto possiamo istruire Postfix a utilizzare le ultime mappature definite:

# postconf -e virtual_alias_maps=mysql:/etc/postfix/mysql-virtual-alias-maps.cf,mysql:/etc/postfix/mysql-email2email.cf

Perfetto!
Tutte le mappature sono state definite e il database è pronto per essere riempito con domini e utenti.

Proibire l'invio di email con mittenti arbitrari

Nella configurazione impostata fino ad adesso ogni utente autenticato sul server SMTP può spedire email da qualsiasi indirizzo. Pur essendo una configurazione perfettamente funzionante, le impostazioni necessitano a mio avviso di qualche miglioramento.
Iniziamo con l'aggiungere le seguenti linee al file:

# nano /etc/postfix/main.cf
smtpd_sender_login_maps = mysql:/etc/postfix/mysql-sender-login-maps.cf
smtpd_sender_restrictions = reject_unknown_sender_domain,reject_non_fqdn_sender,reject_sender_login_mismatch 

Quindi creiamo un nuovo file:

# nano /etc/postfix/mysql-sender-login-maps.cf

con contenuto:

user = mailuser
password = mailuser2009
hosts = 127.0.0.1
dbname = mailserver
query = ( SELECT GROUP_CONCAT( a.`destination` ) FROM `virtual_aliases` a, `virtual_domains` d WHERE a.`source`='%s' AND a.`domain_id`=d.`id` AND d.`name`='%d' ) UNION ( SELECT `email` FROM `virtual_users` WHERE `email`='%s' )

A questo punto possiamo testare la configurazione aggiunta:

# postmap -q email@domian.tld mysql:/etc/postfix/mysql-sender-login-maps.cf

Dovremmo ottenere come risultato il nostro indirizzo email o i nostri alias, a seconda di come abbiamo configurato l'utente.
Da questo momento in poi ogni utente potrà inviare email utilzzando il proprio indirizzo email o uno dei propri alias come mittente e non potrà più inviare email con mittenti arbitrari.