Spis treści
Poczta w Jailu
Założenia:
- web frontend
- obsługa wielu domen
- obsługa anty-spamu
- obsługa RBL-i
- grey listing
- obsługa SPF
- quota
Oprogramowanie:
- postfix
- postfixadmin
- roundcube
Przygotowania
Poniższy opis zakłada istnienie własnego repozytorium ze skompliwanym postfix-em oraz dovecote-em z opcją wsparcia MySQL-a.
Dodatkowo, wymagany będzie użytkownik vmail:
pw useradd -n vmail -u 1001 -c "VMail User" -d /var/mail/vmail -s /sbin/nologin
Postfix - cz. I
Instalacja
Instalacja pakietów:
pkg install postfix
Ustawiamy /etc/mail/mailer.conf
sendmail /usr/local/sbin/sendmail send-mail /usr/local/sbin/sendmail mailq /usr/local/sbin/sendmail newaliases /usr/local/sbin/sendmail
Wyłączamy taski periodic dotyczące sendmaila w pliku /etc/periodic.conf:
daily_clean_hoststat_enable="NO" daily_status_mail_rejects_enable="NO" daily_status_include_submit_mailq="NO" daily_submit_queuerun="NO"
Włączamy postfixa:
echo postfix_enable=\"YES\" > /etc/rc.conf.d/postfix service postfix start
Konfiguracja
W pliku /usr/local/etc/postfix/main.cf zmieniamy:
myhostname = poczta.domain.name <----- w zależności od rev-dns mydestination = $myhostname, localhost.$mydomain, localhost
Oraz dodajemy obsługę TLS:
# TLS (incoming)
smtpd_use_tls = yes
smtpd_tls_auth_only = yes
smtpd_tls_loglevel = 1
smtpd_tls_key_file = /etc/ssl/klucz.key
smtpd_tls_cert_file = /etc/ssl/certyfikat.crt
smtpd_tls_CAfile = /etc/ssl/cert.pem
smtpd_tls_received_header = yes
smtpd_tls_security_level = may
smtpd_tls_session_cache_database = btree:${data_directory}/smtpd_scache
smtpd_tls_session_cache_timeout = 3600s
smtpd_tls_mandatory_protocols=!SSLv2,!SSLv3
smtpd_tls_protocols=!SSLv2,!SSLv3
# TLS (outgoing)
smtp_use_tls = yes
smtp_tls_security_level = may
smtp_tls_note_starttls_offer = yes
smtp_tls_loglevel = 1
smtp_tls_CAfile = /etc/ssl/cert.pem
smtp_tls_mandatory_protocols=!SSLv2,!SSLv3
smtp_tls_protocols=!SSLv2,!SSLv3
smtp_tls_session_cache_database = btree:${data_directory}/smtp_scache
Przygotowujemy obsługę SASL-a przez dovecot-a (będzie wykorzystana przy połączeniach na port 587):
# Dovecot-SASL smtpd_sasl_type = dovecot smtpd_sasl_path = private/auth smtpd_sasl_auth_enable = no broken_sasl_auth_clients = yes
Oraz włączamy port 587 w /usr/local/etc/postfix/master.cf:
submission inet n - n - - smtpd -o syslog_name=postfix/submission -o smtpd_tls_security_level=encrypt -o smtpd_sasl_auth_enable=yes -o smtpd_reject_unlisted_recipient=no # -o smtpd_client_restrictions=$mua_client_restrictions # -o smtpd_helo_restrictions=$mua_helo_restrictions # -o smtpd_sender_restrictions=$mua_sender_restrictions -o smtpd_recipient_restrictions= -o smtpd_relay_restrictions=permit_sasl_authenticated,reject -o milter_macro_daemon_name=ORIGINATING
Postfixadmin + nginx + php-fpm
Instalacja
Instalacja z paczek:
pkg install postfixadmin php56-mysqli php56-imap nginx
Konfiguracja
nginx
Do /usr/local/etc/nginx/nginx.conf dodajemy na końcu (przed ostatnią klamrą):
# VHosts include /usr/local/etc/nginx/conf.d/*.conf;
Tworzymy brakujące katalogi:
mkdir -p /usr/local/etc/nginx/conf.d /var/log/nginx
Konfiguracja serwera w pliku /usr/local/etc/nginx/conf.d/postfixadmin.conf:
server {
	listen 80;
	server_name postfixadmin.domena.com; 
	root	/usr/local/www/postfixadmin;
  	index	index.php;
	access_log	/var/log/nginx/postfixadmin.access.log;
	error_log	/var/log/nginx/postfixadmin.error.log;
	location ~ \.php$ {
		try_files $uri = 404;
		include fastcgi_params;
                fastcgi_pass unix:/var/run/php5-fpm.sock;
		fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
	}
}
Włączenie nginx-a:
echo nginx_enable=\"YES\" > /etc/rc.conf.d/nginx service nginx start
php-fpm
PHP instaluje się jako zależność przy instalacji postfixadmin-a. 
W pliku /usr/local/etc/php-fpm.conf zmieniamy:
listen = 127.0.0.1:9000
Na:
listen = /var/run/php5-fpm.sock listen.owner = www listen.group = www listen.mode = 0660
Kopiujemy domyślną konfigurację php.ini:
cd /usr/local/etc cp php.ini-production php.ini
Włączamy PHP-FPM:
echo php_fpm_enable=\"YES\" > /etc/rc.conf.d/php_fpm service php-fpm start
Postfixadmin
Tworzenie bazy danych w MySQL:
CREATE DATABASE postfix; CREATE USER 'postfix'@'localhost' IDENTIFIED BY 'choose_a_password'; GRANT ALL PRIVILEGES ON `postfix` . * TO 'postfix'@'localhost';
Tworzymy plik config.local.php:
<?php
$CONF['database_host'] = '192.168.0.2';
$CONF['database_type'] = 'mysqli';
$CONF['database_user'] = 'postfix';
$CONF['database_password'] = 'ua0eechoeceiQu2U';
$CONF['database_name'] = 'postfix';
$CONF['configured'] = true;
$CONF['default_aliases'] = array (
    'abuse' => 'konto@domena.com',
    'hostmaster' => 'konto@domena.com',
    'postmaster' => 'konto@domena.com',
    'webmaster' => 'konto@domena.com'
);
$CONF['show_footer_text'] = 'YES';
$CONF['footer_text'] = 'Return to poczta.domena.com';
$CONF['footer_link'] = 'https://poczta.domena.com';
// Quota
// When you want to enforce quota for your mailbox users set this to 'YES'.
$CONF['quota'] = 'YES';
// If you want to enforce domain-level quotas set this to 'YES'.
$CONF['domain_quota'] = 'YES';
// You can either use '1024000' or '1048576'
$CONF['quota_multiplier'] = '1048576';
?>
Uruchamiamy w przeglądarce adres serwera: http://adres.domena.com/setup.php , sprawdzamy czy wszystko jest OK, po czym ustalamy hasło na przyszłość (strona jest wykorzystywana po upgradzie w przyszłości). Strona wygeneruje hash hasła, który należy dopisać do config.local.php.
Po odświeżeniu strony ustalamy użytkownika i hasło super admina.
Dovecot - cz. I
Instalujemy paczkę:
pkg install dovecot2
Następnie w katalogu /usr/local/etc/dovecot tworzymy pliki do obsługi MySQL:
- dovecot-dict-sql-user.conf
connect = host=localhost dbname=postfix user=postfix password=password
 
