wiki.rockstable.it
  • Comments
  • Immutable Page
  • Menu
    • Navigation
    • RecentChanges
    • FindPage
    • Local Site Map
    • Help
    • HelpContents
    • HelpOnMoinWikiSyntax
    • Display
    • Attachments
    • Info
    • Raw Text
    • Print View
    • Edit
    • Copy Page
    • Load
    • Save
  • Login

Configurations

  • 389-ds

  • amavisd-new

  • ansible

  • Apache2

  • apt-cacher-ng

  • autofs

  • Bareos

  • bind9

  • Chrome

  • Clone

  • Debian

  • DNS

  • dovecot

  • ejabberd

  • filesystems

  • Firefox

  • FirefoxSync

  • freeipa

  • Gutenberg

  • HighAvailability

  • Icinga2

  • IPsec

  • isc-dhcp-server

  • jitsi

  • LetsEncrypt

  • libvirt

  • LaTeX

  • Linux

  • matrix

  • mdadm

  • Microsoft

  • mpd

  • moinmoin

  • munin

  • MySQL

  • Names

  • networking

  • OldGamesOnLinux

  • oneliners

  • Openldap

  • OpenSSL

  • openvswitch

  • OpenWRT

  • oscam

  • pdf2book

  • php5-fpm

  • php7-fpm

  • PostgreSQL

  • postfix

  • PowerDNS

  • QRCode

  • RaspberryPi

  • rspamd

  • roundcube

  • Samba

  • Snapper

  • ssh

  • SteamLink

  • StorCLI

  • Systemd

  • tools

  • vim

  • wireguard

  • x2go

  • xinetd

  • xmonad

Services

  • XMPP

  • Rockstable FTP

Sports

  • Squash

Navigation

  • RecentChanges
  • FindPage
  • HelpContents
Revision 68 as of 2019-12-11 15:58:02
Rockstable Wiki:
  • postfix

postfix

Contents

  1. postfix
    1. Netiquette
    2. Debugging
      1. Important commands
    3. Install
    4. Unix-Permissions
    5. Basics
    6. Compatibility Level
    7. Restrictions
    8. Choose your setup
    9. vmail setup
    10. Crypto
      1. Perfect forward secrecy (PFS)
    11. Makefile
    12. Submission
    13. Postgrey
    14. policy-weightd
      1. Configuration
    15. rspamd
    16. Sender Policy Framwork (SPF)

Netiquette

IETF rfc2142

Debugging

When I had no clue what was going on, i took a look into the logs at a higher debugging level. In case of postfix it's as simple as to add -v to the appropriate line in /etc/postfix/master.cf. In this example smtpd -v.

   1 # ==========================================================================
   2 # service type  private unpriv  chroot  wakeup  maxproc command + args
   3 #               (yes)   (yes)   (no)    (never) (100)
   4 # ==========================================================================
   5 smtp      inet  n       -       y       -       -       smtpd -v

Don't forget to remove it later on.

Important commands

Don't forget about the following commands:

   1 postconf -d   #DEFAULTS
   2 postconf -n   #CHANGED
   3 postmap -q    #QUERY DATABASE FOR KEY
   4 postqueue     #SHOW QUEUE
   5 postqueue -f  #FLUSH/SEND QUEUE
   6 postsuper -d  #DELETE QUEUED EMAIL
   7 db_dump       #SHOW CONTENT OF BERKELEY DBS
   8 

Find and delete a stuck Email by address:

   1 postqueue -j \
   2         |jq -s '.[]|select(.recipients[]|.address=="DST_EMAIL@ADDRESS.TLD")|.queue_id' \
   3         |xargs -L1 postsuper -d

Compare custom config to posfix defaults

   1 #!/bin/bash
   2 #!/bin/bash
   3 # Copyright Rockstable IT 2020
   4 # License: GPLv2+
   5 # Delivered as is, no warranty, no liability,…
   6 
   7 set -o pipefail
   8 
   9 CONF_CURRENT="$(postconf -n)"
  10 while read LINE; do
  11         KEY="$(sed -r 's/^([[:alnum:]_$-]+)\s*=.*$/\1/' <<< "$LINE")"
  12         echo -e "\n= Key: '$KEY' ="
  13         VALUE="$(sed -r 's/.*=\s*([^=]+)$/\1/' <<< "$LINE")"
  14         VALUE="$(fold -s <<< "$VALUE")"
  15         if [ -z "$VALUE" ] || grep -E '=$' <<< "$VALUE"; then
  16                 VALUE="NULL"
  17         fi
  18         echo -e "Current: '$VALUE'"
  19         DEFAULT="$(postconf -d "$KEY" 2>&1 \
  20                 |sed -r 's/.*=\s*([^=]+)$/\1/')"
  21         if grep -E 'unknown parameter' <<< "$DEFAULT"; then
  22                 echo "postconf -d '$KEY' -> warned unknown parameter - custom/typo?"
  23                 DEFAULT="NO DEFAULT"
  24         elif [ -z "$DEFAULT" ] || grep -Eq '=$' <<< "$DEFAULT"; then
  25                 DEFAULT="NULL"
  26         fi
  27         DEFAULT="$(fold -s <<< "$DEFAULT")"
  28         echo -e "Default: '$DEFAULT'"
  29 
  30 done <<< "${CONF_CURRENT}"

Install

   1 aptitude install postfix mailutils 

