Serwer poczty na FreeBSD 13 (cz. 6): Postfix (SMTP) i PostfixAdmin
POP3/IMAP mamy gotowe (część 5). Czas na Postfix — serwer SMTP, który przyjmuje i przekazuje pocztę. Połączymy go z Dovecotem (SASL), TLS, oraz z bazą MySQL (domeny i skrzynki wirtualne). Na koniec postawimy PostfixAdmin do zarządzania domenami i kontami z poziomu WWW.
📅 Wersje z epoki (2021). Pliki mysql_*.cf widoczne są na zrzutach (1:1 z projektu). Listy RBL i opcje TLS dostosuj do aktualnych zaleceń przy wdrożeniu.
Przygotowanie
Postfix został zainstalowany razem z pakietem Maia‑Mailguard (część 5). Najpierw zatrzymujemy i wyłączamy sendmail:

W /etc/rc.conf wyłączamy sendmaila i włączamy Postfix przy starcie systemu:


Tworzymy certyfikat SSL dla SMTP i zabezpieczamy pliki przed odczytem przez niepowołanych użytkowników:

Konfiguracja main.cf
Do /usr/local/etc/postfix/main.cf dodajemy ustawienia — SASL (uwierzytelnianie przez Dovecot), restrykcje antyspamowe (RBL), TLS oraz mapy MySQL:
soft_bounce = no
# SASL CONFIG
broken_sasl_auth_clients = yes
smtpd_delay_reject = yes
smtpd_helo_required = yes
smtpd_helo_restrictions =
permit_mynetworks, permit_sasl_authenticated,
reject_invalid_hostname, reject_unknown_hostname,
reject_non_fqdn_hostname, reject_non_fqdn_helo_hostname,
reject_invalid_helo_hostname, permit
smtpd_sender_restrictions =
permit_mynetworks, permit_sasl_authenticated,
reject_non_fqdn_sender, reject_unknown_sender_domain,
reject_unlisted_sender, permit
smtpd_relay_restrictions = permit_mynetworks permit_sasl_authenticated defer_unauth_destination
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,
reject_rbl_client bl.spamcop.net,
reject_rbl_client sbl-xbl.spamhaus.org,
reject_rbl_client zen.spamhaus.org,
reject_rbl_client dnsbl.sorbs.net,
reject_rbl_client rhsbl.sorbs.net,
reject_rbl_client db.wpbl.info,
reject_rbl_client cbl.abuseat.org,
reject_rbl_client proxies.blackholes.wirehub.net,
reject_rbl_client query.bondedsender.org
permit
smtpd_sasl_auth_enable = yes
smtpd_sasl_authenticated_header = yes
smtpd_sasl_local_domain = $myhostname
smtpd_sasl_security_options = noanonymous
smtpd_sasl_type = dovecot
smtpd_sasl_path = private/auth
# TLS CONFIG
smtp_use_tls = yes
smtpd_use_tls = yes
smtp_tls_note_starttls_offer = yes
smtpd_tls_key_file = /usr/local/etc/ssl/postfix/smtpd.pem
smtpd_tls_cert_file = /usr/local/etc/ssl/postfix/smtpd.pem
smtpd_tls_CAfile = /usr/local/etc/ssl/postfix/smtpd.pem
smtpd_tls_loglevel = 0
smtpd_tls_received_header = yes
smtpd_tls_session_cache_timeout = 3600s
smtpd_tls_mandatory_protocols = !SSLv2,!SSLv3
tls_random_source = dev:/dev/urandom
# MySQL Configuration
virtual_alias_maps = proxy:mysql:/usr/local/etc/postfix/mysql_virtual_alias_maps.cf
virtual_gid_maps = static:125
virtual_mailbox_base = /usr/local/virtual
virtual_mailbox_domains = proxy:mysql:/usr/local/etc/postfix/mysql_virtual_domains_maps.cf
virtual_mailbox_limit = 51200000
virtual_mailbox_maps = proxy:mysql:/usr/local/etc/postfix/mysql_virtual_mailbox_maps.cf
virtual_minimum_uid = 125
virtual_transport = dovecot
virtual_uid_maps = static:125
# Additional for quota support
virtual_mailbox_limit_maps = proxy:mysql:/usr/local/etc/postfix/mysql_virtual_mailbox_limit_maps.cf
maximal_queue_lifetime = 1d
bounce_queue_lifetime = 1d
message_size_limit = 25600000
myhostname = projekt.brylka.net
mydomain = projekt.brylka.net
mydestination = localhost.$mydomain, localhost
relay_domains = proxy:mysql:/usr/local/etc/postfix/mysql_relay_domains_maps.cf
relay_recipient_maps = proxy:mysql:/usr/local/etc/postfix/mysql_virtual_mailbox_maps.cf
dovecot_destination_recipient_limit = 1
Konfiguracja master.cf
Do /usr/local/etc/postfix/master.cf dodajemy usługi submission (587), smtps (465) oraz transport dovecot:
submission inet n - n - - smtpd
-o smtpd_sasl_auth_enable=yes
-o smtpd_tls_auth_only=yes
-o smtpd_sender_restrictions=permit_sasl_authenticated,reject
-o smtpd_recipient_restrictions=permit_sasl_authenticated,reject
-o smtpd_relay_restrictions=permit_sasl_authenticated,reject
smtps inet n - n - - smtpd
-o smtpd_tls_wrappermode=yes
-o smtpd_sasl_auth_enable=yes
-o smtpd_sender_restrictions=permit_sasl_authenticated,reject
-o smtpd_recipient_restrictions=permit_sasl_authenticated,reject
-o smtpd_relay_restrictions=permit_sasl_authenticated,reject
dovecot unix - n n - - pipe
flags=DRhu user=vscan:vscan argv=/usr/local/libexec/dovecot/deliver -f ${sender} -d ${recipient}
Mapy MySQL
Tworzymy pliki obsługujące połączenia z bazą i zapytania (alias, domeny, skrzynki, limity, relay). Ich zawartość widać na zrzutach:





Nadajemy plikom odpowiednie prawa (ochrona przed odczytem przez niepowołanych):


PostfixAdmin
PostfixAdmin również zainstalował się z pakietem Maia‑Mailguard.

W pliku /usr/local/www/postfixadmin/config.local.php ustawiamy połączenie z bazą i parametry systemu:
<?php
$CONF['configured'] = true;
$CONF['setup_password'] = 'hasło';
$CONF['database_type'] = 'mysqli';
$CONF['database_host'] = 'localhost';
$CONF['database_user'] = 'postfix';
$CONF['database_password'] = 'hasło';
$CONF['database_name'] = 'postfix';
$CONF['admin_email'] = 'brylka@projekt.brylka.net';
$CONF['smtp_server'] = 'localhost';
$CONF['smtp_port'] = '25';
$CONF['encrypt'] = 'md5crypt';
$CONF['dovecotpw'] = "/usr/sbin/doveadm pw";
$CONF['page_size'] = '50';
$CONF['default_aliases'] = array(
'abuse' => 'abuse@projekt.brylka.net',
'hostmaster' => 'hostmaster@projekt.brylka.net',
'postmaster' => 'postmaster@projekt.brylka.net',
'webmaster' => 'webmaster@projekt.brylka.net'
);
$CONF['domain_path'] = 'NO';
$CONF['domain_in_mailbox'] = 'YES';
$CONF['aliases'] = '50';
$CONF['mailboxes'] = '50';
$CONF['maxquota'] = '102400';
$CONF['domain_quota_default'] = '1024000';
$CONF['quota'] = 'YES';
$CONF['domain_quota'] = 'YES';
$CONF['quota_multiplier'] = '1048576';
$CONF['transport'] = 'NO';
$CONF['vacation'] = 'YES';
$CONF['vacation_domain'] = 'autoreply.projekt.brylka.net';
$CONF['vacation_control'] = 'YES';
$CONF['vacation_control_admin'] = 'YES';
$CONF['alias_control'] = 'YES';
$CONF['alias_control_admin'] = 'YES';
$CONF['emailcheck_resolve_domain'] = 'NO';
?>
Dodajemy konfigurację PostfixAdmin do Apache i przeładowujemy serwer:


Wchodzimy na https://projekt.brylka.net/postfixadmin/setup.php, gdzie sprawdzana jest konfiguracja, i zakładamy konto administratora systemu pocztowego:

Usuwanie kont (sudo) i autoresponder (vacation)
Instalujemy sudo, by móc usuwać użytkowników wraz z czyszczeniem katalogów:
portmaster -dG security/sudo




Tworzymy użytkownika i grupę vacation (autoresponder), katalogi i prawa:


W /var/spool/vacation/vacation.pl ustawiamy połączenie z bazą:
our $db_type = 'mysqli';
our $db_host = 'localhost';
our $db_username = 'postfix';
our $db_password = 'hasło';
our $db_name = 'postfix';
our $vacation_domain = 'autoreply.projekt.brylka.net';
our $smtp_ssl = '';
our $logfile = "/var/log/vacation.log";
our $log_level = 0;
our $log_to_file = 1;
Dodajemy transport vacation do master.cf:
vacation unix - n n - - pipe
flags=DRhu user=vacation argv=/var/spool/vacation/vacation.pl -f ${sender} ${recipient}

Na koniec tworzymy plik transport i aktualizujemy tabelę Postfixa (postmap):

Co dalej
W części 7 konfigurujemy ochronę poczty: SpamAssassin + ClamAV oraz webowy panel kwarantanny Maia‑Mailguard.