map {
  pattern = priv/quota/storage
  table = quota2
  username_field = username
  value_field = bytes
}
map {
  pattern = priv/quota/messages
  table = quota2
  username_field = username
  value_field = messages
}
- dovecot-dict-sql-domain.conf
connect = host=localhost dbname=postfix user=postfix password=password
 
map {
    pattern = priv/quota/storage
    table = domain
    username_field = domain
    value_field = quota
}
 
map {
    pattern = priv/quota/messages
    table = quota2
    username_field = username
    value_field = messages
}
- dovecot-sql.conf
connect = host=localhost dbname=postfix user=postfix password=password
driver = mysql
default_pass_scheme = MD5-CRYPT
 
user_query = SELECT CONCAT('/var/mail/vmail/',maildir) as home, \
                    CONCAT('maildir:/var/mail/vmail/',maildir) as mail, \
                    CONCAT('*:bytes=', \
                     IF(mailbox.quota = 0, domain.maxquota*1024000, mailbox.quota)) \
                    as quota_rule, \
		    1001 AS uid, \
		    1001 AS gid \
             FROM mailbox, domain \
             WHERE username = '%u' AND mailbox.active = '1' AND \
                   domain.domain = '%d' AND domain.active = '1'
 
password_query = SELECT username as user, password, \
                        CONCAT('/var/mail/vmail/',maildir) AS userdb_home, \
                        CONCAT('maildir:/var/mail/vmail/',maildir) AS userdb_mail \
                 FROM mailbox WHERE username = '%u' AND active = '1'
                 