Unix-Permissions

   1 root@mail /etc/postfix # find /etc/postfix -type f -exec chmod o-rx {} \;
   2 root@mail /etc/postfix # find /etc/postfix/ -type d -exec chmod -v 750 {} \;
   3 der Modus von „/etc/postfix/“ wurde von 0755 (rwxr-xr-x) in 0750 (rwxr-x---) geändert
   4 der Modus von „/etc/postfix/sasl“ wurde von 0755 (rwxr-xr-x) in 0750 (rwxr-x---) geändert
   5 Modus von „/etc/postfix/ldap“ als 0750 (rwxr-x---) erhalten
   6 root@mail /etc/postfix # find /etc/postfix/ -type d -exec chgrp -v postfix {} \;
   7 die Gruppe von „/etc/postfix/“ wurde von root in postfix geändert
   8 die Gruppe von „/etc/postfix/sasl“ wurde von root in postfix geändert
   9 die Gruppe von „/etc/postfix/ldap“ wurde von root in postfix geändert
  10 root@mail /etc/postfix # find /etc/postfix/ -exec chgrp -v postfix {} \;
  11 die Gruppe von „/etc/postfix/“ wurde als postfix erhalten
  12 die Gruppe von „/etc/postfix/sasl“ wurde als postfix erhalten
  13 die Gruppe von „/etc/postfix/sasl/smtpd.conf“ wurde von root in postfix geändert
  14 die Gruppe von „/etc/postfix/postfix-files“ wurde von root in postfix geändert
  15 die Gruppe von „/etc/postfix/postfix-script“ wurde von root in postfix geändert
  16 die Gruppe von „/etc/postfix/post-install“ wurde von root in postfix geändert
  17 die Gruppe von „/etc/postfix/dynamicmaps.cf“ wurde von root in postfix geändert
  18 die Gruppe von „/etc/postfix/master.cf“ wurde von root in postfix geändert
  19 die Gruppe von „/etc/postfix/ldap“ wurde als postfix erhalten
  20 die Gruppe von „/etc/postfix/ldap/mailenabled_distgroups.cf“ wurde von root in postfix geändert
  21 die Gruppe von „/etc/postfix/ldap/virtual_alias_maps_mailforwarding.cf“ wurde von root in postfix geändert
  22 die Gruppe von „/etc/postfix/ldap/transport_maps.cf“ wurde von root in postfix geändert
  23 die Gruppe von „/etc/postfix/ldap/virtual_alias_maps_sharedfolders.cf“ wurde von root in postfix geändert
  24 die Gruppe von „/etc/postfix/ldap/mailenabled_dynamic_distgroups.cf“ wurde von root in postfix geändert
  25 die Gruppe von „/etc/postfix/ldap/local_recipient_maps.cf“ wurde von root in postfix geändert
  26 die Gruppe von „/etc/postfix/ldap/virtual_alias_maps.cf“ wurde von root in postfix geändert
  27 die Gruppe von „/etc/postfix/ldap/mydestination.cf“ wurde von root in postfix geändert
  28 die Gruppe von „/etc/postfix/transport.db“ wurde von root in postfix geändert
  29 die Gruppe von „/etc/postfix/header_checks.inbound“ wurde von root in postfix geändert
  30 die Gruppe von „/etc/postfix/header_checks.inbound.db“ wurde von root in postfix geändert
  31 die Gruppe von „/etc/postfix/header_checks.internal“ wurde von root in postfix geändert
  32 die Gruppe von „/etc/postfix/header_checks.internal.db“ wurde von root in postfix geändert
  33 die Gruppe von „/etc/postfix/header_checks.submission“ wurde von root in postfix geändert
  34 die Gruppe von „/etc/postfix/header_checks.submission.db“ wurde von root in postfix geändert
  35 die Gruppe von „/etc/postfix/transport“ wurde von root in postfix geändert
  36 die Gruppe von „/etc/postfix/main.cf“ wurde von root in postfix geändert

Basics

   1 aptitude install db-util

   1 adduser postfix ssl-cert

Compatibility Level

Postfix 3.0 introduces a safety net that runs Postfix programs with backwards-compatible default settings after an upgrade. The safety net will log a warning whenever a "new" default setting could have an negative effect on your mail flow.

Postfix compares the build in compatibility_level (at compile time) to the one specified in main.cf compatibility_level (default: 0). It determines settings in default state and takes actions if compatibility_level in main.cf is less than compiled in.

Sources:

  • www.postfix.org: COMPATIBILITY README

  • man -P "less -p '^compatibility_level'" 5 postconf

Backwards-compatible default settings that may kick in:

  • kept: append_dot_mydomain=yes - new (3.0): append_dot_mydomain=no

  • kept: chroot=y - new (3.0): chroot=n

  • kept: smtpd_relay_restrictions = (empty) new (2.10): smtpd_relay_restrictions = permit_mynetworks, permit_sasl_authenticated, defer_unauth_destination

  • kept: mynetworks_style=subnet new (3.0): mynetworks_style=host

  • kept: relay_domains=$mydestination new (3.0): relay_domains= -> empty

  • kept: smtputf8_enable=no new (3.0): smtputf8_enable=yes

Restrictions

TODO

   1 

Choose your setup

  • http://www.postfix.org/VIRTUAL_README.html

  • http://www.postfix.org/ADDRESS_CLASS_README.html#local_domain_class

Postfix:

  1. local ALIAS: shared domains, UNIX system accounts
  2. virtual MAILBOX: separate domains, non-UNIX accounts
  3. virtual ALIAS: separate domains, UNIX system accounts

vmail setup

Please prepare dovecot first by foolowing follow dovecot#vmail_setup and return here when done.

/etc/postfix/main.cf

   1 ### ALIASED DOMAINS AND ADDRESSES
   2 ### POINTING TO REMOTE DOMAINS
   3 #virtual_maps = 
   4 virtual_maps = hash:/etc/postfix/virtual
   5 virtual_alias_maps = $virtual_maps
   6 #virtual_alias_domains = $virtual_alias_maps
   7 virtual_alias_domains = hash:/etc/postfix/virtual_alias_domains
   8 
   9 ### MAILBOXED DOMAINS AND ADDRESSES WHERE THIS
  10 ### MTA IS FINAL TARGET
  11 
  12 ### ENSURE virtual_mailbox_maps IS EMPTY
  13 ### OR smtpd_reject_unlisted_recipient (default: yes)
  14 ### WILL ENFORCE EVERY USER TO BE LISTED IN THIS DB
  15 virtual_mailbox_maps = 
  16 #virtual_mailbox_domains = $virtual_mailbox_maps
  17 virtual_mailbox_domains = hash:/etc/postfix/virtual_mailbox_domains
  18 
  19 ### virtual_transport CAN BE OVERRIDDEN BY /etc/postfix/transports
  20 #virtual_transport = virtual
  21 virtual_transport = lmtp:unix:private/dovecot-lmtp
  • Please make sure virtual_mailbox_maps is null otherwise smtpd_reject_unlisted_recipient (default: yes) will enforce that every user is listed in this database.

    • This causes error Recipient address rejected: User unknown in virtual mailbox table; in the most cases.

    • Address verfication is performed by address_verify_virtual_transport = $virtual_transport which is default. And dovecot will answer this question in the lmtp-protocol.

  • Hint:

    • Never list a domain or address in multiple of the following databases at the same time:
      • mydestination

      • relay_domains

      • virtual_alias_domains

      • virtual_mailbox_domains

