From 05e4cb9478b45861bb0a24afdde3d22e2e373b6c Mon Sep 17 00:00:00 2001 From: Andrea Dell'Amico Date: Tue, 17 Dec 2019 19:55:06 +0100 Subject: [PATCH] postfix: changes to the configuration that runs the smtpd server. Support milter and haproxy. --- library/roles/postfix/defaults/main.yml | 33 +++++ library/roles/postfix/meta/main.yml | 4 + library/roles/postfix/tasks/main.yml | 2 +- .../postfix/tasks/postfix-relay-server.yml | 14 +- .../postfix/tasks/smtp-common-packages.yml | 14 ++ library/roles/postfix/templates/main.cf.j2 | 128 +++++++++++------- library/roles/postfix/templates/master.cf.j2 | 44 ++++-- .../roles/postfix/templates/saslauthd.conf.j2 | 14 ++ .../postfix/templates/saslauthd.sysconfig.j2 | 11 ++ 9 files changed, 199 insertions(+), 65 deletions(-) create mode 100644 library/roles/postfix/meta/main.yml create mode 100644 library/roles/postfix/templates/saslauthd.conf.j2 create mode 100644 library/roles/postfix/templates/saslauthd.sysconfig.j2 diff --git a/library/roles/postfix/defaults/main.yml b/library/roles/postfix/defaults/main.yml index 6be57d92..e8def685 100644 --- a/library/roles/postfix/defaults/main.yml +++ b/library/roles/postfix/defaults/main.yml @@ -21,6 +21,9 @@ postfix_biff: "no" postfix_append_dot_mydomain: "no" postfix_use_letsencrypt: False +postfix_tls_encryption_level: 'intermediate' +postfix_tls_dhparam_size: 2048 +postfix_tls_dhparam_file: /etc/postfix/dhparam.pem # Accepted values: none, may, encrypt postfix_smtpd_tls_security_level: encrypt # Accepted values: none, may, encrypt, fingerprint, verify, secure. And from 2.11: dane, dane-only @@ -40,11 +43,21 @@ postfix_relay_port: 587 postfix_smtp_relay_user: '{{ ansible_fqdn }}' # This one has to be set inside a vault file #postfix_smtp_relay_pwd: 'set_you_password_here_in_a_vault_encrypted_file' +postfix_smtpd_reject_unknown_helo_hostname: False ############################################################################# # Relay server: accept authenticated clients ############################################################################# postfix_relay_server: False +# +postfix_use_milter: False +postfix_spamassassin_milter: False +postfix_spamassassin_milter_socket: 'unix:/run/spamass-milter/postfix/sock' +postfix_clamav_milter: False +# inet:[127.0.0.1]:7357 +postfix_clamav_milter_socket: 'unix:/run/clamav-milter/clamav-milter.socket' +# Specify accept, reject, tempfail, quarantine +postfix_milter_action: tempfail ############################################################################# # SMTP server that not accept authenticated clients. ############################################################################# @@ -68,6 +81,26 @@ postfix_sasl_deb_packages: postfix_sasl_rh_packages: - cyrus-sasl +postfix_saslauthd_mech: 'pam' +postfix_saslauthd_flags: '' +postfix_saslauthd_conf_file: '/etc/saslauthd.conf' +# +postfix_sasl_ldap_servers: ldap://localhost +postfix_sasl_ldap_bind_dn: cn=saslauthd,ou=dsa,dc=example,dc=com +# postfix_sasl_ldap_bind_pw: set inside a vault file +postfix_sasl_ldap_timeout: 10 +postfix_sasl_ldap_time_limit: 10 +postfix_sasl_ldap_scope: sub +postfix_sasl_ldap_search_base: ou=people,dc=example,dc=com +postfix_sasl_ldap_auth_method: bind +postfix_sasl_ldap_filter: (&(uid=%u)(mail=*)) +postfix_sasl_ldap_debug: 0 +postfix_sasl_ldap_verbose: off +postfix_sasl_ldap_ssl: no +postfix_sasl_ldap_starttls: yes +postfix_sasl_ldap_referrals: no +# + postfix_use_domain_name: False postfix_inet_lmtp_enabled: False postfix_inet_lmtp_host: '127.0.0.1' diff --git a/library/roles/postfix/meta/main.yml b/library/roles/postfix/meta/main.yml new file mode 100644 index 00000000..c5ea1b30 --- /dev/null +++ b/library/roles/postfix/meta/main.yml @@ -0,0 +1,4 @@ +--- +dependencies: + - { role: '../../library/roles/clamav', when: postfix_clamav_milter | bool } + #- { role: '../../library/roles/spamassassin', when: postfix_spamassassin_milter | bool } diff --git a/library/roles/postfix/tasks/main.yml b/library/roles/postfix/tasks/main.yml index b1969d74..87cdd912 100644 --- a/library/roles/postfix/tasks/main.yml +++ b/library/roles/postfix/tasks/main.yml @@ -7,7 +7,7 @@ - postfix_use_sasl_auth | bool - postfix_relay_client | bool - import_tasks: postfix-relay-server.yml - when: postfix_relay_server | bool + when: postfix_smtpd_server | bool - import_tasks: postfix-letsencrypt-hook.yml when: postfix_use_letsencrypt | bool diff --git a/library/roles/postfix/tasks/postfix-relay-server.yml b/library/roles/postfix/tasks/postfix-relay-server.yml index 338cc830..4db90b72 100644 --- a/library/roles/postfix/tasks/postfix-relay-server.yml +++ b/library/roles/postfix/tasks/postfix-relay-server.yml @@ -3,7 +3,6 @@ block: - name: Install the sasl2 authentication infrastructure apt: pkg={{ postfix_sasl_deb_packages }} state=present cache_valid_time=1800 - when: ansible_distribution_file_variety == "Debian" - name: Create the sasl run directory inside /var/spool/postfix, for chroot file: dest=/var/spool/postfix/var/run/saslauthd state=directory owner=root group=root mode=0555 @@ -16,14 +15,24 @@ - name: Enable the saslauth daemon action: configfile path=/etc/default/saslauthd key=START value='yes' syntax=shell + when: ansible_distribution_file_variety == "Debian" tags: [ 'postfix_relay', 'postfix-relay' ] - name: Postfix relay, rh specific block: - name: Install the sasl2 authentication infrastructure yum: pkg={{ postfix_sasl_rh_packages }} state=present - when: ansible_distribution_file_variety == "RedHat" + - name: Install the SASL configuration + template: src=saslauthd.sysconfig.j2 dest=/etc/sysconfig/saslauthd owner=root group=root mode=0644 + notify: restart saslauth daemon + + - name: Install the ldap configuration for saslauthd + template: src=saslauthd.conf.j2 dest=/etc/saslauthd.conf owner=root group=root mode=0400 + when: postfix_saslauthd_mech == 'ldap' + notify: restart saslauth daemon + + when: ansible_distribution_file_variety == "RedHat" tags: [ 'postfix_relay', 'postfix-relay' ] @@ -38,6 +47,7 @@ - name: Assign the sasl group to the postfix user so that postfix can use the saslauthd socket user: name=postfix groups='sasl' notify: Restart postfix + when: ansible_distribution_file_variety == "Debian" - name: Ensure that the saslauthd daemon is started and enabled service: name=saslauthd state=restarted enabled=yes diff --git a/library/roles/postfix/tasks/smtp-common-packages.yml b/library/roles/postfix/tasks/smtp-common-packages.yml index 90c6ede6..d36d22e1 100644 --- a/library/roles/postfix/tasks/smtp-common-packages.yml +++ b/library/roles/postfix/tasks/smtp-common-packages.yml @@ -12,6 +12,20 @@ yum: pkg=ssmtp state=absent when: ansible_distribution_file_variety == "RedHat" + - name: Create a DHPARAM file used by TLS + shell: openssl dhparam -out {{ postfix_tls_dhparam_file }} {{ postfix_tls_dhparam_size }} + args: + creates: '{{ postfix_tls_dhparam_file }}' + when: postfix_tls_encryption_level == "old" + notify: Reload postfix + + - name: Download a DHPARAM file from the mozilla ssl configurator site + get_url: url='https://ssl-config.mozilla.org/ffdhe2048.txt' dest={{ postfix_tls_dhparam_file }} + args: + creates: '{{ postfix_tls_dhparam_file }}' + when: postfix_tls_encryption_level != "old" + notify: Reload postfix + - name: Write the postfix main configuration file template: src=main.cf.j2 dest=/etc/postfix/main.cf owner=root group=root mode=0444 register: postfix_main_restart_needed diff --git a/library/roles/postfix/templates/main.cf.j2 b/library/roles/postfix/templates/main.cf.j2 index 4b85559d..fd72c28e 100644 --- a/library/roles/postfix/templates/main.cf.j2 +++ b/library/roles/postfix/templates/main.cf.j2 @@ -73,7 +73,7 @@ myorigin = {{ ansible_fqdn }} # Note: you need to stop/start Postfix when this parameter changes. # {% if not postfix_use_inet_interfaces %} -{% if not postfix_relay_server %} +{% if not postfix_smtpd_server %} inet_interfaces = localhost inet_protocols = ipv4 {% else %} @@ -535,10 +535,54 @@ disable_vrfy_command = yes smtpd_delay_reject = yes smtpd_helo_required = yes +mailbox_size_limit = {{ postfix_message_size_limit }} + +{% if postfix_use_milter %} +# +# MILTER CONFIGURATION +# +# clamav, milter-greylist, spamassassin +# +#milter_connect_timeout = 30s +#milter_command_timeout = 30s +#milter_content_timeout = 300s +#milter_protocol = 2 +# What to do in case of errors? Specify accept, reject, tempfail, +# or quarantine (Postfix 2.6 or later). +milter_default_action = {{ postfix_milter_action }} +smtpd_milters = +{% if postfix_spamassassin_milter %} + {{ postfix_spamassassin_milter_socket }} +{% endif %} +{% if postfix_clamav_milter %} + {{ postfix_clamav_milter_socket }} +{% endif %} +{% endif %} + {% if postfix_smtpd_server %} smtpd_client_restrictions = permit_mynetworks permit_inet_interfaces +smtpd_sasl_path = smtpd +smtpd_sasl_auth_enable = yes +smtpd_sasl_security_options = {{ postfix_smtp_sasl_security_options }} +smtpd_sasl_tls_security_options = {{ postfix_smtp_sasl_tls_security_options }} +smtpd_sasl_authenticated_header = yes +broken_sasl_auth_clients = yes +smtpd_helo_required = yes +{% if postfix_smtpd_reject_unknown_helo_hostname %} +# Don't talk to mail systems that don't know their own hostname. Use with care: it breaks most dialup setups +smtpd_helo_restrictions = reject_unknown_helo_hostname +{% endif %} +# Block clients that speak too early. +smtpd_data_restrictions = reject_unauth_pipelining +# Our internal servers talk to the submission port so they are treated as clients +smtpd_client_restrictions = permit_inet_interfaces, permit_sasl_authenticated, reject +# Don't accept mail from domains that don't exist. +smtpd_sender_restrictions = reject_unknown_sender_domain +# Relay control: local clients and +# authenticated clients may specify any destination domain. +smtpd_relay_restrictions = permit_sasl_authenticated, reject {% endif %} # FAST ETRN SERVICE @@ -668,43 +712,6 @@ manpage_directory = /usr/share/man readme_directory = no # TLS parameters -# 2019-12-11, https://ssl-config.mozilla.org/#server=postfix&server-version=2.10.1&config=intermediate&openssl-version=1.0.2k -# smtpd_use_tls = yes - -# smtpd_tls_security_level = may -# smtpd_tls_auth_only = yes -# smtpd_tls_cert_file = /path/to/signed_cert_plus_intermediates -# smtpd_tls_key_file = /path/to/private_key -# smtpd_tls_mandatory_protocols = !SSLv2, !SSLv3, !TLSv1, !TLSv1.1 -# smtpd_tls_protocols = !SSLv2, !SSLv3, !TLSv1, !TLSv1.1 -# smtpd_tls_mandatory_ciphers = medium - -# curl https://ssl-config.mozilla.org/ffdhe2048.txt > /path/to/dhparam.pem -# not actually 1024 bits, this applies to all DHE >= 1024 bits -# smtpd_tls_dh1024_param_file = /path/to/dhparam.pem - -# tls_medium_cipherlist = ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384 -# tls_preempt_cipherlist = no - -# 2019-12-11, https://ssl-config.mozilla.org/#server=postfix&server-version=2.10.1&config=old&openssl-version=1.0.2k -# smtpd_use_tls = yes - -# smtpd_tls_security_level = may -# smtpd_tls_auth_only = yes -# smtpd_tls_cert_file = /path/to/signed_cert_plus_intermediates -# smtpd_tls_key_file = /path/to/private_key -# smtpd_tls_mandatory_protocols = !SSLv2, !SSLv3 -# smtpd_tls_protocols = !SSLv2, !SSLv3 -# smtpd_tls_mandatory_ciphers = medium - -# openssl dhparam 1024 > /path/to/dhparam.pem -# not actually 1024 bits, this applies to all DHE >= 1024 bits -# smtpd_tls_dh1024_param_file = /path/to/dhparam.pem - -# tls_medium_cipherlist = ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES256-SHA256:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:DES-CBC3-SHA -# tls_preempt_cipherlist = yes - -# Server {% if letsencrypt_acme_install is defined %} {% if postfix_use_letsencrypt %} smtpd_tls_cert_file={{ letsencrypt_acme_certs_dir }}/cert @@ -718,20 +725,45 @@ smtpd_tls_key_file=/etc/ssl/private/ssl-cert-snakeoil.key smtpd_tls_cert_file=/etc/ssl/certs/ssl-cert-snakeoil.pem smtpd_tls_key_file=/etc/ssl/private/ssl-cert-snakeoil.key {% endif %} -smtpd_tls_session_cache_database = btree:${data_directory}/smtpd_scache -{% if postfix_smtpd_server %} +{% if postfix_tls_encryption_level == 'intermediate' %} +# 2019-12-11, https://ssl-config.mozilla.org/#server=postfix&server-version=2.10.1&config=intermediate&openssl-version=1.0.2k +smtpd_use_tls = yes smtpd_tls_security_level = {{ postfix_smtpd_tls_security_level }} +{% if postfix_smtpd_server %} smtpd_tls_auth_only = yes {% endif %} -smtpd_tls_security_level={{ postfix_smtpd_tls_security_level }} +smtpd_tls_mandatory_protocols = !SSLv2, !SSLv3, !TLSv1, !TLSv1.1 +smtpd_tls_protocols = !SSLv2, !SSLv3, !TLSv1, !TLSv1.1 +smtpd_tls_mandatory_ciphers = medium + +# curl https://ssl-config.mozilla.org/ffdhe2048.txt > /path/to/dhparam.pem +# not actually 1024 bits, this applies to all DHE >= 1024 bits +smtpd_tls_dh1024_param_file = {{ postfix_tls_dhparam_file }} + +tls_medium_cipherlist = ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384 +tls_preempt_cipherlist = no + +{% elif postfix_tls_encryption_level == 'old' %} +# 2019-12-11, https://ssl-config.mozilla.org/#server=postfix&server-version=2.10.1&config=old&openssl-version=1.0.2k +smtpd_use_tls = yes +smtpd_tls_security_level = {{ postfix_smtpd_tls_security_level }} +{% if postfix_smtpd_server %} +smtpd_tls_auth_only = yes +{% endif %} +smtpd_tls_mandatory_protocols = !SSLv2, !SSLv3 +smtpd_tls_protocols = !SSLv2, !SSLv3 +smtpd_tls_mandatory_ciphers = medium + +# openssl dhparam 1024 > /path/to/dhparam.pem +# not actually 1024 bits, this applies to all DHE >= 1024 bits +smtpd_tls_dh1024_param_file = {{ postfix_tls_dhparam_file }} + +tls_medium_cipherlist = ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES256-SHA256:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:DES-CBC3-SHA +tls_preempt_cipherlist = yes +{% endif %} +# Server +smtpd_tls_session_cache_database = btree:${data_directory}/smtpd_scache # Client smtp_tls_security_level = {{ postfix_smtp_tls_security_level }} smtp_tls_session_cache_database = btree:${data_directory}/smtp_scache -# -# HAPROXY -# -{% if postfix_behind_haproxy %} -smtpd_upstream_proxy_protocol = haproxy -{% endif %} - diff --git a/library/roles/postfix/templates/master.cf.j2 b/library/roles/postfix/templates/master.cf.j2 index 7cdf38ac..ed6d5a21 100644 --- a/library/roles/postfix/templates/master.cf.j2 +++ b/library/roles/postfix/templates/master.cf.j2 @@ -13,26 +13,42 @@ smtp inet n - n - - smtpd #smtpd pass - - n - - smtpd #dnsblog unix - - n - 0 dnsblog #tlsproxy unix - - n - 0 tlsproxy -#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 +{% if postfix_smtpd_server %} +submission inet n - n - - smtpd + -o syslog_name=postfix/submission + -o smtpd_tls_security_level=encrypt +{% if postfix_use_letsencrypt %} + -o smtpd_tls_cert_file={{ letsencrypt_acme_certs_dir }}/cert + -o smtpd_tls_key_file={{ letsencrypt_acme_certs_dir }}/privkey +{% endif %} + -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=permit_sasl_authenticated,reject -# -o milter_macro_daemon_name=ORIGINATING -#smtps inet n - n - - smtpd -# -o syslog_name=postfix/smtps -# -o smtpd_tls_wrappermode=yes -# -o smtpd_sasl_auth_enable=yes -# -o smtpd_reject_unlisted_recipient=no + -o smtpd_recipient_restrictions=permit_sasl_authenticated,reject +{% if postfix_behind_haproxy %} + -o smtpd_upstream_proxy_protocol=haproxy +{% endif %} + -o milter_macro_daemon_name=ORIGINATING +smtps inet n - n - - smtpd + -o syslog_name=postfix/smtps + -o smtpd_tls_wrappermode=yes +{% if postfix_use_letsencrypt %} + -o smtpd_tls_cert_file={{ letsencrypt_acme_certs_dir }}/cert + -o smtpd_tls_key_file={{ letsencrypt_acme_certs_dir }}/privkey +{% endif %} +{% if postfix_behind_haproxy %} + -o smtpd_upstream_proxy_protocol=haproxy +{% endif %} + -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=permit_sasl_authenticated,reject -# -o milter_macro_daemon_name=ORIGINATING + -o smtpd_recipient_restrictions=permit_sasl_authenticated,reject + -o milter_macro_daemon_name=ORIGINATING +{% endif %} #628 inet n - n - - qmqpd pickup unix n - n 60 1 pickup cleanup unix n - n - 0 cleanup diff --git a/library/roles/postfix/templates/saslauthd.conf.j2 b/library/roles/postfix/templates/saslauthd.conf.j2 new file mode 100644 index 00000000..f6c49388 --- /dev/null +++ b/library/roles/postfix/templates/saslauthd.conf.j2 @@ -0,0 +1,14 @@ +ldap_servers: {{ postfix_sasl_ldap_servers }} +ldap_bind_dn: {{ postfix_sasl_ldap_bind_dn }} +ldap_bind_pw: {{ postfix_sasl_ldap_bind_pw }} +ldap_timeout: {{ postfix_sasl_ldap_timeout }} +ldap_time_limit: {{ postfix_sasl_ldap_time_limit }} +ldap_scope: {{ postfix_sasl_ldap_scope }} +ldap_search_base: {{ postfix_sasl_ldap_search_base }} +ldap_auth_method: {{ postfix_sasl_ldap_auth_method }} +ldap_filter: {{ postfix_sasl_ldap_filter }} +ldap_debug: {{ postfix_sasl_ldap_debug }} +ldap_verbose: {{ postfix_sasl_ldap_verbose }} +ldap_ssl: {{ postfix_sasl_ldap_ssl }} +ldap_starttls: {{ postfix_sasl_ldap_starttls }} +ldap_referrals: {{ postfix_sasl_ldap_referrals }} diff --git a/library/roles/postfix/templates/saslauthd.sysconfig.j2 b/library/roles/postfix/templates/saslauthd.sysconfig.j2 new file mode 100644 index 00000000..7d6b1417 --- /dev/null +++ b/library/roles/postfix/templates/saslauthd.sysconfig.j2 @@ -0,0 +1,11 @@ +# Directory in which to place saslauthd's listening socket, pid file, and so +# on. This directory must already exist. +SOCKETDIR=/run/saslauthd + +# Mechanism to use when checking passwords. Run "saslauthd -v" to get a list +# of which mechanism your installation was compiled with the ablity to use. +MECH="{{ postfix_saslauthd_mech }}" + +# Additional flags to pass to saslauthd on the command line. See saslauthd(8) +# for the list of accepted flags. +FLAGS={{ postfix_saslauthd_flags }}