iterate_query = SELECT username FROM mailbox
Następnie tworzymy główną konfigurację Dovecot-a:
log_path = syslog
syslog_facility = local0
mail_location = maildir:/var/mail/vmail/%d/%n/
mailbox_list_index = yes
namespace inbox {
  inbox = yes
  mailbox Trash {
    auto = no
    special_use = \Trash
    autoexpunge = 31d
  }
  mailbox Drafts {
    auto = no
    special_use = \Drafts
  }
  mailbox Sent {
    auto = subscribe
    special_use = \Sent
  }
  mailbox "Sent Messages" {
    auto = no
    special_use = \Sent
  }
  mailbox Junk {
    auto = create
    special_use = \Junk
    autoexpunge = 14d
  }
}
protocols = "imap lmtp"
# change to 'no' if you don't have ssl cert/keys, and comment out ssl_cert/ssl_key
ssl = yes
ssl_min_protocol = TLSv1
ssl_dh = </usr/local/etc/dovecot/dh.pem
ssl_cert = </etc/ssl/certyfikat.crt
ssl_key = </etc/ssl/klucz.key
service auth {
        unix_listener /var/spool/postfix/private/auth {
        mode = 0660
        user = postfix
        group = postfix
        }
}
# login is for outlook express smtpd auth
auth_mechanisms = plain login
# Needs to match Postfix virtual_uid_maps
first_valid_uid = 1001 
# allow plaintext auth (change to 'yes' to block plaintext passwords)
disable_plaintext_auth = yes
mail_plugins = $mail_plugins quota
 
userdb {
    args = /usr/local/etc/dovecot/dovecot-sql.conf
    driver = sql
}
 
passdb {
    args = /usr/local/etc/dovecot/dovecot-sql.conf
    driver = sql
}
 
service dict {
    unix_listener dict {
        mode = 0600
        user = vmail
    }
}
 
service quota-status {
	executable = quota-status -p postfix
	unix_listener quota-status {
		mode = 0660
		user = dovecot
		group = mail
	}
	client_limit = 1
}
protocol imap {
    mail_plugins = $mail_plugins imap_quota
}
 
protocol lmtp {
  postmaster_address = root@domena.com
  mail_plugins = $mail_plugins
}
plugin {
    # Using SQL Tables to store current quota size
    quota = dict:Quota:%d:proxy::sqldomainquota
    quota = dict:User Quota::proxy::sqluserquota
 
    # Allow 10% more for Trash Folder
    quota_rule2 = Trash:storage=+10%%
    
    # Przepuszczaj dalej checki, jesli quota OK lub brak usera
    quota_status_success = DUNNO
    quota_status_nouser = DUNNO
}
 