Address verfiy cache

   1 ### ADDRESS VERIFY CACHE
   2 address_verify_map = btree:$data_directory/verify_cache
   3 #address_verify_negative_cache = yes
   4 address_verify_negative_cache = no
   5 #address_verify_negative_expire_time = 3d
   6 #address_verify_negative_refresh_time = 3h
   7 #address_verify_positive_expire_time = 31d
   8 #address_verify_positive_refresh_time = 7d
   9 address_verify_virtual_transport = $virtual_transport

You can look inside into the verify cache with the following command:

   1 db_dump -p /var/lib/postfix/verify_cache

Crypto

   1 ### IF SYNTAX HIGHLIGHTING IS MISSING:
   2 ## -> "make vim_syntax"
   3 
   4 ciphers_insecure = RC4
   5 cipher_suite_minimum = high
   6 protocols_insecure = !SSLv2,!SSLv3,!TLSv1
   7 tls_security_level = may
   8 
   9 
  10 ### Cipherlists
  11 ##tls_export_cipherlist = aNULL:-aNULL:ALL:+RC4:@STRENGTH
  12 ##tls_high_cipherlist = aNULL:-aNULL:ALL:!EXPORT:!LOW:!MEDIUM:+RC4:@STRENGTH
  13 ##tls_low_cipherlist = aNULL:-aNULL:ALL:!EXPORT:+RC4:@STRENGTH
  14 ##tls_medium_cipherlist = aNULL:-aNULL:ALL:!EXPORT:!LOW:+RC4:@STRENGTH
  15 ##tls_null_cipherlist = eNULL:!aNULL
  16 
  17 
  18 ### LMTP Client
  19 #lmtp_enforce_tls (default: no)
  20 #lmtp_sasl_tls_security_options (default: $lmtp_sasl_security_options)
  21 #lmtp_sasl_tls_verified_security_options (default: $lmtp_sasl_tls_security_options)
  22 #lmtp_starttls_timeout (default: 300s)
  23 #lmtp_tls_CAfile (default: empty)
  24 #lmtp_tls_CApath (default: empty)
  25 #lmtp_tls_block_early_mail_reply (default: empty)
  26 #lmtp_tls_cert_file (default: empty)
  27 #lmtp_tls_ciphers (default: export)
  28 lmtp_tls_ciphers = $cipher_suite_minimum
  29 #lmtp_tls_dcert_file (default: empty)
  30 #lmtp_tls_dkey_file (default: $lmtp_tls_dcert_file)
  31 #lmtp_tls_eccert_file (default: empty)
  32 #lmtp_tls_eckey_file (default: empty)
  33 #lmtp_tls_enforce_peername (default: yes)
  34 #lmtp_tls_exclude_ciphers (default: empty)
  35 lmtp_tls_exclude_ciphers = $ciphers_insecure
  36 #lmtp_tls_fingerprint_cert_match (default: empty)
  37 #lmtp_tls_fingerprint_digest (default: md5)
  38 lmtp_tls_fingerprint_digest = sha1
  39 #lmtp_tls_force_insecure_host_tlsa_lookup (default: no)
  40 #lmtp_tls_key_file (default: $lmtp_tls_cert_file)
  41 #lmtp_tls_loglevel (default: 0)
  42 #lmtp_tls_mandatory_ciphers (default: empty)
  43 lmtp_tls_mandatory_ciphers = $cipher_suite_minimum
  44 #lmtp_tls_mandatory_exclude_ciphers (default: empty)
  45 lmtp_tls_mandatory_exclude_ciphers = $ciphers_insecure
  46 #lmtp_tls_mandatory_protocols (default: !SSLv2)
  47 lmtp_tls_mandatory_protocols  = $protocols_insecure
  48 #lmtp_tls_note_starttls_offer (default: no)
  49 #lmtp_tls_per_site (default: empty)
  50 #lmtp_tls_policy_maps (default: empty)
  51 #lmtp_tls_protocols (default: empty)
  52 lmtp_tls_protocols = $protocols_insecure
  53 #lmtp_tls_scert_verifydepth (default: 9)
  54 #lmtp_tls_secure_cert_match (default: nexthop)
  55 #lmtp_tls_security_level (default: empty)
  56 # possible values:      none, may, encrypt, dane, dane-only,
  57 #                       fingerprint, verify, secure
  58 lmtp_tls_security_level = $tls_security_level
  59 #lmtp_tls_session_cache_database (default: empty)
  60 #lmtp_tls_session_cache_timeout (default: 3600s)
  61 #lmtp_tls_trust_anchor_file (default: empty)
  62 #lmtp_tls_verify_cert_match (default: hostname)
  63 #lmtp_use_tls (default: no) <- deprecaded with 2.3 -> smtpd_tls_security_level
  64 
  65 
  66 ### SMTP Client
  67 #smtp_enforce_tls (default: no)
  68 #smtp_sasl_tls_security_options (default: $smtp_sasl_security_options)
  69 #smtp_sasl_tls_verified_security_options (default: $smtp_sasl_tls_security_options)
  70 #smtp_starttls_timeout (default: 300s)
  71 #smtp_tls_CAfile (default: empty)
  72 #smtp_tls_CApath (default: empty)
  73 #smtp_tls_block_early_mail_reply (default: no)
  74 #smtp_tls_cert_file (default: empty)
  75 #smtp_tls_cipherlist (default: empty) <- obsolete
  76 #smtp_tls_ciphers (default: export)
  77 smtp_tls_ciphers = $cipher_suite_minimum
  78 #smtp_tls_dcert_file (default: empty)
  79 #smtp_tls_dkey_file (default: $smtp_tls_dcert_file)
  80 #smtp_tls_eccert_file (default: empty)
  81 #smtp_tls_eckey_file (default: $smtp_tls_eccert_file)
  82 #smtp_tls_enforce_peername (default: yes)
  83 #smtp_tls_exclude_ciphers (default: empty)
  84 smtp_tls_exclude_ciphers = $ciphers_insecure
  85 #smtp_tls_fingerprint_cert_match (default: empty)
  86 #smtp_tls_fingerprint_digest (default: md5)
  87 smtp_tls_fingerprint_digest = sha1
  88 #smtp_tls_force_insecure_host_tlsa_lookup (default: no)
  89 #smtp_tls_key_file (default: $smtp_tls_cert_file)
  90 #smtp_tls_loglevel (default: 0)
  91 #smtp_tls_mandatory_ciphers (default: medium)
  92 smtp_tls_mandatory_ciphers = $cipher_suite_minimum
  93 #smtp_tls_mandatory_exclude_ciphers (default: empty)
  94 smtp_tls_mandatory_exclude_ciphers = $ciphers_insecure
  95 #smtp_tls_mandatory_protocols (default: !SSLv2)
  96 smtp_tls_mandatory_protocols = $protocols_insecure
  97 #smtp_tls_note_starttls_offer (default: no)
  98 #smtp_tls_per_site (default: empty)
  99 #smtp_tls_policy_maps (default: empty)
 100 #smtp_tls_protocols (default: !SSLv2)
 101 smtp_tls_protocols = $protocols_insecure
 102 #smtp_tls_scert_verifydepth (default: 9)
 103 #smtp_tls_secure_cert_match (default: nexthop, dot-nexthop)
 104 #smtp_tls_security_level (default: empty)
 105 # possible values:      none, may, encrypt, dane, dane-only,
 106 #                       fingerprint, verify, secure
 107 smtp_tls_security_level = $tls_security_level
 108 #smtp_tls_session_cache_database (default: empty)
 109 #smtp_tls_session_cache_timeout (default: 3600s)
 110 #smtp_tls_trust_anchor_file (default: empty)
 111 #smtp_tls_verify_cert_match (default: hostname)
 112 #smtp_use_tls (default: no) <- deprecaded with 2.3 -> smtp_tls_security_level
 113 
 114 
 115 ### SMTPD Server
 116 #smtpd_client_new_tls_session_rate_limit (default: 0)
 117 #smtpd_enforce_tls (default: no)
 118 #smtpd_sasl_tls_security_options (default: $smtpd_sasl_security_options)
 119 #smtpd_starttls_timeout (default: see postconf -d output)
 120 #smtpd_tls_CAfile (default: empty)
 121 #smtpd_tls_CApath (default: empty)
 122 #smtpd_tls_always_issue_session_ids (default: yes)
 123 #smtpd_tls_ask_ccert (default: no)
 124 #smtpd_tls_auth_only (default: no)
 125 #smtpd_tls_ccert_verifydepth (default: 9)
 126 #smtpd_tls_cert_file (default: empty)
 127 #smtpd_tls_cipherlist (default: empty) <- obsolete
 128 #smtpd_tls_ciphers (default: export)
 129 smtpd_tls_ciphers = $cipher_suite_minimum
 130 #smtpd_tls_dcert_file (default: empty)
 131 #smtpd_tls_dh1024_param_file (default: empty)
 132 #smtpd_tls_dh512_param_file (default: empty)
 133 #smtpd_tls_dkey_file (default: $smtpd_tls_dcert_file)
 134 #smtpd_tls_eccert_file (default: empty)
 135 #smtpd_tls_eckey_file (default: $smtpd_tls_eccert_file)
 136 #smtpd_tls_eecdh_grade (default: see postconf -d output)
 137 #smtpd_tls_exclude_ciphers (default: empty)
 138 smtpd_tls_exclude_ciphers = $ciphers_insecure
 139 #smtpd_tls_fingerprint_digest (default: md5)
 140 smtpd_tls_fingerprint_digest = sha1
 141 #smtpd_tls_key_file (default: $smtpd_tls_cert_file)
 142 #smtpd_tls_loglevel (default: 0)
 143 #smtpd_tls_mandatory_ciphers (default: medium)
 144 smtpd_tls_mandatory_ciphers = $cipher_suite_minimum
 145 #smtpd_tls_mandatory_exclude_ciphers (default: empty)
 146 smtpd_tls_mandatory_exclude_ciphers = $ciphers_insecure
 147 #smtpd_tls_mandatory_protocols (default: !SSLv2)
 148 smtpd_tls_mandatory_protocols = $protocols_insecure
 149 #smtpd_tls_protocols (default: none)
 150 smtpd_tls_protocols=$protocols_insecure
 151 #smtpd_tls_received_header (default: no)
 152 #smtpd_tls_req_ccert (default: no)
 153 #smtpd_tls_security_level (default: empty)
 154 # possible values:      none, may, encrypt
 155 smtpd_tls_security_level = $tls_security_level
 156 #smtpd_tls_session_cache_database (default: empty)
 157 #smtpd_tls_session_cache_timeout (default: 3600s)
 158 #smtpd_tls_wrappermode (default: no)
 159 #smtpd_use_tls (default: no) <- deprecaded with 2.3 -> smtpd_tls_security_level

