Sinistra <- Mono - Indice Generale - Copertina - Maven: accumulator of knowledge -> Destra

Sistemi Liberi


Installazione e configurazione di un server Linux

di Francisco Yepes Barrera

L'articolo...

I servizi che è possibile attivare all'interno di un moderno server dipartimentale, così come la configurazione dello stesso sistema operativo, impongono al sistemista la realizzazione di un gran numero di operazioni in un ordine logico ben preciso. Il presente articolo aiuta a non dimenticare le "cose da fare" per alcuni servizi importanti all'interno di un server Linux.



Introduzione

Il titolo di questo articolo è molto generico. Tuttavia, è opportuno fare alcune precisazioni. Lo scopo dell'articolo è quello di fornire indicazioni dettagliate che si devono seguire per mettere in piedi servizi importanti all'interno di un server Linux, ma facendo in modo di poter avere tutto "alla mano", senza dover cercare (e perdersi, direi) all'interno dell'imponente massa di documentazione disponibile per questi servizi.

Naturalmente, non c'è niente di nuovo sotto il sole. Tutto quello che leggerete in questo articolo lo si trova in Rete, disponibile liberamente, ma penso che un piccolo compendio che riassuma le più importanti operazioni da realizzare sia utile, anche se mi rendo conto che si tratta di un parere opinabile.

Ritengo che la scelta della distribuzione sia importante ma non essenziale. Comunque, dato che questa scelta può portare a fare delle considerazioni che differiscono da altre distribuzioni, noi ne sceglieremo una in particolare. Anche se io non ne ho provate moltissime, parto dell'idea che "quello che funziona non si cambia" e, visto che l'articolo lo scrivo io, quanto sarà detto farà riferimento esplicitamente a una Debian etch.

Sempre nell'ottica di motivare il più possibile le scelte, che sono comunque in gran misura personali e dipendenti dalla storia e dalla formazione del sistemista, posso dire che apprezzo enormemente la stabilità e robustezza dei server Debian. Inoltre, sono dell'opinione che il sistema di aggiornamenti dei pacchetti sia tra i migliori in circolazione. A differenza delle altre distribuzioni non ho mai avuto problemi nel processo di aggiornamento del software, neppure nel passaggio dalla sarge alla etch, infatti è bastato modificare i sorgenti dei pacchetti e apt si è occupato di aggiornare l'intero sistema. Per quanto riguarda il software di aggiornamento dei pacchetti Debian, noi faremo riferimento a aptitude anziché apt, come consigliato dallo stesso team Debian, e che dovrebbe consentire una gestione più efficiente di alcune dipendenze, oltre a racchiudere nello stesso frontend tutta una serie di pacchetti apt (apt-get, apt-cache, ecc.).

Una buona "ricetta"

Quindi, il risultato di questo articolo sarà una "ricetta". Il concetto di ricetta è noto e comune ad altre categorie professionali. Pensiamo ad esempio ai cuochi oppure ai chimici. Entrambi usano dei protocolli chiamati nel gergo "ricette", che consistono sostanzialmente nell'elencare il tipo, il numero e l'ordine dei passaggi da seguire. La ricetta risparmia lo sforzo di dover ricordare ogni singolo passaggio, evitando quindi di perdere operazioni che potrebbero essere dimenticate, velocizzando enormemente l'intero processo di configurazione. Inoltre ci permette di standardizzare la sequenza di operazioni, utile nel caso l'operatore proponga ai suoi clienti lo stesso sistema.

Naturalmente, quanto detto non significa che le cose non debbano essere capite. Soprattutto perché non c'è modo di risolvere un problema, qualora si presenti, se non si comprende bene il sistema. Ma questo è uno sforzo che si fa le prime volte, dopodiché si può procedere molto più velocemente, senza dover focalizzare l'attenzione ogni volta sul singolo passaggio.

Quanto segue è il risultato di alcune note personali che ho costruito negli ultimi anni su queste problematiche, e che risultano sempre di enorme utilità. Spero che qualcuno di voi, alla fine della lettura, sarà della stessa opinione. Discuterò anche qualche opzione di configurazione che ho fatto fatica a reperire nella documentazione ufficiale, e che ho appreso su alcuni forum grazie all'aiuto di qualche collega.

Cominciamo.

I servizi

I punti che discuteremo sono i seguenti:

  1. installazione e configurazione minimale del server Debian;

  2. MySQL 5;

  3. Postfix + Clamav + Courier + Spamassassin + Postgrey, con virtualizzazione delle caselle di posta con un database MySQL;

  4. Apache 2 + phpmyadmin + postfixadmin;

  5. Hylafax;

  6. Rsnapshot.

Il sistema