dict {
    sqluserquota = mysql:/usr/local/etc/dovecot/dovecot-dict-sql-user.conf
    sqldomainquota = mysql:/usr/local/etc/dovecot/dovecot-sql-domain.conf
}
Generujemy DH:
dd if=/var/db/dovecot/ssl-parameters.dat bs=1 skip=88 | openssl dhparam -inform der > /usr/local/etc/dovecot/dh.pem
Dodajemy regułę do /etc/syslog.conf:
local0.* /var/log/dovecot.log
Oraz rotowanie logów do /usr/local/etc/newsyslog.conf.d/dovecot:
# logfilename [owner:group] mode count size when flags [/pid_file] [sig_num] /var/log/dovecot 640 30 * @T00 JC
Uruchamiamy dovecot-a i restartujemy syslog-a:
echo dovecot_enable=\"YES\" > /etc/rc.conf.d/dovecot service syslogd restart service dovecot start
Postfix - cz. II - MySQL
Podłączamy postfix-a do MySQL-a. Tworzymy katalog:
mkdir -p /usr/local/etc/postfix/sql
Oraz tworzymy w nim pliki:
- mysql_virtual_alias_maps.cf
user = postfix password = password hosts = localhost dbname = postfix query = SELECT goto FROM alias WHERE address='%s' AND active = '1' #expansion_limit = 100
- mysql_virtual_alias_domain_maps.cf
user = postfix
password = password
hosts = localhost
dbname = postfix
query = SELECT goto FROM alias,alias_domain WHERE alias_domain.alias_domain = '%d' and alias.address = CONCAT('%u', '@', alias_domain.target_domain) AND alias.active = 1 AND alias_domain.active='1'
- mysql_virtual_alias_domain_catchall_maps.cf
user = postfix
password = password
hosts = localhost
dbname = postfix
query  = SELECT goto FROM alias,alias_domain WHERE alias_domain.alias_domain = '%d' and alias.address = CONCAT('@', alias_domain.target_domain) AND alias.active = 1 AND alias_domain.active= '1'
- mysql_virtual_domains_maps.cf
user = postfix password = password hosts = localhost dbname = postfix query = SELECT domain FROM domain WHERE domain='%s' AND active = '1' #query = SELECT domain FROM domain WHERE domain='%s' #optional query to use when relaying for backup MX #query = SELECT domain FROM domain WHERE domain='%s' AND backupmx = '0' AND active = '1' #expansion_limit = 100
- mysql_virtual_mailbox_maps.cf
user = postfix password = password hosts = localhost dbname = postfix query = SELECT maildir FROM mailbox WHERE username='%s' AND active = '1' #expansion_limit = 100
- mysql_virtual_alias_domain_mailbox_maps.cf
user = postfix
password = password
hosts = localhost
dbname = postfix
query = SELECT maildir FROM mailbox,alias_domain WHERE alias_domain.alias_domain = '%d' and mailbox.username = CONCAT('%u', '@', alias_domain.target_domain) AND mailbox.active = 1 AND alias_domain.active='1'
- mysql_virtual_mailbox_limit_maps.cf
user = postfix password = password hosts = localhost dbname = postfix query = SELECT quota FROM mailbox WHERE username='%s' AND active = '1'
Następnie dodajemy do /usr/local/etc/postfix/main.cf obsługę MySQL-a oraz zmieniamy transport LMTP na Dovecot-a:
# Postfixadmin virtual_mailbox_domains = proxy:mysql:/usr/local/etc/postfix/sql/mysql_virtual_domains_maps.cf virtual_uid_maps = static:1001 virtual_gid_maps = static:1001 virtual_alias_maps = proxy:mysql:/usr/local/etc/postfix/sql/mysql_virtual_alias_maps.cf, proxy:mysql:/usr/local/etc/postfix/sql/mysql_virtual_alias_domain_maps.cf, proxy:mysql:/usr/local/etc/postfix/sql/mysql_virtual_alias_domain_catchall_maps.cf virtual_mailbox_maps = proxy:mysql:/usr/local/etc/postfix/sql/mysql_virtual_mailbox_maps.cf, proxy:mysql:/usr/local/etc/postfix/sql/mysql_virtual_alias_domain_mailbox_maps.cf virtual_mailbox_base = /var/mail/vmail # Dovecot virtual_transport = lmtp:unix:/var/run/dovecot/lmtp # Restrykcje smtpd_recipient_restrictions = check_policy_service unix:/var/run/dovecot/quota-status
Postfix - cz. III - SPF
SPF-a obecnie sprawdza Spamassasin (patrz niżej) oraz dodatkowo OpenDMARC.
Postfix - cz. III - RBL
Modyfikujemy plik main.cf w sekcji z restrykcjami:
# Restrykcje
smtpd_recipient_restrictions =
        reject_invalid_hostname,
        reject_non_fqdn_sender,
        reject_non_fqdn_recipient,
        reject_unknown_sender_domain,
        reject_unknown_recipient_domain,
        reject_unauth_pipelining,
        check_policy_service unix:private/policyd-spf,
        check_policy_service unix:/var/run/dovecot/quota-status,
        check_client_access hash:/usr/local/etc/postfix/rbl_override,
        reject_rbl_client zen.spamhaus.org,
        reject_rbl_client bl.spamcop.net,
        reject_rbl_client cbl.abuseat.org