You can delete all these comments in vim to get a clean version by:

   1 :g/^#[^#]/d

   1 ### Customs
   2 ciphers_insecure = RC4
   3 cipher_suite_minimum = high
   4 protocols_insecure = !SSLv2,!SSLv3,!TLSv1
   5 tls_security_level = may
   6 
   7 
   8 ### Cipherlists
   9 ##tls_export_cipherlist = aNULL:-aNULL:ALL:+RC4:@STRENGTH
  10 ##tls_high_cipherlist = aNULL:-aNULL:ALL:!EXPORT:!LOW:!MEDIUM:+RC4:@STRENGTH
  11 ##tls_low_cipherlist = aNULL:-aNULL:ALL:!EXPORT:+RC4:@STRENGTH
  12 ##tls_medium_cipherlist = aNULL:-aNULL:ALL:!EXPORT:!LOW:+RC4:@STRENGTH
  13 ##tls_null_cipherlist = eNULL:!aNULL
  14 
  15 
  16 ### LMTP Client
  17 lmtp_tls_ciphers = $cipher_suite_minimum
  18 lmtp_tls_exclude_ciphers = $ciphers_insecure
  19 lmtp_tls_fingerprint_digest = sha1
  20 lmtp_tls_mandatory_ciphers = $cipher_suite_minimum
  21 lmtp_tls_mandatory_exclude_ciphers = $ciphers_insecure
  22 lmtp_tls_mandatory_protocols  = $protocols_insecure
  23 lmtp_tls_protocols = $protocols_insecure
  24 lmtp_tls_security_level = $tls_security_level
  25 
  26 
  27 ### SMTP Client
  28 smtp_tls_ciphers = $cipher_suite_minimum
  29 smtp_tls_exclude_ciphers = $ciphers_insecure
  30 smtp_tls_fingerprint_digest = sha1
  31 smtp_tls_mandatory_ciphers = $cipher_suite_minimum
  32 smtp_tls_mandatory_exclude_ciphers = $ciphers_insecure
  33 smtp_tls_mandatory_protocols = $protocols_insecure
  34 smtp_tls_protocols = $protocols_insecure
  35 smtp_tls_security_level = $tls_security_level
  36 
  37 
  38 ### SMTPD Server
  39 smtpd_tls_ciphers = $cipher_suite_minimum
  40 smtpd_tls_exclude_ciphers = $ciphers_insecure
  41 smtpd_tls_fingerprint_digest = sha1
  42 smtpd_tls_mandatory_ciphers = $cipher_suite_minimum
  43 smtpd_tls_mandatory_exclude_ciphers = $ciphers_insecure
  44 smtpd_tls_mandatory_protocols = $protocols_insecure
  45 smtpd_tls_protocols=$protocols_insecure
  46 smtpd_tls_security_level = $tls_security_level