I sistemi che io metto in piedi sono in genere formati da due dischi identici in RAID1, senza LVM. Preferisco una installazione minimale iniziale partendo da una installazione da rete:

  1. Masterizzare l'immagine ISO netinstall scaricata dal sito ufficiale Debian (http://www.debian.org/).

  2. Installare il sistema, seguendo le indicazioni in RAID1, eventualmente con il supporto LVM. Il programma di installazione Debian consente molto intuitivamente di definire le partizioni dei singoli dischi che verranno "integrate" nei diversi volumi RAID. Ovviamente bisogna prima partizionare ciascun disco.

    Il corretto partizionamento dei dischi è un punto soggetto a controversie, ma noi non ci soffermeremo a discuterlo per non allungare ulteriormente l'articolo. Per un disco da 160 GB (SATA) su un sistema con un 1 GB di RAM, in genere faccio il seguente partizionamento:

    # fdisk /dev/sda 
     
    Disk /dev/sda: 160.0 GB, 160000000000 bytes 
    255 heads, 63 sectors/track, 19452 cylinders 
    Units = cylinders of 16065 * 512 = 8225280 bytes 
     
       Device Boot      Start         End      Blocks   Id  System 
    /dev/sda1   *           1         122      979933+  fd  Linux raid autodetect 
    /dev/sda2             123        1338     9767520   fd  Linux raid autodetect 
    /dev/sda3            1339        1460      979965   fd  Linux raid autodetect 
    /dev/sda4            1461       19452   144520740    5  Extended 
    /dev/sda5            1461        3284    14651248+  fd  Linux raid autodetect 
    /dev/sda6            3285       19452   129869428+  fd  Linux raid autodetect

    La procedura di installazione si occupa per noi di assegnare il corretto id alla partizione; l'asterisco indica la partizione di boot. Io definisco 3 partizioni primarie (sda1 di 1 GB per la partizione di boot, sda2 di 10 GB per la partizione di root e sda3 di 1 GB per la swap, che è anch'essa in RAID) e una partizione estesa (sda4), che poi viene ridefinita in due partizioni logiche (sda5 di 15 GB per /usr e sda6 con il resto della capienza del disco per /var). La scelta di avere anche la swap in RAID1 permette, al prezzo di un rallentamento trascurabile, di avere un sistema completo se uno dei dischi si guasta. La partizione più grande è assegnata a /var dato che su un sistema Debian è qui che si verrà a trovare la maggior parte dei dati (posta, fax, ecc.). Lo stesso partizionamento deve essere fatto sull'altro disco (sdb).

    Fatto il partizionamento, le partizioni sono raggruppate per formare i diversi volumi RAID (definiti sempre comodamente dalla procedura di installazione):

    # cat /proc/mdstat  
    Personalities : [raid1]  
    md4 : active raid1 sda6[0] sdb6[1]
          129869312 blocks [2/2] [UU]       
     
    md3 : active raid1 sda5[0] sdb5[1]
          14651136 blocks [2/2] [UU]         
     
    md2 : active raid1 sda3[0] sdb3[1]
          979840 blocks [2/2] [UU]        
     
    md1 : active raid1 sda2[0] sdb2[1]
          9767424 blocks [2/2] [UU]         
     
    md0 : active raid1 sda1[0] sdb1[1]
          979840 blocks [2/2] [UU]         
     
    unused devices: <none> 

    che alla fine danno luogo al filesystem Linux:

    # cat /etc/fstab  
    # /etc/fstab: static file system information. 

    # <file system> <mount point>   <type>  <options>       <dump>  <pass> 
    proc            /proc           proc    defaults        0       0 
    /dev/md1        /               ext3    defaults,errors=remount-ro 0       1 
    /dev/md0        /boot           ext3    defaults        0       2 
    /dev/md3        /usr            ext3    defaults        0       2 
    /dev/md4        /var            ext3    defaults        0       2 
    /dev/md2        none            swap    sw              0       0 

  3. Per gli utenti, oltre al root, è meglio definire un altro utente, diciamo admin, il quale è l'unico a cui si potrà accedere da remoto tramite ssh, per ragioni di sicurezza.

  4. A questo punto è necessario modificare i sorgenti del package manager. Infatti, per qualche strana ragione, dopo l'installazione, il file dove sono definiti i sorgenti contiene una configurazione come se il sistema fosse caricato da CDROM. Quindi editiamo il file /etc/apt/sources.list e inseriamo, se non ci sono, le seguenti righe:

    # cat /etc/apt/sources.list
    deb http://ftp.it.debian.org/debian/ etch main 
    deb-src http://ftp.it.debian.org/debian/ etch main 
     
    deb http://security.debian.org/ etch/updates main contrib 
    deb-src http://security.debian.org/ etch/updates main contrib 
     
    # Debian volatile 
    deb http://volatile.debian.org/debian-volatile etch/volatile main contrib

    che definiscono gli host http da dove il sistema di aggiornamento reperisce i pacchetti. Il server security è importante e contiene frequenti patch di sicurezza. Il server volatile, invece, contiene pacchetti necessari per alcuni programmi che hanno bisogno di frequenti modifiche, tipicamente usato per aggiornare clamav e la definizione dei virus. Tutti e tre i server sono indispensabili per il corretto aggiornamento del sistema.

    La configurazione precedente è valida per un sistema che ha una installazione stable (la versione etch al momento di scrivere questo articolo) della distribuzione Debian. Per le versioni testing o unstable la configurazione sarà in genere differente. Al momento di un cambio nella versione stable, il file sources.list va modificato secondo le specifiche che si troveranno sul sito ufficiale.

  5. Installare il sistema base. I pacchetti addizionali verranno installati in seguito. Questo consente di avere più controllo, a mia opinione, sul software effettivamente caricato sul server.

  6. Aggiornare il file /etc/hosts con il nome corretto della macchina:

    # cat /etc/hosts 
    127.0.0.1      localhost 
    192.168.x.y    server.dominio    server

  7. Verificare l'hostname della macchina ed eventualmente settarlo con il comando hostname oppure scrivendo nome e dominio nel file /etc/hostname:

    # cat /etc/hostname  
    server.dominio

  8. A questo punto è necessario fare alcune modifiche nel file di configurazione di mdadm, il programma che si occupa della gestione del RAID dal punto di vista amministrativo. In particolare, editiamo il file /etc/mdadm/mdadm.conf e inseriamo o cambiamo le seguenti direttive:

    # automatically tag new arrays as belonging to the local system 
    HOMEHOST server.dominio 
     
    # instruct the monitoring daemon where to send mail alerts 
    MAILADDR email@dominio

    dove definiamo il nome del server e l'indirizzo di posta al quale verranno inviati eventuali messaggi. Se, ad esempio, il demone che gestisce il RAID verifica un guasto su uno dei dischi, invierà una comunicazione all'indirizzo di posta elettronica indicato in mdadm.conf.

    Salviamo le modifiche e facciamo ripartire il demone RAID:

    /etc/init.d/mdadm restart

  9. Per l'aggiornamento del sistema, creo un piccolo script update_system.sh che lancia in sequenza tutti i comandi necessari:

    #!/bin/sh
    apt-get update 
    apt-get -u dist-upgrade 
    apt-get clean 

    che lancio periodicamente, in genere una volta al mese. C'è un pacchetto Debian per fare la stessa cosa, ma io preferisco lanciare a mano questo script per avere il controllo su eventuali domande e messaggi di avvertimento generati durante il processo di aggiornamento. Dopo l'installazione del sistema, è opportuno lanciare questo script per la prima volta, in modo da aggiornare tutti i pacchetti del sistema all'ultima versione stabile.

  10. È arrivato il momento di installare grub sul mbr di entrambi i dischi. La procedura prevede i seguenti passaggi:

    # grub 
    grub> root (hd0,0)  
     Filesystem type is ext2fs, partition type 0xfd
    grub> setup (hd0)   
     Checking if "/boot/grub/stage1" exists... yes  
     Checking if "/boot/grub/stage2" exists... yes  
     Checking if "/boot/grub/e2fs_stage1_5" exists... yes  
     Running "embed /boot/grub/e2fs_stage1_5 (hd0)"...  16 sectors are 
    embedded. 
    succeeded  
     Running "install /boot/grub/stage1 (hd0) (hd0)1+16 p 
    (hd0,0)/boot/grub/stage2 /boot/grub/grub.conf"... succeeded 
    Done. 
     
    grub> root (hd1,0)  
     Filesystem type is ext2fs, partition type 0xfd
    grub> setup (hd1)   
     Checking if "/boot/grub/stage1" exists... yes  
     Checking if "/boot/grub/stage2" exists... yes  
     Checking if "/boot/grub/e2fs_stage1_5" exists... yes  
     Running "embed /boot/grub/e2fs_stage1_5 (hd1)"...  16 sectors are 
    embedded. 
    succeeded  
     Running "install /boot/grub/stage1 (hd1) (hd1)1+16 p 
    (hd1,0)/boot/grub/stage2 /boot/grub/grub.conf"... succeeded 
    Done.
    grub> quit

    In questo modo, se uno dei dischi si guasta, il disco rimanente ha tutte le informazioni per poter far ripartire il sistema e per lavorare normalmente, swap inclusa. L'aggiornamento del mbr di entrambi i dischi è necessario ad ogni cambiamento del kernel.

    Facciamo un reboot.

  11. Installiamo il server ssh:

    aptitude install openssh-server

    Modifichiamo il file /etc/ssh/sshd_config in modo da non permettere il login al root, tramite la direttiva:

    PermitRootLogin no

    e facciamo un restart del servizio:

    /etc/init.d/ssh restart

    Gli accessi ssh al server dovranno essere realizzati accedendo inizialmente con l'utente admin. Questo aumenta la sicurezza del sistema al costo di un doppio passaggio. Naturalmente, non si deve permettere all'utente admin l'esecuzione di comandi come root tramite sudo per non invalidare quanto detto.

  12. Sui server che faccio io, installo anche il dns per fare in modo che sia la macchina a occuparsi dei compiti di risoluzione dei nomi:

    aptitude install bind9

    Facciamo capire al server che sarà lui stesso a occuparsi della risoluzione dei nomi, aggiungendo nel file /etc/resolv.conf:

    search dominio
    nameserver 127.0.0.1

    In genere non installo il pacchetto resolvconf.

    Adesso però bisogna tenere in mente che, a differenza di quando si sceglie di utilizzare il dns del provider, non abbiamo previsto un sistema per aggiornare l'elenco dei root dns, che in genere varierà nel tempo. Il file che contiene questo elenco è definito nel file /etc/bind/named.conf:

    // prime the server with knowledge of the root servers 
    zone "." {
          type hint;
          file "/etc/bind/db.root";
    };

    e dove il file db.root contiene qualcosa come:

    ; <<>> DiG 9.3.4-P1.1 <<>> @e.root-servers.net . ns 
    ; (1 server found) 
    ;; global options:  printcmd 
    ;; Got answer: ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 10584 
    ;; flags: qr aa rd; QUERY: 1, ANSWER: 13, AUTHORITY: 0, ADDITIONAL: 14 
     
    ;; QUESTION SECTION: 
    ;.                         IN      NS 
     
    ;; ANSWER SECTION: 
    .                    518400  IN      NS      L.ROOT-SERVERS.NET. 
    .                   518400  IN      NS      J.ROOT-SERVERS.NET. 
    .                   518400  IN      NS      I.ROOT-SERVERS.NET. 
    .                   518400  IN      NS      D.ROOT-SERVERS.NET. 
    .                   518400  IN      NS      M.ROOT-SERVERS.NET. 
    .                   518400  IN      NS      C.ROOT-SERVERS.NET. 
    .                   518400  IN      NS      G.ROOT-SERVERS.NET. 
    .                   518400  IN      NS      H.ROOT-SERVERS.NET. 
    .                   518400  IN      NS      E.ROOT-SERVERS.NET. 
    .                   518400  IN      NS      F.ROOT-SERVERS.NET. 
    .                   518400  IN      NS      K.ROOT-SERVERS.NET. 
    .                   518400  IN      NS      B.ROOT-SERVERS.NET. 
    .                   518400  IN      NS      A.ROOT-SERVERS.NET. 
     
    ;; ADDITIONAL SECTION: 
    A.ROOT-SERVERS.NET.      3600000 IN      A       198.41.0.4 
    A.ROOT-SERVERS.NET.  3600000 IN      AAAA    2001:503:ba3e::2:30 
    B.ROOT-SERVERS.NET. 3600000 IN      A       192.228.79.201 
    C.ROOT-SERVERS.NET.      3600000 IN      A       192.33.4.12 
    D.ROOT-SERVERS.NET. 3600000 IN      A       128.8.10.90 
    E.ROOT-SERVERS.NET. 3600000 IN      A       192.203.230.10 
    F.ROOT-SERVERS.NET.      3600000 IN      A       192.5.5.241 
    F.ROOT-SERVERS.NET. 3600000 IN      AAAA    2001:500:2f::f 
    G.ROOT-SERVERS.NET.      3600000 IN      A       192.112.36.4 
    H.ROOT-SERVERS.NET.        3600000 IN      A       128.63.2.53 
    H.ROOT-SERVERS.NET. 3600000 IN      AAAA    2001:500:1::803f:235 
    I.ROOT-SERVERS.NET.        3600000 IN      A       192.36.148.17 
    J.ROOT-SERVERS.NET.       3600000 IN      A       192.58.128.30 
    J.ROOT-SERVERS.NET.       3600000 IN      AAAA    2001:503:c27::2:30 
     
    ;; Query time: 243 msec 
    ;; SERVER: 192.203.230.10#53(192.203.230.10) 
    ;; WHEN: Mon Dec  1 06:52:02 2008 
    ;; MSG SIZE  rcvd: 500 

    derivante dal lanciare il comando dig senza parametri. Per aggiornare questo file, costruiamo il seguente script:

    #!/bin/sh # 
    # Update the nameserver cache information file once per month. 
    # This is run automatically by a cron entry. 

    # Original by Al Longyear 
    # Updated for BIND 8 by Nicolai Langfeldt 
    # Miscelanious error-conditions reported by David A. Ranch 
    # Ping test suggested by Martin Foster 
    # bind up-test suggested by Erik Bryer. 

    (   
     
    PATH=/sbin:/usr/sbin:/bin:/usr/bin:  
    export PATH  
    # NOTE: /etc/bind must be writable only by trusted users or this script   
    # will cause root compromise/denial of service opportunities.  
    cd /etc/bind 2>/dev/null || {
        echo "Subject: Cannot cd to /etc/bind, error $?"
        echo
        echo "The subject says it all"
        exit 1  

     
    dig @e.root-servers.net . ns > db.root.new 2> errors 
     
    case `cat db.root.new` in
       *NOERROR*)
            # It worked
            :;;
       *)
            echo "Subject: The db.root file update has FAILED."
            echo         echo "The db.root update has failed"
            echo "This is the dig output reported:"
            echo         cat db.root.new errors
            exit 1
            ;;
    esac 
     
    # echo "Subject: The db.root file has been updated"
    echo  
    echo "The db.root file has been updated to contain the following information:"
    echo  
    cat db.root.new 
     
    chown root:root db.root.new  
    chmod 444 db.root.new  
    rm -fv db.root.old errors  
    mv -v db.root db.root.old  
    mv -v db.root.new db.root  
      
    /etc/init.d/bind9 restart  
    echo  
    echo "The nameserver has been restarted to ensure that the update is complete."  
    echo "The previous db.root file is now called    /etc/bind/db.root.old." 
    ) 2>&1 | mail -s 'The db.root file has been updated' email@dominio 
    exit 0 

    Basta mettere questo script nella cartella /etc/cron.monthly perché venga eseguito una volta al mese. Se qualche cosa va storto, possiamo sempre recuperare il file di backup /etc/bind/db.root.old.

  13. webmin è un programma utile per realizzare certi compiti di amministrazione. La etch non lo riporta più come pacchetto ufficiale, per cui bisogna scaricarlo e installarlo separatamente (c'è un apposito pacchetto .deb nel sito ufficiale del programma). webmin funziona come servizio a sé attraverso la porta 10000, nella configurazione di default. Per ragioni di sicurezza, imposto l'eventuale firewall o router a valle del server con la porta 10000 chiusa, in modo da impedire l'accesso dall'esterno. Il collegamento avviene attraverso vpn.

  14. Installo apache, nella versione 2 e con alcune dipendenze, che poi sarà necessario per molti servizi che andremo a configurare più avanti:

    aptitude install apache2 libnet-ssleay-perl openssl libauthen-pam-perl libio-pty-perl libmd5-perl

  15. Ci rimane qualche cosetta da fare. In primo luogo, accertarci che il sistema aggiorni l'ora periodicamente. A questo scopo, installiamo un client ntp:

    aptitude install ntpdate

    e scheduliamo l'aggiornamento di data e ora all'avvio del server e una volta al giorno. Io in genere lo faccio attraverso il crontab del root, inserendo le righe:

    @reboot /usr/sbin/ntpdate ntp1.ien.it
    @daily /usr/sbin/ntpdate ntp1.ien.it

  16. Per ultimo, cambio lo strip rotate, e cioè il numero massimo di periodi che verranno conservati per i file di log da logrotate. Io in genere utilizzo una periodicità settimanale e conservo 52 periodi, equivalenti a un anno:

# cat /etc/logrotate.conf  
# see "man logrotate" for details 
# rotate log files weekly 
weekly 
 
# keep 52 weeks worth of backlogs 
rotate 52 

MySQL

mysql è il database server che verrà utilizzato da tanti altri servizi, ad esempio dal server di posta postfix per la virtualizzazione delle caselle di posta. È un server affidabile e leggero. La configurazione prevede i seguenti passaggi:

  1. aptitude install mysql-server-5.0

    che installa anche tutta una serie di dipendenze associate.

  2. Cambiare la password di root per mysql:

    mysqladmin -u root password <new password>

  3. Per dare accesso da remoto oltre a localhost al server mysql, seguire la seguente procedura:

  4. Alcuni programmi hanno bisogno della compatibilità password con la versione 4 di mysql. Per settare la compatibilità per un utente mioutente password miapassword, inserire dalla console del programma:

UPDATE mysql.user SET PASSWORD = old_password( 'miapassword' ) WHERE User = 'mioutente';

Postfix + Clamav + Courier + Spamassassin + Postgrey

postfix è un server di posta sviluppato tenendo d'occhio la sicurezza. Su una macchina Linux gli utenti di sistema, di default hanno una casella di posta. I diversi servizi associati alla posta elettronica (smtp, pop, imap, ...) controllano e inoltrano le email verso la casella di posta dell'utente. Questa è una configurazione sconsigliabile, benché molo facile da configurare (in pratica bisogna installare il software e poco più), dal momento che per abilitare la posta a un utente bisogna creare un utente di sistema, con ovvie ricadute negative dal punto di vista della sicurezza. Quindi, in questo articolo proporremo una configurazione "virtuale", nel senso che le caselle di posta saranno delle cosiddette caselle di posta virtuali, slegate dagli utenti del sistema. Le credenziali di autenticazione e altri parametri necessari saranno definiti in un database mysql.

Gli altri programmi associati a questo servizio sono:

Il sistema proposto avrà quindi due sistemi antispam:

A questi due sottosistemi si aggiunge anche il controllo che postfix può realizzare sul messaggio in arrivo in base a un certo numero di restrizioni che possono essere impostate. Ad esempio, possiamo scegliere di accettare solo i messaggi che hanno un FQDN valido, oppure controllare se il mittente si trova in qualche blacklist di spammer. Questo controllo viene realizzato prima dell'inoltro del messaggio al sottosistema gestito da postgrey. Questo triplo meccanismo, nella mia esperienza, è enormemente efficiente nella gestione dello spam che arriverà sul nostro server.

L'interfacciamento tra postfix e il sistema antivirus/antispam avviene attraverso un software aggiuntivo, chiamato amavis-new.

  1. Innanzitutto installiamo tutto il software necessario, incluse le librerie che permettono l'interfacciamento di postfix e courier a mysql:

    aptitude install postgrey postfix courier-pop courier-imap courier-authlib courier-authlib-mysql postfix-mysql clamav clamav-daemon razor spamassassin amavisd-new

  2. Impostiamo alcuni parametri di configurazione di postfix, definiti nel file /etc/postfix/main.cf:

    # See /usr/share/postfix/main.cf.dist for a commented, more complete version
    smtpd_banner = $myhostname ESMTP $mail_name (Debian/GNU)  
     
    # appending .domain is the MUA's job. 
    append_dot_mydomain = no 
     
    # Uncomment the next line to generate "delayed mail" warnings 
    delay_warning_time = 4h 
     
    alias_maps = hash:/etc/aliases
    alias_database = hash:/etc/aliases 
    myorigin = $mydomain 
    mynetworks = 127.0.0.0/8 192.168.0.0/24 
    mailbox_command = procmail -a "$EXTENSION" 
    mailbox_size_limit = 0 
    message_size_limit = 30360000 
    recipient_delimiter = +

    Direttive importanti sono alias_maps e alias_database, che contengono le impostazioni degli alias, usati anche da programmi come mailman (ulteriormente aggiungeremo le direttive per specificare la tabella di mysql dove verranno registrati gli alias virtuali), mynetworks che definisce le reti per le quali i client sono definiti locali (in pratica le reti dalle quali postfix accetterà posta). mailbox_size_limit = 0 indica che la casella di posta è senza limiti.

  3. Abbiamo detto che tutti gli account saranno definiti in un database mysql. Quindi creiamo un database di nome postfix e un utente postfix che sarà l'unico a poter accedere a questo db:

    CREATE DATABASE postfix;
    GRANT ALL ON postfix.* TO postfix@localhost IDENTIFIED BY 'password';

    dopodiché bisogna definire la struttura delle tabelle del db postfix:

    CREATE TABLE `admin` (
      `username` varchar(255) NOT NULL default ",
      `password` varchar(255) NOT NULL default ",
      `created` datetime NOT NULL default '0000-00-00 00:00:00',
      `modified` datetime NOT NULL default '0000-00-00 00:00:00',
      `active` tinyint(1) NOT NULL default '1',
      PRIMARY KEY  (`username`),
      KEY `username` (`username`)
    ) ENGINE=MyISAM DEFAULT CHARSET=latin1 COMMENT='Postfix Admin - Virtual Admins'; 
     
    CREATE TABLE `alias` (
      `address` varchar(255) NOT NULL default ",
      `goto` text NOT NULL,
      `domain` varchar(255) NOT NULL default ",
      `created` datetime NOT NULL default '0000-00-00 00:00:00',
      `modified` datetime NOT NULL default '0000-00-00 00:00:00',
      `active` tinyint(1) NOT NULL default '1',
      PRIMARY KEY  (`address`),
      KEY `address` (`address`)
    ) ENGINE=MyISAM DEFAULT CHARSET=latin1 COMMENT='Postfix Admin - Virtual Aliases'; 
     
    CREATE TABLE `domain` (
      `domain` varchar(255) NOT NULL default ",
      `description` varchar(255) NOT NULL default ",
      `aliases` int(10) NOT NULL default '0',
      `mailboxes` int(10) NOT NULL default '0',
      `maxquota` int(10) NOT NULL default '0',
      `transport` varchar(255) default NULL,
      `backupmx` tinyint(1) NOT NULL default '0',
      `created` datetime NOT NULL default '0000-00-00 00:00:00',
      `modified` datetime NOT NULL default '0000-00-00 00:00:00',
      `active` tinyint(1) NOT NULL default '1',
      PRIMARY KEY  (`domain`),
      KEY `domain` (`domain`)
    ) ENGINE=MyISAM DEFAULT CHARSET=latin1 COMMENT='Postfix Admin - Virtual Domains'; 
     
    CREATE TABLE `domain_admins` (
      `username` varchar(255) NOT NULL default ",
      `domain` varchar(255) NOT NULL default ",
      `created` datetime NOT NULL default '0000-00-00 00:00:00',
      `active` tinyint(1) NOT NULL default '1',
      KEY `username` (`username`)
    ) ENGINE=MyISAM DEFAULT CHARSET=latin1 COMMENT='Postfix Admin - Domain Admins'; 
     
    CREATE TABLE `log` (
      `timestamp` datetime NOT NULL default '0000-00-00 00:00:00',
      `username` varchar(255) NOT NULL default ",
      `domain` varchar(255) NOT NULL default ",
      `action` varchar(255) NOT NULL default ",
      `data` varchar(255) NOT NULL default ",
      KEY `timestamp` (`timestamp`)
    ) ENGINE=MyISAM DEFAULT CHARSET=latin1 COMMENT='Postfix Admin - Log'; 
     
    CREATE TABLE `mailbox` (
      `username` varchar(255) NOT NULL default ",
      `password` varchar(255) NOT NULL default ",
      `name` varchar(255) NOT NULL default ",
      `maildir` varchar(255) NOT NULL default ",
      `quota` int(10) NOT NULL default '0',
      `domain` varchar(255) NOT NULL default ",
      `created` datetime NOT NULL default '0000-00-00 00:00:00',
      `modified` datetime NOT NULL default '0000-00-00 00:00:00',
      `active` tinyint(1) NOT NULL default '1',
      PRIMARY KEY  (`username`),
      KEY `username` (`username`)
    ) ENGINE=MyISAM DEFAULT CHARSET=latin1 COMMENT='Postfix Admin - Virtual Mailboxes'; 
     
    CREATE TABLE `vacation` (
      `email` varchar(255) NOT NULL default ",
      `subject` varchar(255) NOT NULL default ",
      `body` text NOT NULL,
      `cache` text NOT NULL,
      `domain` varchar(255) NOT NULL default ",
      `created` datetime NOT NULL default '0000-00-00 00:00:00',
      `active` tinyint(1) NOT NULL default '1',
      PRIMARY KEY  (`email`),
      KEY `email` (`email`)
    ) ENGINE=MyISAM DEFAULT CHARSET=latin1 COMMENT='Postfix Admin - Virtual Vacation';

  4. Per la configurazione delle caselle di posta virtuali, usiamo le seguenti direttive in /etc/postfix/main.cf:

    # VIRTUAL MAILBOXES 
    virtual_alias_maps = mysql:/etc/postfix/mysql_virtual_alias_maps.cf
    virtual_gid_maps = static:105 
    virtual_mailbox_base = /var/mail/virtual/ 
    virtual_mailbox_domains = mysql:/etc/postfix/mysql_virtual_domains_maps.cf 
    virtual_mailbox_limit = 0 
    virtual_mailbox_maps = mysql:/etc/postfix/mysql_virtual_mailbox_maps.cf 
    virtual_minimum_uid = 104 
    virtual_transport = virtual 
    virtual_uid_maps = static:104 
     
    # quota support 
    virtual_create_maildirsize = yes 
    virtual_mailbox_extended = yes 
    virtual_mailbox_limit_maps = mysql:/etc/postfix/mysql_virtual_mailbox_limit_maps.cf 
    virtual_mailbox_limit_override = yes 
    virtual_maildir_limit_message = Mi dispiace, la casella di posta dell'utente ha superato il suo limite 
    virtual_overquota_bounce = yes 

    Importanti sono le direttive virtual_uid_maps e virtual_gid_maps, che indicano l'id dell'utente e del gruppo di sistema dell'utente postfix. Questi id si possono trovare in /etc/passwd e /etc/group-.

    Con questa configurazione, il server è pronto per il supporto quote, che però non vedremo in questo articolo per non allungare eccessivamente la trattazione. Il file mysql_virtual_mailbox_limit_maps.cf contiene i riferimenti alla tabella dove vengono registrate eventuali impostazioni per le quote utenti.

    Vediamo i file contenenti la configurazione per l'accesso alle diverse tabelle del db postfix:

  5. È il momento di applicare alcune restrizioni alla configurazione del server smtp. A questo scopo scriviamo, sempre nel file /etc/postfix/main.cf:

    smtpd_recipient_restrictions =
      permit_mynetworks,
      permit_sasl_authenticated,
      reject_non_fqdn_hostname,
      reject_non_fqdn_sender,
      reject_non_fqdn_recipient,
      reject_unauth_destination,
      reject_unauth_pipelining,
      reject_invalid_hostname,
      check_policy_service inet:127.0.0.1:60000

    che in pratica consente il relay mail ai client appartenenti alle sottoreti definite in mynetworks e in cui gli host mittente e destinatario sono ben formati. L'ultima direttiva (check_policy_service) gira tutto quello che arriva al servizio di rete in ascolto sulla porta 60000, in pratica postgrey, come vedremo più avanti.

    E' possibile specificare altre direttive in smtpd_recipient_restrictions che permettono il controllo del mittente sulle blacklist di spammer, ad esempio:

    smtpd_recipient_restrictions =
      permit_mynetworks,
      permit_sasl_authenticated,
      reject_non_fqdn_hostname,
      reject_non_fqdn_sender,
      reject_non_fqdn_recipient,
      reject_unauth_destination,
      reject_unauth_pipelining,
      reject_invalid_hostname,
      check_policy_service inet:127.0.0.1:60000,
      reject_rbl_client opm.blitzed.org,
      reject_rbl_client list.dsbl.org,
      reject_rbl_client bl.spamcop.net,
      reject_rbl_client sbl-xbl.spamhaus.org 

  6. Una cosa conveniente da fare è girare l'utente root a una delle caselle di posta virtuali valide create (per i compiti amministrativi). A questo scopo si può modificare il file /etc/aliases in modo da avere qualcosa come:

    root: email@dominio

    poi bisogna lanciare il programma newaliases o postalias /etc/aliases per aggiornare la tabella degli alias (file /etc/aliases.db).

  7. Resta da creare la cartella dove sarà immagazzinata tutta la posta in arrivo per le diverse caselle, dando i permessi corretti, come specificato nella configurazione di postfix e courier:

    mkdir /var/mail/virtual
    chown postfix:postfix /var/mail/virtual/
    chmod ug+rwx /var/mail/virtual/
    chmod -s /var/mail/virtual/
    chmod o-rwx /var/mail/virtual/
    /etc/init.d/postfix restart

    Bisogna ricordarsi che, nel caso di domini virtuali, la username per il login sui servizi pop e imap deve essere specificata comprensiva del dominio.

  8. La configurazione di courier (il server pop/imap) è definita, fondamentalmente, nei file /etc/courier/authdaemonrc:

    authmodulelist="authmysql"
    authmodulelistorig="authcustom authcram authuserdb authldap authpgsql authmysql authpam"
    daemons=5
    authdaemonvar=/var/run/courier/authdaemon

    e /etc/courier/authmysqlrc:

    # The server name, userid, and password used to log in.
    MYSQL_SERVER            127.0.0.1
    MYSQL_USERNAME          postfix
    MYSQL_PASSWORD          <password> 
     
    # MYSQL_PORT can be used with MySQL version 3.22 or later to specify a port to
    # connect to.
    MYSQL_PORT              0 
     
    # Leave MYSQL_OPT as 0, unless you know what you're doing.
    MYSQL_OPT               0 
     
    # The name of the MySQL database we will open:
    MYSQL_DATABASE          postfix 
     
    # The name of the table containing your user data.  See README.authmysqlrc
    # for the required fields in this table.
    MYSQL_USER_TABLE        mailbox 
     
    # Either MYSQL_CRYPT_PWFIELD or MYSQL_CLEAR_PWFIELD must be defined.  Both
    # are OK too. crypted passwords go into MYSQL_CRYPT_PWFIELD, cleartext
    # passwords go into MYSQL_CLEAR_PWFIELD.  Cleartext passwords allow
    # CRAM-MD5 authentication to be implemented.
    MYSQL_CRYPT_PWFIELD     password 
     
    # MYSQL_UID_FIELD - contains the numerical userid of the account
    MYSQL_UID_FIELD         104 
     
    # Numerical groupid of the account
    MYSQL_GID_FIELD         105 
     
    # The login id, default is id.  Basically the query is:
    #
    #  SELECT MYSQL_UID_FIELD, MYSQL_GID_FIELD, ... WHERE id='loginid'
    MYSQL_LOGIN_FIELD       username 
     
    MYSQL_HOME_FIELD        '/var/mail/virtual' 
     
    # The user's name (optional)
    MYSQL_NAME_FIELD        name
    MYSQL_MAILDIR_FIELD     maildir 
     
    # MYSQL_AUXOPTIONS_FIELD        CONCAT("disableimap=",disableimap,",disablepop3=",disablepop3,",disablewebmail=",disablewebmail,",sharedgroup=",sharedgroup)

    Oltre alle direttive che specificano i parametri di connessione al server mysql, sono molto importanti MYSQL_UID_FIELD e MYSQL_GID_FIELD, che specificano l'utente postfix e il gruppo di appartenenza tramite il quale si accederà ai servizi di courier, in modo simile a quanto detto relativamente al file main.cf di postfix.
    Finito tutto facciamo ripartire tutti i servizi:

    /etc/init.d/courier-authdaemon restart
    /etc/init.d/courier-pop restart
    /etc/init.d/courier-imap restart

  9. Vediamo adesso l'interfacciamento tra postfix e il sistema antivirus/antispam. La prima cosa è inserire la seguente direttiva nel file /etc/postfix/main.cf:

    content_filter = amavis:[127.0.0.1]:10024

    che come si vede, viene configurato come un servizio di rete in ascolto sulla porta 10024. Nel file /etc/postfix/master.cf, dobbiamo inserire:

    amavis    unix  -       -       n       -       3       smtp -o smtp_data_done_timeout=1200 -o disable_dns_lookups=yes 
    127.0.0.1:10025 inet n -       n       -       -       smtpd -o content_filter

    quindi, amavis ascolta sulla porta 10024, ma poi gira tutto alla porta 10025, dove vengono applicate le direttive specificate in master.cf.

  10. Vediamo adesso la configurazione di amavis. Su una Debian etch, la configurazione è divisa in file multipli, come specificato in /usr/share/doc/amavisd-new/README.Debian:

    Come si vede, la configurazione di amavis è piuttosto complessa e articolata. Seguendo quanto consigliato nel file README.Debian, noi inseriremo le nostre direttive personalizzate in /etc/amavis/conf.d/50-user, che essendo l'ultimo file ad essere letto, sovrascrive tutta la configurazione definita precedentemente dagli altri file di configurazione. Le direttive più importanti in questo file sono:

    # $MYHOME serves as a quick default for some other configuration settings.
    # More refined control is available with each individual setting further down.
    # $MYHOME is not used directly by the program. No trailing slash!
    $MYHOME = '/var/lib/amavis';   # (default is '/var/amavis') 
     
    # $mydomain serves as a quick default for some other configuration settings.
    # More refined control is available with each individual setting further down.
    # $mydomain is never used directly by the program.
    $mydomain = 'dominio';      # (no useful default) 
     
    # Set the user and group to which the daemon will change if started as root
    # (otherwise just keeps the UID unchanged, and these settings have no effect):
    $daemon_user  = 'amavis';       # (no default (undef))
    $daemon_group = 'amavis';       # (no default (undef)) 
     
    # Runtime working directory (cwd), and a place where
    # temporary directories for unpacking mail are created.
    # if you change this, you might want to modify the cleanup()
    # function in /etc/init.d/amavisd-new
    # (no trailing slash, may be a scratch file system)
    $TEMPBASE = $MYHOME;           # (must be set if other config vars use is) 
     
    # Run the daemon in the specified chroot jail if nonempty:
    #$daemon_chroot_dir = $MYHOME;  # (default is undef, meaning: do not chroot)
    $pid_file  = "/var/run/amavis/amavisd.pid";  # (default: "$MYHOME/amavisd.pid")
    $lock_file = "/var/run/amavis/amavisd.lock"; # (default: "$MYHOME/amavisd.lock") 
     
    # POSTFIX, or SENDMAIL in dual-MTA setup, or EXIM V4
    # (set host and port number as required; host can be specified
    # as IP address or DNS name (A or CNAME, but MX is ignored)
    $forward_method = 'smtp:127.0.0.1:10025';  # where to forward checked mail
    $notify_method = $forward_method;          # where to submit notifications 
     
    # Net::Server pre-forking settings
    # You may want $max_servers to match the width of your MTA pipe
    # feeding amavisd, e.g. with Postfix the 'Max procs' field in the
    # master.cf file, like the '2' in the:  smtp-amavis unix - - n - 2 smtp
    $max_servers  =  2;   # number of pre-forked children          (default 2)
    $max_requests = 10;   # retire a child after that many accepts (default 10)
    $child_timeout=5*60;  # abort child if it does not complete each task in n sec
                          # (default: 8*60 seconds) 
     
    # With Postfix (2.0) a quick reminder on what local domains normally are:
    # a union of domains specified in: $mydestination, $virtual_alias_domains,
    # $virtual_mailbox_domains, and $relay_domains.
    @local_domains_acl = ( ".$mydomain" );  # $mydomain and its subdomains 
     
    # SMTP SERVER (INPUT) PROTOCOL SETTINGS (e.g. with Postfix, Exim v4, ...)
    #   (used when MTA is configured to pass mail to amavisd via SMTP or LMTP)
    $inet_socket_port = 10024;        # accept SMTP on this local TCP port 
     
    # SMTP SERVER (INPUT) access control
    # - do not allow free access to the amavisd SMTP port !!!
    #
    # when MTA is at the same host, use the following (one or the other or both):
    $inet_socket_bind = '127.0.0.1';  # limit socket bind to loopback interface
                                      # (default is '127.0.0.1')
    @inet_acl = qw( 127.0.0.1 );      # allow SMTP access only from localhost IP
                                      # (default is qw( 127.0.0.1 ) ) 
     
    # Notifications
    $notify_spam_sender_templ = read_text('/var/lib/amavis/notify_spam_sender.txt'); 
     
    # The following symbolic constants can be used in *destiny settings:
    #
    # D_PASS     mail will pass to recipients, regardless of bad contents;
    #
    # D_DISCARD  mail will not be delivered to its recipients, sender will NOT be
    #            notified. Effectively we lose mail (but will be quarantined
    #            unless disabled). Losing mail is not decent for a mailer,
    #            but might be desired.
    #
    # D_BOUNCE   mail will not be delivered to its recipients, a non-delivery
    #            notification (bounce) will be sent to the sender by amavisd-new;
    #            Exception: bounce (DSN) will not be sent if a virus name matches
    #            $viruses_that_fake_sender_re, or to messages from mailing lists
    #            (Precedence: bulk|list|junk);
    #
    # D_REJECT   mail will not be delivered to its recipients, sender should
    #            preferably get a reject, e.g. SMTP permanent reject response
    #            (e.g. with milter), or non-delivery notification from MTA
    #            (e.g. Postfix). If this is not possible (e.g. different recipients
    #            have different tolerances to bad mail contents and not using LMTP)
    #            amavisd-new sends a bounce by itself (same as D_BOUNCE).
    #
    # Notes:
    #   D_REJECT and D_BOUNCE are similar, the difference is in who is responsible
    #            for informing the sender about non-delivery, and how informative
    #            the notification can be (amavisd-new knows more than MTA);
    #   With D_REJECT, MTA may reject original SMTP, or send DSN (delivery status
    #            notification, colloquially called 'bounce') - depending on MTA;
    #            Best suited for sendmail milter, especially for spam.
    #   With D_BOUNCE, amavisd-new (not MTA) sends DSN (can better explain the
    #            reason for mail non-delivery, but unable to reject the original
    #            SMTP session). Best suited to reporting viruses, and for Postfix
    #            and other dual-MTA setups, which can't reject original client SMTP
    #            session, as the mail has already been enqueued.
    $final_virus_destiny      = D_BOUNCE; # (defaults to D_BOUNCE)
    $final_banned_destiny     = D_BOUNCE;  # (defaults to D_BOUNCE)
    $final_spam_destiny       = D_BOUNCE;  # (defaults to D_REJECT)
    $final_bad_header_destiny = D_BOUNCE;  # (defaults to D_PASS), D_BOUNCE suggested
    $virus_admin = "antivirus\@$mydomain";
    $spam_admin = "antispam\@$mydomain"; 
     
    # whom notification reports are sent from (ENVELOPE SENDER);
    # may be a null reverse path, or a fully qualified address:
    #   (admin and recip sender addresses default to $mailfrom
    #   for compatibility, which in turn defaults to undef (empty) )
    #   If using strings in double quotes, don't forget to quote @, i.e. \@
    $mailfrom_notify_admin     = "antivirus\@$mydomain";
    $mailfrom_notify_recip     = "antispam\@$mydomain";
    $mailfrom_notify_spamadmin = "antispam\@$mydomain"; 
     
    # 'From' HEADER FIELD for sender and admin notifications.
    # This should be a replyable address, see rfc1894. Not to be confused
    # with $mailfrom_notify_sender, which is the envelope return address
    # and should be empty (null reverse path) according to rfc2821.
    #
    # The syntax of the 'From' header field is specified in rfc2822, section
    # '3.4. Address Specification'. Note in particular that display-name must be
    # a quoted-string if it contains any special characters like spaces and dots.
    $hdrfrom_notify_sender = "Antispam <antispam\@$mydomain>"; 
     
    # Location to put infected mail into: (applies to 'local:' quarantine method)
    #   empty for not quarantining, may be a file (mailbox),
    #   or a directory (no trailing slash)
    #   (the default value is undef, meaning no quarantine)
    $QUARANTINEDIR = '/var/lib/amavis/virusmails';
    $virus_quarantine_to  = 'virus-quarantine';    # traditional local quarantine
    $spam_quarantine_to = 'spam-quarantine'; 
     
    # Add X-Virus-Scanned header field to mail?
    $X_HEADER_TAG = 'X-Virus-Scanned';      # (default: undef)
    $X_HEADER_LINE = "by $myversion (Debian) at $mydomain"; 
     
    # a hash lookup table can be read from a file, 
    # one address per line, comments and empty lines are permitted: 
    read_hash(\%whitelist_sender, '/var/lib/amavis/whitelist'); 
    read_hash(\%blacklist_sender, '/var/lib/amavis/blacklist'); 
    read_hash(\%spam_lovers, '/var/lib/amavis/spam_lovers');

    Chiaramente, bisogna definire due caselle virtuali: antivirus@dominio e antispam@dominio, per poter ricevere le notifiche amministrative quando amavis identifica un virus o un messaggio di spam. Le tre direttive finali indicano la posizione della blacklist e whitelist (si rimanda alla documentazione ufficiale per la sintassi utilizzata in questi file). Ho preferito essere prolisso nell'illustrare questa configurazione, in modo da inserire i commenti esplicitativi presenti nello stesso file.

    Il file /var/lib/amavis/notify_spam_sender.txt contiene il template del testo con cui il mittente verrà avvisato che il messaggio non è stato recapitato perché non ha superato il filtro antispam:

    From: AutoSpamChecker <antispam@dominio>
    Subject: **Message you sent blocked by our SPAM filter**
    [? %m |#|In-Reply-To: %m]
    Message-ID: <SS%n@%h> 
     
    Your message to: %R
    has triggered our SpamAssassin SPAM filters and has been rejected. 
    The email you sent with the following subject has NOT BEEN DELIVERED: 
     
    Subject: %j 
     
    Our company uses a set of email filters to help block the delivery of 
    unsolicited commercial email, otherwise known as SPAM. For more 
    information on SPAM, please visit http://spam.abuse.net. 
     
    If you believe that you have received this message in error, please 
    accept our sincere apologies. We ask that you please reply to this 
    email message. When we receive your reply, we will add your email 
    address to our list of approved senders so that in the future 
    we can avoid making this mistake again. Please note that this is a 
    manual process and is only done during business hours. 
     
    The report below will help you determine why your message was flagged 
    as SPAM.   If you continue to have problems, please contact our 
    administrator at abuse@dominio. 
     
    Thank you very much,
    Postmaster 

    SpamAssassin report:
    [%A
    ]\

    dove si suppone che abuse@dominio sia una casella di posta valida.

    Se facciamo un /etc/init.d/amavis restart, possiamo leggere in /var/log/syslog alcune righe relative alla configurazione di amavis che ci danno indicazione dei moduli caricati (decompressori, il modulo per spamassassin, ecc.):

    Jan 12 17:16:46 marte amavis[32333]: Module Archive::Tar 1.30
    Jan 12 17:16:46 marte amavis[32333]: Module Archive::Zip 1.16
    Jan 12 17:16:46 marte amavis[32333]: Module Compress::Zlib 1.42
    Jan 12 17:16:46 marte amavis[32333]: Module Mail::SpamAssassin 3.002003
    Jan 12 17:16:46 marte amavis[32333]: Module Razor2::Client::Version 2.81
    ...

    e se i sottosistemi antivirus e antispam sono funzionanti:

    Jan 12 17:16:46 marte amavis[32333]: Amavis::DB code loaded
    Jan 12 17:16:46 marte amavis[32333]: ANTI-VIRUS code loaded
    Jan 12 17:16:46 marte amavis[32333]: ANTI-SPAM code loaded
    Jan 12 17:16:46 marte amavis[32333]: ANTI-SPAM-SA code loaded
    Jan 12 17:16:46 marte amavis[32333]: Unpackers code loaded
    ...
    Jan 12 17:16:46 marte amavis[32333]: Using internal av scanner code for (primary) Clam Antivirus-clamd
    Jan 12 17:16:46 marte amavis[32333]: Found secondary av scanner Clam Antivirus - clamscan at /usr/bin/clamscan
    Jan 12 17:16:46 marte amavis[32333]: Creating db in /var/lib/amavis/db/; BerkeleyDB 0.31, libdb 4.4

    razor è un sistema distribuito di blacklisting per spammers, e viene usato da spamassassin per realizzare una verifica sul mittente del messaggio, prima dell'analisi effettiva del contenuto. razor verrà implementato e configurato più avanti, come parte del sottosistema relativo a spamassassin.

  11. Vediamo adesso la configurazione di clamav, l'antivirus. C'è un difetto nella configurazione di default quando si usa amavis, ed è che il file di configurazione imposta il proprietario del database come clamav, l'utente antivirus, anziché amavis, che è l'utente che effettivamente deve aver accesso ai file interni di clamav. Quindi, sostituiamo

    DatabaseOwner clamav

    con

    DatabaseOwner amavis

    nel file /etc/clamav/freshclam.conf. Poi cambiamo tutti i permessi dei file di lavoro interessati:

    /etc/init.d/clamav-daemon stop
    /etc/init.d/clamav-freshclam stop
    chown -R amavis:amavis /var/log/clamav
    chown -R amavis:amavis /var/run/clamav
    chown -R amavis:amavis /var/lib/clamav
    sed -i 's/clamav adm/amavis adm/' /etc/logrotate.d/clamav-daemon
    sed -i 's/clamav adm/amavis adm/' /etc/logrotate.d/clamav-freshclam
    sed -i 's/User clamav/User amavis/' /etc/clamav/clamd.conf
    /etc/init.d/clamav-freshclam start
    /etc/init.d/clamav-daemon start

  12. Vediamo adesso la configurazione di spamassassin e razor. La configurazione di spamassassin la si trova in /etc/spamassassin/local.cf:

    # This is the right place to customize your installation of SpamAssassin.
    #
    # See 'perldoc Mail::SpamAssassin::Conf' for details of what can be
    # tweaked.
    #
    ###########################################################################

     
    rewrite_header Subject *****SPAM*****
    report_safe                             1
    required_hits                           5.0
    skip_rbl_checks                         0
    rbl_timeout                             10
    dns_available                           yes
    ok_locales                              all
    score DCC_CHECK                         3.8
    score RAZOR_CHECK                       2.5
    score PYZOR_CHECK                       2.5 
     
    # dcc
    use_dcc 1
    dcc_path /usr/bin/dccproc
    dcc_add_header 1
    dcc_dccifd_path /usr/sbin/dccifd 
     
    #pyzor
    use_pyzor 1
    pyzor_path /usr/bin/pyzor
    pyzor_add_header 1 
     
    #razor
    use_razor2 1
    razor_config /etc/razor/razor-agent.conf 
     
    #bayes
    use_bayes 1
    use_bayes_rules 1
    bayes_auto_learn 1
    bayes_auto_learn_threshold_nonspam      0.1
    bayes_auto_learn_threshold_spam         10.0

    Per completezza, riporto anche la configurazione di dcc e pyzor (altri due sistemi di verifica spammer distribuiti) che ho usato in passato. Per quanto riguarda razor (/etc/razor/razor-agent.conf):

    # See razor-agent.conf (5)
    # Change this to 5 for safer classification of MIME attachments.  This will let more spam through
    logic_method = 4 
     
    # Uncomment the next line for logging via syslog
    #logfile = sys-syslog
    # If you do log to syslog, consider using logrotate
    # (see /usr/share/doc/razor/logcheck.ignore.eg)

    C'è un altro file in /var/lib/amavis/.razor/razor-agent.conf, che però viene autogenerato dallo stesso software:

    #
    # Razor2 config file

    # Autogenerated by Razor-Agents v2.81 
    # Thu Jul 12 11:29:12 2007
    # Non-default values taken from /var/lib/amavis/.razor/razor-agent.conf 

    # see razor-agent.conf(5) man page 
    #
    debuglevel             = 3
    identity               = identity
    ignorelist             = 0
    listfile_catalogue     = servers.catalogue.lst
    listfile_discovery     = servers.discovery.lst
    listfile_nomination    = servers.nomination.lst
    logfile                = razor-agent.log
    logic_method           = 4
    min_cf                 = ac
    razordiscovery         = discovery.spamnet.com
    rediscovery_wait       = 172800
    report_headers         = 1
    turn_off_discovery     = 0
    use_engines            = 4,8
    whitelist              = razor-whitelist

    A questo punto bisogna dire al sistema di far partire spamassassin come servizio all'avvio della macchina. Questa operazione la si fa mettendo ENABLED = 1 nel file /etc/default/spamassassin:

    # /etc/default/spamassassin
    # Duncan Findlay
    # WARNING: please read README.spamd before using.
    # There may be security risks.
    # Change to one to enable spamd
    ENABLED=1 
     
    # Options
    # See man spamd for possible options. The -d option is automatically added.
    # SpamAssassin uses a preforking model, so be careful! You need to
    # make sure -max-children is not set to anything higher than 5,
    # unless you know what you're doing.
    OPTIONS="-create-prefs -max-children 5 -helper-home-dir" 
     
    # Pid file
    # Where should spamd write its PID to file? If you use the -u or
    # -username option above, this needs to be writable by that user.
    # Otherwise, the init script will not be able to shut spamd down.
    PIDFILE="/var/run/spamd.pid" 
     
    # Set nice level of spamd
    #NICE="-nicelevel 15"
    # Cronjob
    # Set to anything but 0 to enable the cron job to automatically update
    # spamassassin's rules on a nightly basis
    CRON=0

    Poi facciamo partire il servizio:

    /etc/init.d/spamassassin start

  13. L'ultimo punto è costituito dal sottosistema postgrey. Abbiamo già visto la direttiva da inserire nella configurazione di postfix al punto 5. La configurazione si trova nel file /etc/default/postgrey:

# postgrey startup options, created for Debian
# (c)2004 Adrian von Bidder <avbidder@fortytwo.ch>
# Distribute and/or modify at will.
# you may want to set
#   -delay=N   how long to greylist, seconds (default: 300)
#   -max-age=N delete old entries after N days (default: 30)
# see also the postgrey(8) manpage
POSTGREY_OPTS="-inet=127.0.0.1:60000" 
 
# the -greylist-text commandline argument can not be easily passed through
# POSTGREY_OPTS when it contains spaces.  So, insert your text here:
#POSTGREY_TEXT="Your customized rejection message here"

Apache 2 + phpmyadmin + postfixadmin

  1. Innanzitutto, installiamo il software necessario:

    aptitude install apache2 php5 phpmyadmin postfixadmin

    phpmyadmin e postfixadmin sono due programmi web molto ben fatti e facili da utilizzare che ci possono dare una preziosa mano nella gestione dei dati associati alle caselle di posta virtuali. postfixadmin è stato sviluppato appositamente per questo scopo; invece phpmyadmin ha una utilità generica nella gestione di database mysql. Entrambi sono programmi php, e per questo abbiamo installato l'interprete per questo linguaggio.

  2. Dobbiamo attivare i moduli di apache per il php e ssl, che ci serviranno nei punti successivi:

    a2enmode php5
    a2enmode ssl

  3. È possibile che ci si voglia collegare dall'esterno della rete aziendale per poter gestire le caselle di posta (o eventualmente qualsiasi database mysql), anche se non è raccomandabile, essendo sempre preferibile realizzare un collegamento via VPN. Ovviamente, in questo caso non possiamo realizzare una connessione HTTP usuale, dal momento che tutto il traffico dati passa in chiaro. Bisogna incapsulare la connessione attraverso il layer SSL del protocollo HTTP (HTTPS). Bisogna disporre di un certificato, che per i nostri scopi può essere autofirmato. Il certificato viene creato attraverso il seguente comando:

    openssl req $@ -new -x509 -days 9999 -nodes -out /etc/apache2/ssl/apache.pem -keyout /etc/apache2/ssl/apache.pem

    e che viene salvato in /etc/apache2/ssl. Inoltre, bisogna specificare nella configurazione di apache la porta attraverso la quale verrà realizzata la connessione HTTPS (la porta canonica è la 443), aggiungendo:

    Listen 443

    nel file /etc/apache2/ports.conf.

  4. Adesso è arrivato il momento di creare gli host virtuali. Per postfixadmin, io ne creo due, uno per la gestione della connessione HTTP (/etc/apache2/sites_available/postfixadmin):

    <VirtualHost *:80>
            ServerAdmin email@dominio
            
            DocumentRoot /var/www/postfixadmin
            ServerName postfixadmin.dominio
            Redirect permanent / https://postfixadmin.dominio/
    </VirtualHost>

    e un altro per la connessione HTTPS (/etc/apache2/sites_available/postfixadmin_ssl):

    <VirtualHost *:443>
            ServerAdmin email@dominio
            
            DocumentRoot /var/www/postfixadmin
            ServerName postfixadmin.dominio
            <Directory /var/www/postfixadmin>
                    Options -Indexes FollowSymLinks MultiViews
                    AllowOverride None
                    Order allow,deny
                    allow from all
            </Directory> 
     
            # Possible values include: debug, info, notice, warn, error, crit,
            # alert, emerg.
            LogLevel warn
            ErrorLog /var/log/apache2/postfixadmin_error.log
            CustomLog /var/log/apache2/postfixadmin.log combined
            ServerSignature Off
            <Directory /var/www/postfixadmin/admin>
                    AllowOverride AuthConfig
            </Directory>
            SSLEngine on
            SSLCertificateFile /etc/apache2/ssl/apache.pem
    </VirtualHost>

    come si può osservare, tutto il traffico che arriva tramite HTTP viene girato all'host virtuale attivo sulla porta 443, in modo da evitare che sia possibile l'accesso non protetto. Quest'ultimo attiva il layer SSL e logga tutto sui file specificati.

    Per phpmyadmin abbiamo dei file simili, ma è necessario definire solo quello SSL, dal momento che sulla Debian l'installazione del programma prevede l'inclusione di un file di configurazione già pronto e l'attivazione e lettura da parte di apache. Per il reindirizzamento di tutto il traffico HTTPS basta aggiungere

    Redirect permanent / https://phpmyadmin.dominio/

    nel file /etc/apache2/conf.d/phpmyadmin.conf.

  5. Attiviamo gli host virtuali e facciamo ripartire il servizio:

a2ensite phpmyadmin postfixadmin postfixadmin_ssl
/etc/init.d/apache2 reload

Hylafax

hylafax è un potente programma per l'invio e ricezione fax. Lavora a basso livello ed è estremamente affidabile. La configurazione prevede la creazione di un utente faxmaster, operazione realizzata automaticamente durante il processo di installazione.

  1. Per prima cosa installiamo il software:

    aptitude install hylafax-server

    La procedura di installazione lancia un programma chiamato faxsetup, attraverso il quale viene realizzata la configurazione, compresa la tipologia di modem (che viene riconosciuta automaticamente), il numero di telefono, ecc. Successivamente si può lanciare il programma faxaddmodem per realizzare variazioni a questa configurazione, anche se io preferisco modificare manualmente i file di configurazione.

  2. È opportuno configurare l'email dell'utente al quale verranno recapitati tutti i fax ricevuti e la tipologia di file; il fax sarà ricevuto per posta elettronica come allegato a un messaggio con il formato specificato. Queste due opzioni si trovano nel file /var/spool/hylafax/bin/faxrcvd:

    FILETYPE=pdf 
    SENDTO=faxmaster@dominio

    L'opzione predefinita per il formato del file è TIF. Ovviamente, faxmaster@dominio deve essere una casella virtuale valida oppure un alias a una casella virtuale.

  3. Adesso dobbiamo configurare le reti e/o gli utenti che avranno il permesso di utilizzare i servizi fax dal file /etc/hylafax/hosts.hfaxd:

    localhost:21::
    192\.168\.x\.:::
    ^user1@::zdsUsd324

    Questa configurazione permette l'utilizzo del servizio fax alla macchina locale, alla sottorete 192.168.10.0 e all'utente user1. Per l'inserimento e cancellazione degli utenti si utilizzano i programmi faxadduser e faxdeluser (con password crittografata). Questa è una configurazione di esempio; in realtà si potrà scegliere tra specificare gli utenti con password o permettere l'utilizzo a tutta la rete.

  4. Facciamo ripartire il servizio e siamo a posto:

    /etc/init.d/hylafax restart

    Per verificare se il tutto funziona si può usare il comando faxstat:

    # faxstat 
    HylaFAX scheduler on server.dominio: Running 
    Modem ttyS0 (+39.xxx.xxxxxxx): Running and idle

  5. Per finire, possiamo schedulare i programmi faxcron e faxqclean, che rispettivamente inviano un resoconto periodico delle attività fax e puliscono la cache dei fax ricevuti/inviati:

    @monthly /usr/sbin/faxcron | mail -s 'Hylafax statistiche' root && /usr/sbin/faxqclean

    dove la casella root è un alias alla casella reale dell'amministratore del sistema.

  6. Una cosa molto funzionale consiste nell'integrazione tra hylafax e postfix per fare in modo di inviare i fax come email direttamente dal nostro client di posta elettronica. Per fare questo dobbiamo modificare la configurazione di postfix. Nel file main.cf aggiungiamo:

    # Hylafax via mail 
    fax_destination_recipient_limit = 1

    mentre in master.cf, bisogna aggiungere:

    # Hylafax via mail
    fax unix     -       n       n       -       1       pipe
       flags= user=faxmaster argv=/usr/bin/faxmail -d -n ${user}

    Infine, in /etc/postfix/transport, aggiungiamo la seguente riga:

    fax.dominio fax:localhost

    (si possono aggiungere insieme più domini). Fatto questo, aggiorniamo il database trasport.db e rileggiamo la configurazione:

    postmap transport
    /etc/init.d/postfix reload

    Da questo momento abbiamo la possibilità di inviare fax via posta elettronica, inserendo come destinatario <numero di telefono>@fax.dominio. postfix girerà il messaggio a hylafax che lo invierà come un normale fax.

Rsnapshot

Finiamo questo articolo con un sistema per il backup. rsnapshot è uno script perl che realizza backup (di tipo snapshot) utilizzando rsync e gli hard-link, supportati dalla maggior parte dei filesystem linux. Come è noto, rsync permette di sincronizzare due filesystem in modo efficiente, ma c'è un problema: se modifico un file nel filesystem originale e non me ne accorgo prima della successiva sincronizzazione con rsync, la modifica sarà replicata nella mia copia di backup e mi sarà impossibile recuperare il file prima della modifica. Lo stesso discorso vale per la cancellazione dei file se sto usando rsync con l'opzione -delete.

rsnapshot utilizza questa logica ma permette di organizzare gli snapshot in più periodi temporali, in modo che sia possibile recuperare le copie del file non modificate su un backup precedente alla data in cui è stata realizzata la modifica o è stato cancellato il file. Gli hard-link sono usati dal momento che richiedono molto meno spazio su disco della semplice copia del file.

La base del funzionamento del sistema è la seguente: supponiamo di avere 3 backup relativi agli ultimi tre giorni, daily0, daily1 e daily2. rsnapshot inizia il suo lavoro cancellando daily2 (si suppone che un quarto backup sarebbe al di fuori dell'arco temporale coperto dal sistema secondo la configurazione, che poi analizzeremo) e rinominando daily1 come daily2; a questo punto abbiamo i seguenti snapshot: daily0 e daily2. Successivamente, rsnapshot realizza una copia di daily0 e la chiama daily1, ma non si tratta di una copia usuale, ma di una copia ricorsiva come hard-link (viene usata l'opzione -l del comando cp). In pratica, alla fine del processo, abbiamo due cartelle uguali (daily0 e daily1), ma daily1 occupa molto meno spazio di daily0. Una cancellazione di un file in daily0 non coinvolge la cancellazione del file in daily1, dal momento che il filesystem conserva una copia del file fintanto che tutti gli hard-link non sono stati cancellati. È il momento di rsync, che realizza una sincronizzazione di daily0 con il filesystem da backupare. Tutti i file modificati nel filesystem di partenza sono cancellati in daily0 e riscritti con le nuove modifiche, ma una copia della vecchia versione rimane in daily1, dal momento che rimane ancora un hard-link che punta alla versione non modificata. Il file sarà effettivamente modificato in tutti gli snapshot quando sarà passato l'intero arco temporale coperto dalla configurazione di rsnapshot.

Un punto di forza importante è che questo sistema permette il backup sia locale che remoto. Il backup remoto viene realizzato in modalità push (rispetto al sistema remoto), incapsulando il traffico dati in una connessione ssh, per cui è estremamente sicuro. Possiamo realizzare il backup giornaliero del nostro portatile e anche dei nostri server sparsi in giro in tutta tranquillità.

Questo sistema io lo uso da anni e non ho mai avuto problemi. È chiaro che non si tratta di un sistema per il backup sofisticato come quello di bacula, ad esempio, ma è estremamente flessibile e semplice e può essere indicato in diverse situazioni:

Il backup di sistemi Windows non è un problema: basta montare la cartella da backupare via samba sul server linux prima di lanciare rsnapshot.

Nel proseguo di questo paragrafo userò la seguente terminologia: con "sistema locale" farò riferimento al server di backup, ovvero il sistema che contiene gli snapshot; per "sistema remoto" si intenderà il sistema da backupare.

  1. Iniziamo con la installazione del software. Sul sistema locale installiamo rsnapshot; il sistema di pacchetti apt installerà anche tutta una serie di dipendenze necessarie:

    aptitude install rsnapshot

    Sul sistema remoto basta installare:

    aptitude install sudo rsync

  2. C'è una questione importante: come abbiamo detto il backup remoto avviene attraverso una sessione ssh, ma il server ssh ci chiederà una password per consentire l'accesso. Per evitarlo, bisogna generare una chiave e configurare entrambi i sistemi in modo che le credenziali di accesso vengano garantite attraverso la chiave e non la password. Per cominciare, su tutti i sistemi remoti da backupare creiamo un utente rsnapshot senza password e appartenente a un gruppo con lo stesso nome.

  3. Nel computer locale generiamo la chiave ssh, senza password, per l'accesso al sistema remoto:

    cd /root/.ssh
    ssh-keygen -t rsa

    come si vede, la chiave viene generata nella home directory dell'utente root, che è l'utente che lancerà il processo di backup. Vengono creati due file: id_rsa con la chiave privata e id_rsa.pub con quella pubblica.

  4. Copiamo la chiave id_rsa.pub in tutti i sistemi remoti soggetti a backup, salvandola all'interno della home dell'utente rsnapshot appena creato:

    scp id_rsa.pub rsnapshot@server.dominio:/home/rsnapshot/.ssh

  5. Aggiungiamo la chiave al file authorized_keys, copiando il contenuto del file id_rsa.pub dopo la stringa from="server.backup". Il file authorized_keys diventa quindi:

    from="server.backup" (contenuto del file 'id_rsa.pub')

    In questo modo è permesso il collegamento ssh solo da quell'ip, senza password e usando la chiave. È anche possibile aggiungere il comando che sarà possibile eseguire da remoto, se si vuole aumentare ancora la sicurezza.

  6. Il programma rsync viene lanciato dall'utente rsnapshot che, quindi, deve disporre dei permessi di root per poter accedere e fare il backup di cartelle di sistema e di altri utenti. In breve, è necessario lanciare rsync tramite sudo, ma questo crea un problema, dal momento che non è possibile richiamare da remoto il comando sudo rsync. Per risolvere il problema, si crea uno wrapper in /usr/local/bin/rsync:

    #!/bin/sh
    sudo rsync_real "$@"

    di seguito rinominiamo il file rsync originale come rsync_real:

    mv /usr/bin/rsync /usr/bin/rsync_real

    In questo modo, la procedura di backup remoto chiamerà rsync che non è altro che uno wrapper al vero rsync (adesso rsync_real) che però, viene chiamato con sudo.

  7. Abbiamo finito l'accesso ssh da remoto per il backup. Adesso vediamo la configurazione di rsnapshot. Le direttive importanti in /etc/rsnapshot.conf sono le seguenti:

    ###########################
    # SNAPSHOT ROOT DIRECTORY #
    ###########################
    # All snapshots will be stored under this root directory.
    #
    snapshot_root   /mnt/backup/ 
     
    # If no_create_root is enabled, rsnapshot will not automatically create the
    # snapshot_root directory. This is particularly useful if you are backing
    # up to removable media, such as a FireWire or USB drive.
    #
    no_create_root  1 
     
    ... 
     
    #########################################
    #           BACKUP INTERVALS            #
    # Must be unique and in ascending order #
    # i.e. hourly, daily, weekly, etc.      #
    #########################################
    # The interval names (hourly, daily, ...) are just names and have no influence
    # on the length of the interval. The numbers set the number of snapshots to
    # keep for each interval (hourly.0, hourly.1, ...).
    # The length of the interval is set by the time between two executions of
    # rsnapshot <interval name>, this is normally done via cron.
    # Feel free to adapt the names, and the sample cron file under /etc/cron.d/rsnapshot
    # to your needs. The only requirement is that the intervals must be listed
    # in ascending order. To activate just uncomment the entries.
    #interval       hourly  6
    interval        daily   14
    interval        weekly  8
    interval        monthly 6 
     
    ###############################
    ### BACKUP POINTS / SCRIPTS ###
    ###############################
    # LOCALHOST
    backup  /home/                  saturno/
    backup  /etc/                   saturno/
    backup  /var/www/               saturno/
    backup  /var/log/               saturno/
    backup  /root/                  saturno/
    backup_script           /usr/local/bin/mysqlbackup.pl   saturno/var/lib/mysql/ 
     
    # BACKUP REMOTO
    backup  rsnapshot@server.dominio:/etc/                            server/
    backup  rsnapshot@server.dominio:/home/                   server/

    che fa un backup del server locale e di quello remoto per 14 giorni, 8 settimane e 6 mesi. All'interno della cartella contenente il backup di ciascun periodo temporale, troveremo delle sottocartelle contenenti il backup di ciascun server. I commenti del file di configurazione sono abbastanza chiarificatori.

  8. L'ultimo punto è lo schedulamento dei 3 processi (giornaliero, settimanale e mensile). Si può inserire il seguente script in /etc/cron.d:

0 20 2-6,8-13,15-20,22-27,29-31 * * root /usr/bin/rsnapshot daily
0 20 7,14,21,28 * * root /usr/bin/rsnapshot weekly
0 20 1 * * root /usr/bin/rsnapshot monthly

Conclusione e una proposta

Abbiamo finito. Spero che il taglio dato a questo articolo e le informazioni in esso contenute possano essere considerate di interesse. Sono rimaste in sospeso molte cose interessanti, tra tutte, la configurazione del TLS e l'autenticazione SMTP in postfix, ma anche l'integrazione con altri programmi, come mailman.

Sarebbe bello se queste note potessero essere integrate nel tempo con nuove informazioni, che coprissero la configurazione di servizi non considerati in questo articolo o le variazioni relative all'evoluzione del software. Quindi, lo lancio come proposta: un documento da estendere e integrare nel tempo da più persone, per quanto riguarda la configurazione di un server Linux, e che serva da compendio per tutta una serie di risorse sparpagliate in Rete.

Attendo tanti vostri contatti.



L'autore

Francisco Yepes Barrera lavora da anni offrendo consulenza come sistemista e programmatore su piattaforme libere. Parte del suo lavoro si centra nella soluzione di problemi in ambito scientifico-computazionale usando Software Libero.




Sinistra <- Mono - Indice Generale - Copertina - Maven: accumulator of knowledge -> Destra