Tworzymy plik z whitelistą /usr/local/etc/postfix/rbl_override, w którym wpisujemy domeny wpuszczane zawsze, np.:
gmail.com OK
Po każdorazowej modyfikacji pliku, należy odświeżyć bazę:
postmap /usr/local/etc/postfix/rbl_override
Spamassassin
Instalujemy paczkę:
pkg install spamassassin p5-DBD-mysql
Następnie zakładamy nową bazę w MySQL:
CREATE DATABASE spamassassin; CREATE USER 'spamassassin'@'localhost' IDENTIFIED BY 'password'; GRANT ALL PRIVILEGES ON `spamassassin` . * TO 'spamassassin'@'localhost';
Importujemy strutury:
cd /usr/local/share/doc/spamassassin/sql mysql -u spamassassin -ppassword spamassassin < awl_mysql.sql mysql -u spamassassin -ppassword spamassassin < bayes_mysql.sql mysql -u spamassassin -ppassword spamassassin < userprefs_mysql.sql
Włączamy pluginy (dopisujemy) w /usr/local/etc/mail/spamassassin/init.pre:
loadplugin Mail::SpamAssassin::Plugin::AWL loadplugin Mail::SpamAssassin::Plugin::Pyzor loadplugin Mail::SpamAssassin::Plugin::Razor2 loadplugin Mail::SpamAssassin::Plugin::SPF
Tworzymy konfigurację w pliku /usr/local/etc/mail/spamassassin/local.cf
report_safe 0 lock_method flock required_score 5.0 use_bayes 1 bayes_auto_learn 1 skip_rbl_checks 1 use_razor2 1 use_pyzor 1 normalize_charset 1 # Userprefs user_scores_dsn DBI:mysql:spamassassin:localhost user_scores_sql_username spamassassin user_scores_sql_password password # AWL auto_whitelist_factory Mail::SpamAssassin::SQLBasedAddrList user_awl_dsn DBI:mysql:spamassassin:localhost user_awl_sql_table awl user_awl_sql_username spamassassin user_awl_sql_password password # Bayes bayes_store_module Mail::SpamAssassin::BayesStore::MySQL bayes_sql_dsn DBI:mysql:spamassassin:localhost bayes_sql_username spamassassin bayes_sql_password password
Wypełniamy tabelę w MySQL wartościami:
mysql -u spamassassin -ppassword spamassassin
INSERT INTO userpref (username, preference, value, prefid) VALUES ('@GLOBAL',  'report_safe', '0', NULL);
INSERT INTO userpref (username, preference, value, prefid) VALUES ('@GLOBAL',  'lock_method', 'flock', NULL);
INSERT INTO userpref (username, preference, value, prefid) VALUES ('@GLOBAL',  'required_score', '5.0', NULL);
INSERT INTO userpref (username, preference, value, prefid) VALUES ('@GLOBAL',  'use_bayes', '1', NULL);
INSERT INTO userpref (username, preference, value, prefid) VALUES ('@GLOBAL',  'bayes_auto_learn', '1', NULL);
INSERT INTO userpref (username, preference, value, prefid) VALUES ('@GLOBAL',  'skip_rbl_checks', '1', NULL);
INSERT INTO userpref (username, preference, value, prefid) VALUES ('@GLOBAL',  'use_razor2', '1', NULL);
INSERT INTO userpref (username, preference, value, prefid) VALUES ('@GLOBAL',  'use_pyzor', '1', NULL);
INSERT INTO userpref (username, preference, value, prefid) VALUES ('@GLOBAL',  'normalize_charset', '1', NULL);
Aktualizujemy i kompilujemy reguły dla Spamassassina:
sa-update sa-compile
 Należałoby rozważyć wrzucenie do cron-a powyższych poleceń