Perfect forward secrecy (PFS)

First generate Diffie-Hellmann parameters and return here afterwards: OpenSSL#Generate or renew files with Diffie-Hellman-Parameters

Enable PFS in postfix

Defaults:

   1 smtpd_tls_dh1024_param_file =
   2 smtpd_tls_dh512_param_file =
   3 smtpd_tls_eecdh_grade = auto
   4 tls_eecdh_auto_curves = X25519 X448 prime256v1 secp521r1 secp384r1
   5 tls_eecdh_strong_curve = prime256v1
   6 tls_eecdh_ultra_curve = secp384r1
   7 tlsproxy_tls_dh1024_param_file = $smtpd_tls_dh1024_param_file
   8 tlsproxy_tls_dh512_param_file = $smtpd_tls_dh512_param_file
   9 tlsproxy_tls_eecdh_grade = $smtpd_tls_eecdh_grade

Hardened:

   1 smtpd_tls_dh1024_param_file = /etc/ssl/dhparam/dhparam_512.pem
   2 smtpd_tls_dh512_param_file = /etc/ssl/dhparam/dhparam_1024.pem
   3 smtpd_tls_eecdh_grade = strong

Makefile

Nice trick to save some work - use a Makefile
/etc/postfix/Makefile

   1 postmap:
   2         postmap /etc/postfix/access_client
   3         postmap /etc/postfix/access_helo
   4         postmap /etc/postfix/access_sender
   5         postmap /etc/postfix/access_recipient
   6         postmap /etc/postfix/body_checks
   7         postmap /etc/postfix/esmtp_access
   8         postmap /etc/postfix/header_checks
   9         postmap /etc/postfix/relay_domains
  10         postmap /etc/postfix/virtual
  11         postmap /etc/postfix/transport
  12         newaliases
  13 
  14 vim_syntax:
  15         cat vim_syntax.vim >> /usr/share/vim/vim73/syntax/pfmain.vim

Define a syntax-file to be appended
/etc/postfix/vim_syntax.vim

   1 syntax keyword pfmainConf ciphers_insecure
   2 syntax keyword pfmainConf cipher_suite_minimum
   3 syntax keyword pfmainConf protocols_insecure
   4 syntax keyword pfmainConf tls_security_level
   5 
   6 syntax match pfmainRef "$\<ciphers_insecure\>"
   7 syntax match pfmainRef "$\<cipher_suite_minimum\>"
   8 syntax match pfmainRef "$\<protocols_insecure\>"
   9 syntax match pfmainRef "$\<tls_security_level\>"

   1 make postmap

Submission

Prepare postfix for dovecot submission:

Because dovecot-submissiond binds to tcp/587 we need to add an alternate submission port to /etc/services.

   1 submission-alt  10587/tcp                       # Submission [RFC4409]
   2 

Now we configure /etc/postfix/master.cf to fire up a submission-service bound to localhost.

Postgrey

Wenn eine Email an den Mail-Server versendet zugestellt wird, trägt "postgrey" ein Tripel aus (Client, Sender, Recipient) zusammen mit einem Timestamp in die Datenbank "/var/lib/postgrey/postgrey.db" ein, sollte dieses noch nicht dort zu finden sein. Postgrey versendet einem solchen unbestätigten Client dann ein Return-Code 450 "Try again later". Ist ein konfigurierbares Delay (Default: 300s) erreicht, so ist es dem Client erneut gestattet die Email einzuliefern. Die Datenbank wird standardmäßig von Triplets befreit, zu welchen es seit 35d keinen Kontakt mehr gab. Postgrey stellt Whitelists für clients und recipients bereit.

Ich halte postgrey im Produktivbetrieb für absolut einsetzbar, denn nur die erste Email eines Triplets wird um 5min verzögert.

Evtl. kann das Bereinigungsintervall auf einen höheren Wert gesetzt werden, um seltene Prozesse zu beschleunigen oder interne Server von denen ständig wechselnde Email-Adressen kommt, in die Whitelist eingetragen werden.

About Postgrey

  • postgrey.schweikert.ch

  • www.postfix.org: SMTPD POLICY README

  • www.greylisting.org

  • projects.puremagic.com/greylisting