Włączenie Spamassassina:
echo spamd_enable=\"YES\" > /etc/rc.conf.d/spamd spamd_flags=\"-q -x -u spamd --listen /var/run/spamd.sock\" >> /etc/rc.conf.d/spamd service sa-spamd start
Postfix - cz. IV - Integracja ze Spamassissem
Do pliku master.cf dopisujemy filtr do konfiguracji smtp, oraz podłączamy spamassassina:
smtp      inet  n       -       n       -       -       smtpd
  -o content_filter=spamd
spamd   unix    -       n       n       -       -       pipe
  user=spamd argv=/usr/local/bin/spamc -u ${user}@${domain} --socket=/var/run/spamd.sock -e
  /usr/local/sbin/sendmail -oi -f ${sender} ${recipient}
Po czym restarujemy postfixa:
service postfix restart
Sprawdzenie działania:
- pobieramy testowy mail, na który spamassassin reaguje jako SPAM:
wget http://spamassassin.apache.org/gtube/gtube.txt
- wysyłamy testowego maila na nasz serwer:
swaks -4 -f sender@domena.com -t user@nasz_serwer.pl --server nasz_serwer.pl --body ./gtube.txt
W mailu powinniśmy zobaczyć, że spamassassin wykrył SPAM. Nagłówki:
X-Spam-Checker-Version: SpamAssassin 3.4.1 (2015-04-28) on nasz_serwer.pl X-Spam-Flag: YES X-Spam-Level: ************************************************** X-Spam-Status: Yes, score=1000.0 required=5.0 tests=AWL,GTUBE autolearn=no autolearn_force=no version=3.4.1 X-Spam-Report: * 1000 GTUBE BODY: Generic Test for Unsolicited Bulk Email * 0.0 AWL AWL: Adjusted score from AWL reputation of From: address Received-SPF: Pass (sender SPF authorized) identity=helo; client-ip=1.2.3.4; helo=domena.com; envelope-from=sender@domena.com; receiver=user@nasz_serwer.pl
Aktualizacje baz Spamassassina
Tworzymy skrypt /root/bin/sa_update_cron.sh:
#!/bin/sh PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/games:/usr/local/sbin:/usr/local/bin if sa-update -v then sa-compile service sa-spamd restart fi
Oraz dodajemy uruchamianie go w /etc/crontab:
# SA update 15 2 * * * root /root/bin/sa_update_cron.sh
Dovecot - cz. II - filtrowanie
Instalujemy dodatkowy pakiet:
pkg install dovecot-pigeonhole
W konfiguracji dovecot.conf włączamy plugin sieve w protokole LMTP oraz dodajemy opcje pluginu:
protocol lmtp {
  postmaster_address = root@domena.com
  mail_plugins = $mail_plugins sieve
}
...
...
plugin {
    ...
    ...
    
    # Sieve
    sieve = /var/mail/vmail/%d/%n/.dovecot.sieve
    sieve_global_path = /var/lib/dovecot/sieve/default.sieve
    sieve_dir = /var/mail/vmail/%d/%n/sieve/
    sieve_global_dir = /var/lib/dovecot/sieve/
    sieve_before = /var/lib/dovecot/sieve/detect-spam.sieve
}
Zakładamy brakujący katalog:
mkdir -p /var/lib/dovecot/sieve chown vmail:vmail /var/lib/dovecot/sieve
Oraz tworzymy w tym katalogu domyślne filtry w pliku default.sieve, oraz filtr przenoszący SPAM w pliku detect-spam.sieve:
require "fileinto";
if header :contains "X-Spam-Flag" "YES" {
  fileinto "Spam";
}
Na końcu restartujemy dovecota:
service dovecot restart
Postfix - cz. V - Postgrey
Instalujemy paczkę:
pkg install postgrey
Do main.cf w restrykcjach dopisujemy ostatnią linię:
smtpd_recipient_restrictions = reject_invalid_hostname, reject_non_fqdn_sender, reject_non_fqdn_recipient, reject_unknown_sender_domain, reject_unknown_recipient_domain, reject_unauth_pipelining, check_policy_service unix:private/policyd-spf, check_policy_service unix:/var/run/dovecot/quota-status, check_client_access hash:/usr/local/etc/postfix/rbl_override, reject_rbl_client zen.spamhaus.org, reject_rbl_client bl.spamcop.net, reject_rbl_client cbl.abuseat.org check_policy_service unix:/var/run/postgrey.sock
Uruchamiamy postgreya:
echo postgrey_enable=\"YES\" > /etc/rc.conf.d/postgrey postgrey_flags=\"--unix=/var/run/postgrey.sock --delay=900\" >> /etc/rc.conf.d/postgrey service postgrey start
Postfix - cz. VI - Antispoof
Do master.cf na porcie submission (587) dodajemy warunek sprawdzający sendera (reject_sender_login_mismatch):
submission inet n - n - - smtpd -o syslog_name=postfix/submission -o smtpd_tls_security_level=encrypt -o smtpd_sasl_auth_enable=yes -o smtpd_reject_unlisted_recipient=no # -o smtpd_client_restrictions=$mua_client_restrictions # -o smtpd_helo_restrictions=$mua_helo_restrictions -o smtpd_sender_restrictions=reject_sender_login_mismatch -o smtpd_recipient_restrictions= -o smtpd_relay_restrictions=permit_sasl_authenticated,reject -o milter_macro_daemon_name=ORIGINATING
W main.cf definiujemy mapę loginów w postarci wyrażeń Perla:
# Mail antispoof smtpd_sender_login_maps = pcre:/usr/local/etc/postfix/login_maps.pcre
Tworzymy plik /usr/local/etc/postfix/login_maps.pcre:
/^(.*)$/ $1
W przypadku więcej wpisów, plik jest przetwarzany na zasadzie pierwszego dopasowania. Składnia:
- maska_adresów_pola_from kto_może_wysłać
Testowanie wpisanych map:
postmap -f -q adres@domena.com pcre:login_maps.pcre
W odpowiedzi dostaniemy kto może nadawać z w/w adresu.
 
Po każdym modyfikacji tego pliku, należy przeładować postfix-a. 
Tutaj tester PCRE do poćwiczenia: https://regex101.com/
Roundcube
Instalujemy paczki:
pkg install roundcube
Tworzymy nową bazę w MySQL oraz użytkownika:
CREATE DATABASE roundcubemail /*!40101 CHARACTER SET utf8 COLLATE utf8_general_ci */; GRANT ALL PRIVILEGES ON `roundcubemail` . * TO 'roundcube'@'localhost' identified by 'password';
Oraz robimy import struktury:
cd /usr/local/www/roundcube/SQL mysql -u roundcube -ppassword roundcubemail < mysql.initial.sql
W pliku /usr/local/etc/php.ini zmieniamy zmienną:
date.timezone = Europe/Warsaw error_reporting = E_ALL & ~E_NOTICE post_max_size = 50M upload_max_filesize = 50M
Wgrywamy mime.types z apache:
cd /usr/local/www/roundcube/config wget http://svn.apache.org/repos/asf/httpd/httpd/trunk/docs/conf/mime.types
Odpalamy instalator na stronie: http://serwer.domena.com/installer i przechodzimy kolejne kroki. Wygenerowany konfig zapisujemy w /usr/local/www/roundcube/config/config.inc.php, dodając na końcu linię:
$config['mime_types'] = '/usr/local/www/roundcube/config/mime.types';
Pluginy
Kilka ciekawych pluginów do Roundcube (dopisz do config.inc.php):
$config['plugins'] = array('contextmenu', 'managesieve', 'markasjunk2', 'newmail_notifier', 'password', 'sauserprefs', 'userinfo', 'zipdownload');
Część z powyższych dostęna jest z Roundcube, część trzeba doinstalować:
pkg install roundcube-contextmenu roundcube-html5_notifier roundcube-sauserprefs
Wszystkie pluginy znajdują się w /usr/local/www/roundcube/plugins/nazwa_pluginu.
contextmenu
Plugin pokazujący menu kontekstowe pod prawym przycikiem myszy.
Konfiguracja: brak
managesieve
Plugin do zarządzania filtrowanie poczty.
Konfiguracja do /usr/local/www/roundcube/plugins/managesieve/config.inc.php:
$config['managesieve_host'] = 'poczta.mky.waw.pl';
markasjunk2
Plugin, który dodaje przycisk „Spam/Not Spam” w interfejsie Web. Dodatkowo istnieje możliwość uczenia Spamassassina z zaznaczonych maili.
Plugin do pobrania stąd: https://github.com/JohnDoh/Roundcube-Plugin-Mark-as-Junk-2/releases
Konfiguracja:
$config['markasjunk2_learning_driver'] = 'cmd_learn'; $config['markasjunk2_spam_cmd'] = '/usr/local/bin/sa-learn --spam --username=%u %f'; $config['markasjunk2_ham_cmd'] = '/usr/local/bin/sa-learn --ham --username=%u %f';
newmail_notifier
Plugin pokazujący notyfikacje przy nadejściu nowej wiadomości.
Konfiguracja: brak (opcje użytkownika dostępne są w Ustawieniach w panelu Web)
password
Plugin do zmiany hasła z poziomu Roundcube'a.
Konfiguracja:
$config['password_db_dsn'] = 'mysql://postfix:password@localhost/postfix_db'; $config['password_query'] = "UPDATE `mailbox` SET `password` = %c, modified=now() WHERE `username` = %u LIMIT 1";
 UWAGA - bazę i dane logowania podajemy do bazy Postfix'a a nie Roundcube'a.