Configuration

  • Database unter /var/lib/postgrey/postgrey.db

  • Defaults
    • delay: 300s
    • max-age: 35d
    • bind-socket: 127.0.0.1:10023

   1 root@mail /etc/postgrey # cat /etc/default/postgrey
   2 # postgrey startup options, created for Debian
   3 
   4 # you may want to set
   5 #   --delay=N   how long to greylist, seconds (default: 300)
   6 #   --max-age=N delete old entries after N days (default: 35)
   7 # see also the postgrey(8) manpage
   8 
   9 POSTGREY_OPTS="--inet=127.0.0.1:10023"
  10 
  11 # the --greylist-text commandline argument can not be easily passed through
  12 # POSTGREY_OPTS when it contains spaces.  So, insert your text here:
  13 #POSTGREY_TEXT="Your customized rejection message here"
  14 

Inclusion via restriction in /etc/postfix/main.cf

   1 smtpd_recipient_restrictions =
   2         …
   3         check_policy_service inet:127.0.0.1:10023,
   4         …

Whitelists

   1 root@mail /etc/postgrey # ls -1 /etc/postgrey/*
   2 /etc/postgrey/whitelist_clients
   3 /etc/postgrey/whitelist_clients.local
   4 /etc/postgrey/whitelist_recipients
   5 /etc/postgrey/whitelist_recipients.local

Whitelist format for recipient addresses

domain.addr              "domain.addr" domain and subdomains.
name@                    "name@.*" and extended addresses "name+blabla@.*".
name@domain.addr         "name@domain.addr" and extended addresses.
/regexp/                 anything that matches "regexp" (the full address is matched).

Whitelist format for client addresses

domain.addr              "domain.addr" domain and subdomains.
IP1.IP2.IP3.IP4          IP address IP1.IP2.IP3.IP4. You can also leave off one number, in which case only the first specified numbers will be checked.
IP1.IP2.IP3.IP4/MASK     CIDR-syle network. Example: 192.168.1.0/24
/regexp/                 anything that matches "regexp" (the full address is matched).

policy-weightd

policyd-weight(8) is a SMTP policy daemon written in perl(1) for postfix(1). It evaluates based on RBL/RHSBL results, HELO and MAIL FROM domain and subdomain arguments and the client IP address the possibility of forgery or SPAM. It is designed to be called before the SMTP DATA command at the RCPT TO stage. This way it is a) possible to reject a mail attempt before the body has been received and b) to keep multirecipient mail intact, i.e. provide the functionality of selective usage based on recipients.

Configuration

   1 root@mail /etc (git)-[master] # cat /etc/policyd-weight.conf
   2 #policyd-weight  uses  a perl(1) style configuration file which it reads
   3 #on  startup.  The  cache  re-reads  the  configuration  after  $MAINTE‐
   4 #NANCE_LEVEL  (default:  5) queries. If -f is not specified, it searches
   5 #for configuration files on following locations:
   6 
   7 
   8 #CACHE SETTINGS
   9 #       $CACHESIZE (default: 2000)
  10 #              Set the minimum size of the SPAM cache.
  11 #       $CACHEMAXSIZE (default: 4000)
  12 #              Set the maximum size of the SPAM cache.
  13 #       $CACHEREJECTMSG
  14 #              (default: 550 temporarily blocked because of previous errors)"
  15 #              Set the SMTP status code and a explanatory message for  rejected
  16 #              mails due to cached results
  17 #       $NTTL (default: 1)
  18 #              The client is penalized for that many retries.
  19 $NTTL=10;
  20 #       $NTIME (default: 30)
  21 #              The  $NTTL  counter will only be decremented if the client waits
  22 #              at least $NTIME seconds.
  23 $NTIME=5;
  24 #       $POSCACHESIZE (default: 1000)
  25 #              Set the minimum size of the HAM cache.
  26 #       $POSCACHEMAXSIZE (default: 2000)
  27 #              Set the maximum size of the HAM cache.
  28 #       $PTTL (default: 60)
  29 #              After that many queries the  HAM  entry  must  succeed  one  run
  30 #              through the RBL checks again.
  31 #       $PTIME (default: 3h)
  32 #              after  $PTIME in HAM Cache the client must pass one time the RBL
  33 #              checks again.  Values must be nonfractal.  Accepted  time-units:
  34 #              s(econds), m(inutes), h(ours), d(ays)
  35 #       $TEMP_PTIME (default: 1d)
  36 #              The  client  must  pass  this time the RBL checks in order to be
  37 #              listed as hard-HAM. After this time the client will pass immedi‐
  38 #              ately  for  PTTL  within  PTIME.  Values  must  be  non-fractal.
  39 #              Accepted time-units: s(econds), m(inutes), h(ours), d(ays)
  40 
  41 
  42 #DEBUG SETTINGS
  43 #       $DEBUG (default: 0)
  44 #              Turn debugging on (1) or off (0)
  45 
  46 
  47 
  48 #DNS SETTINGS
  49 #       $DNS_RETRIES (default: 2)
  50 #              How many times a single DNS query may be repeated
  51 #       $DNS_RETRY_IVAL (default: 2)
  52 #              Retry a query without response after that many seconds
  53 #       $MAXDNSERR (default: 3)
  54 #              If that many queries fail, the mail is accepted with  $MAXDNSER‐
  55 #              RMSG.
  56 #              In total DNS queries this means: $MAXDNSERR * $DNS_RETRIES
  57 
  58 
  59 #MISC SETTINGS
  60 #       $MAINTENANCE_LEVEL (default: 5)
  61 #              After  that  many  policy requests the cache (and in daemon mode
  62 #              child processes) checks for configuration file changes
  63 #       $MAXIDLECACHE (default: 60)
  64 #              After that many seconds of being idle the cache checks for  con‐
  65 #              figuration file changes.
  66 #       $PIDFILE (default: /var/run/policyd-weight.pid)
  67 #              Path and filename to store the master pid (daemon mode)
  68 #       $LOCKPATH (default: /tmp/.policyd-weight/)
  69 #              Directory   where   policyd-weight   stores  sockets  and  lock-
  70 #              files/directories. Its argument must contain a trailing slash.
  71 #       $SPATH (default: $LOCKPATH.'/polw.sock')
  72 #              Path and filename which the cache has to use for communication.
  73 #       $TCP_PORT (default: 12525)
  74 #              TCP port on which the policy server listens (daemon mode)
  75 #       $BIND_ADDRESS (default: '127.0.0.1')
  76 #              IP Address on which policyd-weight binds. Currently either  only
  77 #              one  or all IPs are supported. Specify 'all' if you want to lis‐
  78 #              ten on all IPs.
  79 #       $SOMAXCONN (default: 1024)
  80 #              Maximum connections which policyd-weight accepts.  This  is  set
  81 #              high enough to cover most scenarios.
  82 #       $USER (default: polw)
  83 #              Set the user under which policyd-weight runs
  84 #       $GROUP (default: $USER)
  85 #              Set the group under which policyd-weight runs
  86 
  87 
  88 #OUTPUT AND LOG SETTINGS
  89 #       $ADD_X_HEADER (default: 1)
  90 #              Insert a X-policyd-weight: header with evaluation messages.
  91 #              1 = on, 0 = off
  92 #       $LOG_BAD_RBL_ONLY (default: 1)
  93 #              Insert  only  RBL  results  in  logging strings if the RBL score
  94 #              changes the overall score. Thus RBLs with  a  GOOD  SCORE  of  0
  95 #              don't appear in logging strings if the RBL returned no BAD hit.
  96 #              1 = on, 0 = off
  97 #       $MAXDNSBLMSG (default: 550 Your MTA is listed in too many DNSBLs)
  98 #              The  message sent to the client if it was reject due to $MAXDNS‐
  99 #              BLHITS and/or $MAXDNSBLSCORE.
 100 #       $REJECTMSG (default: 550 Mail appeared to be SPAM or forged.  Ask  your
 101 #       Mail/DNS-Adminisrator  to  correct  HELO  and DNS MX settings or to get
 102 #       removed from DNSBLs)
 103 #              Set the SMTP status code for rejected mails and  a  message  why
 104 #              the action was taken
 105 
 106 
 107 
 108 #RESOURCE AND OPTIMIZATIONS
 109 #       $CHILDIDLE (default: 120)
 110 #              How  many  seconds  a  child  may be idle before it dies (daemon
 111 #              mode)
 112 #       $MAX_PROC (default: 50)
 113 #              Process limit on how many processes  policyd-weight  will  spawn
 114 #              (daemon mode)
 115 #       $MIN_PROC (default: 2)
 116 #              Minimum child processes which are kept alive in idle times (dae‐
 117 #              mon mode)
 118 #       $PUDP (default: 0)
 119 #              Set persistent UDP connections used for DNS queries  on  (1)  or
 120 #              off (0).
 121 
 122 
 123 
 124 #SCORE SETTINGS
 125 #       Positive values indicate a bad (SPAM) score, negative values indicate a
 126 #       good (HAM) score.
 127 #       @bogus_mx_score (2.1, 0)
 128 #              If the sender domain has neither  MX  nor  A  records  or  these
 129 #              records resolve to a bogus IP-Address (for instance private net‐
 130 #              works) then this check asigns the full score of  bogus_mx_score.
 131 #              If  there  is no MX but an A record of the sender domain then it
 132 #              receives a penalty only if DNSBL-listed.
 133 #              Log Entries:
 134 #              BOGUS_MX
 135 #               The sender A and MX records are bogus or empty.
 136 #              BAD_MX
 137 #               The sender domain has an empty  or  bogus  MX  record  and  the
 138 #               client is DNSBL listed.
 139 #              Related RFCs:
 140 #              [1918] Address Allocation for Private Internets
 141 #              [2821] Simple Mail Transfer Protocol (Sect 3.6 and Sect 5)
 142 #       @client_ip_eq_helo_score (1.5, -1.25)
 143 #              Define  scores  for  the  match of the reverse record (hostname)
 144 #              against the HELO argument. Reverse lookups are done, if the for‐
 145 #              ward lookups failed and are not trusted.
 146 #              Log Entries:
 147 #              REV_IP_EQ_HELO
 148 #               The  Client's  PTR  matched  the  HELO  argument.
 149 #              REV_IP_EQ_HELO_DOMAIN
 150 #               Domain portions  of Client PTR and HELO argument matched.
 151 #              RESOLVED_IP_IS_NOT_HELO
 152 #               Client  PTRs  found   but  did  not  match  HELO argument.
 153 #       @helo_score (1.5, -2)
 154 #              Define  scores for the match of the Client IP and its /24 subnet
 155 #              against the A records of HELO or MAIL FROM domain/host. It  also
 156 #              holds the bad score for MX verifications.
 157 #              Log Entries:
 158 #              CL_IP_EQ_HELO_NUMERIC
 159 #               Client IP matches the [IPv4] HELO.
 160 #              CL_IP_EQ_FROM_IP
 161 #               Client  IP  matches   the  A  record  of  the  MAIL FROM sender
 162 #               domain/host.
 163 #              CL_IP_EQ_HELO_IP
 164 #               Client  IP  matches  the  A  record  of the HELO argument.
 165 #              CL_IP_NE_HELO
 166 #               The IP and  the /24  subnet did  not  match  A/MX  records   of
 167 #               HELO  and MAIL FROM  arguments and their subdomains.
 168 #       @helo_from_mx_eq_ip_score (1.5, -3.1)
 169 #              Define  scores  for  the  match of Client IP against MX records.
 170 #              Positive (SPAM) values are used in case the  MAIL  FROM  matches
 171 #              not the HELO argument AND the client seems to be dynamic AND the
 172 #              client is no MX for HELO and  MAIL  FROM  arguments.  The  total
 173 #              DNSBL score is added to its bad score.
 174 #              Log Entries:
 175 #              CL_IP_EQ_FROM_MX
 176 #               Client IP  matches  the MAIL FROM domain/host MX record
 177 #              CL_IP_EQ_HELO_MX
 178 #               Client IP matches the HELO domain/host MX record
 179 #              CLIENT_NOT_MX/A_FROM_DOMAIN
 180 #               Client  is  not a verified  HELO and doesn't match A/MX records
 181 #               of MAIL FROM argument
 182 #              CLIENT/24_NOT_MX/A_FROM_DOMAIN
 183 #               Client's subnet does  not  match A/MX records of the MAIL  FROM
 184 #               argument
 185 #       $dnsbl_checks_only (default: 0)
 186 #              Disable  HELO/RHSBL  verifications  and  the  like.  Do only RBL
 187 #              checks.
 188 #              1 = on, 0 = off
 189 #       @dnsbl_score (default: see below)
 190 #              A list of RBLs to be checked. If you want that  a  host  is  not
 191 #              being  evaluated any further if it is listed on several lists or
 192 #              a very trustworthy list you can control a immediate REJECT  with
 193 #              $MAXDNSBLHITS  and/or  $MAXDNSBLSCORE.  A  list  of RBLs must be
 194 #              build as follows:
 195 #              @dnsbl_score = (
 196 #                  RBLHOST1,   HIT SCORE,  MISS SCORE,     LOG NAME,
 197 #                  RBLHOST2,   HIT SCORE,  MISS SCORE,     LOG NAME,
 198 #                  ...
 199 #              );
 200 #              The default is:
 201 #              @dnsbl_score = (
 202 #                  "dynablock.njabl.org",  3.25,   0,      "DYN_NJABL",
 203 #                  "dnsbl.njabl.org",      4.25,   -1.5,   "BL_NJABL",
 204 #                  "bl.spamcop.net",       1.75,   -1.5,   "SPAMCOP",
 205 #                  "sbl-xbl.spamhaus.org", 4.35,   -1.5,   "SBL_XBL_SPAMHAUS",
 206 #                  "list.dsbl.org",        4.35,   0,      "DSBL_ORG",
 207 #                  "ix.dnsbl.manitu.net",  4.35,   0,      "IX_MANITU",
 208 #                  "relays.ordb.org",      3.25,   0,      "ORDB_ORG"
 209 #              );
 210 #       @rhsbl_score (default: see below)
 211 #              Define a list of RHSBL host which are  queried  for  the  sender
 212 #              domain.  Results  get additionally scores of 0.5 * DNSBL results
 213 #              and @rhsbl_penalty_score.  A list of RHSBL hosts to  be  queried
 214 #              must be build as follows:
 215 #              @rhsbl_score = (
 216 #                  RHSBLHOST1,  HIT SCORE,  MISS SCORE,     LOG NAME,
 217 #                  RHSBLHOST2,  HIT SCORE,  MISS SCORE,     LOG NAME,
 218 #                  ...
 219 #              );
 220 #              The default is:
 221 #              @rhsbl_score = (
 222 #                  "rhsbl.ahbl.org",              1.8,     0,  "AHBL",
 223 #                  "dsn.rfc-ignorant.org",        3.2,     0,  "DSN_RFCI",
 224 #                  "postmaster.rfc-ignorant.org", 1 ,      0,  "PM_RFCI",
 225 #                  "abuse.rfc-ignorant.org",      1,       0,  "ABUSE_RFCI"
 226 #              );
 227 #       @rhsbl_penalty_score (3.1, 0)
 228 #              This  score  will be added to each RHSBL hit if following crite‐
 229 #              rias are met:
 230 #                  Sender has a random local-part (i.e. yztrzgb@example.tld)
 231 #               or MX records of sender domain are bogus
 232 #               or FROM matches not HELO
 233 #               or HELO is untrusted (Forward record matched, reverse record
 234 #                  did not match)
 235 #       $MAXDNSBLHITS (default: 2)
 236 #              If the client is listed in more than $MAXDNSBLHITS RBLs it  will
 237 #              be  rejected  immediately  with $MAXDNSBLMSG and without further
 238 #              evaluation. Results are cached by default.
 239 #       $MAXDNSBLSCORE (default: 8)
 240 #              If the BAD SCOREs of @dnsbl_score  listed  RBLs  reach  a  level
 241 #              greater  than $MAXDNSBLSCORE the client will be rejected immedi‐
 242 #              ately with $MAXDNSBLMSG and without further evaluation.  Results
 243 #              are cached by default.
 244 #       $REJECTLEVEL (default: 1)
 245 #              Score  results equal or greater than this level will be rejected
 246 #              with $REJECTMSG
 247 