sauserprefs
Plugin do zarządzania ustawieniami Spamassassina dla użytkowników.
Konfiguracja:
$rcmail_config['sauserprefs_db_dsnw'] = 'mysql://spamassassin:password@localhost/spamassassin_db';
$rcmail_config['sauserprefs_default_prefs'] = array(
                                                                        "required_score" => "5",
                                                                        "rewrite_header Subject" => "",
                                                                        "ok_languages" => "all",
                                                                        "ok_locales" => "all",
                                                                        "fold_headers" => "1",
                                                                        "add_header all Level" => "_STARS(*)_",
                                                                        "use_razor1" => "0",
                                                                        "use_razor2" => "1",
                                                                        "use_pyzor" => "1",
                                                                        "use_dcc" => "1",
                                                                        "use_bayes" => "1",
                                                                        "skip_rbl_checks" => "1",
                                                                        "report_safe" => "0",
                                                                        "bayes_auto_learn" => "1",
                                                                        "bayes_auto_learn_threshold_nonspam" => "0.1",
                                                                        "bayes_auto_learn_threshold_spam" => "12.0",
                                                                        "use_bayes_rules" => "1"
userinfo
Plugin pokazujący informacje o użytkowniku w ustawieniach.
Konfiguracja: brak
zipdownload
Plugin pozwalający pobieranie wielu załączników w postaci archiwum ZIP.
Konfiguracja: brak
Optymalizacja działania
Domyślnie Roundcube nie jest zbyt szybkim frontendem Web. Można wykonać kilka zabiegów, by mu pomóc w jego pracy.
imapproxy
Instalujemy paczkę:
pkg install up-imapproxy
Ustawiamy w /usr/local/etc/imappproxyd.conf:
server_hostname serwer.domena.com listen_port 8143 listen_address 127.0.0.1 syslog_prioritymask LOG_WARNING
Po czym uruchamiamy:
echo imapproxyd_enable=\"YES\" > /etc/rc.conf.d/imapproxyd service imapproxyd start
W Roundcube edytujemy w głównym konfigu w '/usr/local/www/roundcube/config/config.inc.php':
$config['imap_force_caps'] = true; $config['default_host'] = '127.0.0.1'; $config['default_port'] = 8143;
PHP APCu
Instalujemy pakiet:
pkg install pecl-APCu
Oraz restartujemy PHP:
service php-fpm restart
Do konfiguracji Roundcube w '/usr/local/www/roundcube/config/config.inc.php' dopisujemy:
$config['imap_cache'] = 'apc';