Defaults

   1 ## This is a POSIX shell fragment sourced by /etc/init.d/policyd-weight
   2 ## variable: DAEMON_OPTS
   3 ## daemon options to policyd-weight, possible options:
   4 ## 
   5 ## Options
   6 ##    -D                   Don't detach master - run master in foreground
   7 ##    -d                   Debug, don't daemonize, log to STDOUT
   8 ##    -f /path/to/file     Specify a configuration file
   9 ##    -h                   This help
  10 ##    -k                   Kill cache instance
  11 ##    -s                   Show  cache entries and exit. With -d show debug
  12 ##                         cache entries
  13 ##    -v                   Show version and exit
  14 ##
  15 ## default: unset
  16 DAEMON_OPTS="-f /etc/policyd-weight.conf"

Inclusion via restriction in /etc/postfix/main.cf

   1 smtpd_recipient_restrictions =
   2         …
   3         check_policy_service inet:127.0.0.1:12525,
   4         …

rspamd

For installation see rspamd

/etc/postfix/main.cf

   1 ### RSPAMD
   2 
   3 #smtpd_milters = unix:/var/lib/rspamd/milter.sock
   4 # or for TCP socket
   5 smtpd_milters = inet:localhost:11332
   6 non_smtpd_milters = inet:localhost:11332
   7 
   8 # skip mail without checks if something goes wrong
   9 milter_default_action = accept
  10 
  11 # 6 is the default milter protocol version;
  12 # prior to Postfix 2.6 the default protocol was 2.
  13 # milter_protocol = 6
  14 
  15 milter_default_action = accept
  16 milter_mail_macros = i {auth_type} {auth_authen} {auth_author} {mail_addr} {mail_host} {mail_mailer}
  17 #milter_mail_macros = i {auth_authen} {client_addr} {client_name} {mail_addr}

Sender Policy Framwork (SPF)

* www.spf-record.de * www.dmarcanalyzer.com: SPF Checker

Only the Server behind MX-Record may send email. v=spf1 mx -all

   1 $TTL    86400
   2 $ORIGIN rockstable.it.
   3 
   4 ; SOA RECORD WITH INCREMENTED SERIAL OMITTED
   5 
   6 @               MX      10      mx1
   7                 TXT     "v=spf1 mx -all"
  • MoinMoin Powered
  • Python Powered
  • GPL licensed
  • Valid HTML 4.01
  • Theme Memodump