Changeset - 9727c5e3ac7c
[Not reviewed]
0 5 0
Branko Majic (branko) - 5 years ago 2021-01-13 23:54:35
branko@majic.rs
MAR-151: Added support for Debian 10 Buster to mail_forwarder role:

- Updated role reference documentaiton.
- Updated role meta information.
- Updated tests.
- Set the smtpd_relay_restrictions configuration option for Postfix
SMTP server in mail_forwarder role (required for version found in
Debian 10 Buster).
5 files changed with 45 insertions and 1 deletions:
0 comments (0 inline, 0 general)
docs/rolereference.rst
Show inline comments
 
@@ -1273,192 +1273,193 @@ Here is an example configuration for setting-up XMPP server using Prosody:
 
  smtp_rbl:
 
    - bl.spamcop.net
 
    - zen.spamhaus.org
 
  mail_postmaster: postmaster@example.com
 

	
 
  smtp_allow_relay_from:
 
    - ldap.example.com
 
    - xmpp.example.com
 

	
 
  imap_max_user_connections_per_ip: 50
 

	
 

	
 
Mail Forwarder
 
--------------
 

	
 
The ``mail_forwarder`` role can be used for setting-up a local SMTP server for
 
sending out mails and receiving mails for local users. The SMTP server is
 
provided by Postfix.
 

	
 
SMTP service on server set-up this way is not meant to be exposed to the
 
Internet directly, and should receive delivery failures from the relay server
 
instead.
 

	
 
The role implements the following:
 

	
 
* Installs and configures Postfix.
 
* Purges Exim4 configuration (just in case).
 
* Sets-up aliases for the local recipients.
 
* Installs SWAKS (utility for testing SMTP servers).
 
* Configures firewall to accept SMTP connections from SMTP relay (if one has
 
  been configured). This allows for delivery of bounced e-mails.
 

	
 
Postfix is configured as follows:
 

	
 
* Local destinations are set-up.
 
* A relay host is set.
 
* TLS is enforced for relaying mails, with configurable truststore for server
 
  certificate verification if SMTP relay is used. If SMTP relay is not used
 
  (configured), no certificate verification is done.
 
* Uses 2048-bit Diffie-Hellman parameters for relevant TLS ciphers for
 
  incoming connections.
 

	
 

	
 
Role dependencies
 
~~~~~~~~~~~~~~~~~
 

	
 
Depends on the following roles:
 

	
 
* **common**
 

	
 

	
 
Parameters
 
~~~~~~~~~~
 

	
 
**local_mail_aliases** (dictionary, optional, ``[]``)
 
  Dictionary defining the local aliases. Aliases defined this way will either be
 
  appended to default aliases on the server, or replace the existing entries (if
 
  the alias/recipient is already present). Keys in the dictionary are the local
 
  recipients/aliases, while the value provided should be a space-separated list
 
  of mail addresses (or local users) where the mails should be forwarded.
 

	
 
**mail_message_size_limit** (integer, optional, ``10240000``)
 
  Maximum size of message in bytes that the SMTP server should accept
 
  for incoming mails. If the mail message size exceeds the listed
 
  value, it will be rejected by the server. The size is also
 
  advertised as part of SMTP server capabilities (in response to the
 
  ``ehlo`` SMTP command). Changing the value is primarily useful when
 
  SMTP from relay is allowed (via the ``smtp_from_relay_allowed``
 
  parameter), since incoming SMTP communication is otherwise not
 
  allowed at all.
 

	
 
**smtp_from_relay_allowed** (boolean, optional, ``True``)
 
  Specify if SMTP traffic from SMTP relay should be allowed or not (for bounced
 
  messages, for example). This parameter should be set to ``False`` on systems
 
  behind NAT or on systems that may not have constant network connectivity (such
 
  as laptops) to avoid firewall failures since SMTP relay name needs to be
 
  resolvable.
 

	
 
**smtp_relay_host** (string, optional, ``None``)
 
  SMTP server via which the mails are sent out for non-local recipients.
 

	
 
**smtp_relay_host_port** (integer, optional, ``None``)
 
  Port to use when connecting to the SMTP relay host.
 

	
 
**smtp_relay_truststore** (string, mandatory)
 
  X.509 certificate chain used for issuing certificate for the SMTP relay
 
  service. The file will be stored in location
 
  ``/etc/ssl/certs/smtp_relay_truststore.pem``
 

	
 

	
 
Distribution compatibility
 
~~~~~~~~~~~~~~~~~~~~~~~~~~
 

	
 
Role is compatible with the following distributions:
 

	
 
- Debian 9 (Stretch)
 
- Debian 10 (Buster)
 

	
 

	
 
Examples
 
~~~~~~~~
 

	
 
Here is an example configuration for setting-up the mail forwarder:
 

	
 
.. code-block:: yaml
 

	
 
  ---
 

	
 
  # All mails sent to local user root will be forwarded to external account as
 
  # well.
 
  local_mail_aliases:
 
    root: "root john.doe@example.com"
 

	
 
  smtp_relay_host: mail.example.com
 

	
 
  smtp_relay_host_port: 27
 

	
 
  smtp_from_relay_allowed: False
 

	
 
  smtp_relay_truststore: /etc/ssl/certs/example_ca_chain.pem
 

	
 

	
 
Web Server
 
----------
 

	
 
The ``web_server`` role can be used for setting-up a web server on destination
 
machine.
 

	
 
The role is supposed to be very lightweight, providing a basis for deployment of
 
web applications.
 

	
 
The role implements the following:
 

	
 
* Installs and configures nginx with a single, default vhost with a small static
 
  index page.
 
* Deploys the HTTPS TLS private key and certificate (for default vhost).
 
* Configures TLS versions and ciphers supported by Nginx.
 
* Uses 2048-bit Diffie-Hellman parameters for relevant TLS ciphers for
 
  incoming connections.
 
* Configures firewall to allow incoming connections to the web server.
 
* Installs and configures virtualenv and virtualenvwrapper as a common base for
 
  Python apps.
 
* Installs and configures PHP FPM as a common base for PHP apps.
 

	
 
The web server is configured as follows:
 

	
 
* No plaintext HTTP is allowed, HTTPS is mandatory. Clients connecting
 
  via plaintext HTTP are redirected to HTTPS.
 
* Clients are served with ``Strict-Transport-Security`` header with
 
  value of ``max-age=31536000; includeSubDomains``. This forces
 
  compliant clients to always connect using HTTPS to the web server
 
  when accessing its default domain, as well as any subdomains served
 
  by this web server or any other. The (client-side) cached header
 
  value expires after one year.
 

	
 

	
 
Role dependencies
 
~~~~~~~~~~~~~~~~~
 

	
 
Depends on the following roles:
 

	
 
* **common**
 

	
 

	
 
Parameters
 
~~~~~~~~~~
 

	
 
**default_https_tls_certificate** (string, mandatory)
 
  X.509 certificate used for TLS for HTTPS service. The file will be stored in
 
  directory ``/etc/ssl/certs/`` under name ``{{ ansible_fqdn }}_https.pem``.
 

	
 
**default_https_tls_key** (string, mandatory)
 
  Private key used for TLS for HTTPS service. The file will be stored in
 
  directory ``/etc/ssl/private/`` under name ``{{ ansible_fqdn }}_https.key``.
 

	
 
**web_default_title** (string, optional, ``Welcome``)
 
  Title for the default web page shown to users (if no other vhosts were matched).
 

	
 
**web_default_message** (string, optional, ``You are attempting to access the web server using a wrong name or an IP address. Please check your URL.``)
 
  Message for the default web page shown to users (if no other vhosts were
 
  matched).
 

	
 
**web_server_tls_protocols** (list, optional, ``[ "TLSv1.2" ]``)
 
  List of TLS protocols the web server should support. Each value specified
 
  should be compatible with Nginx configuration option ``ssl_protocols``.
 

	
 
**web_server_tls_ciphers** (string, optional, ``DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-CHACHA20-POLY1305:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-CHACHA20-POLY1305:!aNULL:!MD5:!EXPORT``)
 
  TLS ciphers to enable on the web server. This should be an OpenSSL-compatible
 
  cipher specification. Value should be compatible with Nginx configuration
 
  option ``ssl_ciphers``. Default value allows only TLSv1.2 and strong PFS
 
  ciphers with RSA private keys.
 

	
 

	
roles/mail_forwarder/meta/main.yml
Show inline comments
 
---
 

	
 
dependencies:
 
  - common
 

	
 
galaxy_info:
 
  author: Branko Majic
 
  description: Sets-up local SMTP server for sending out mails and receiving mails for local users
 
  license: BSD
 
  min_ansible_version: 2.9
 
  platforms:
 
    - name: Debian
 
      versions:
 
        - 8
 
        - 9
 
        - 10
roles/mail_forwarder/molecule/default/molecule.yml
Show inline comments
 
---
 

	
 
dependency: {}
 

	
 
driver:
 
  name: vagrant
 
  provider:
 
    name: virtualbox
 

	
 
lint:
 
  name: yamllint
 
  options:
 
    config-file: ../../.yamllint.yml
 

	
 
platforms:
 

	
 
  - name: mail-server
 
    groups:
 
      - mail-servers
 
      - helper
 
    box: debian/contrib-stretch64
 
    memory: 256
 
    cpus: 1
 
    interfaces:
 
      - auto_config: true
 
        ip: 10.31.127.10
 
        network_name: private_network
 
        type: static
 

	
 
  - name: client1
 
    groups:
 
      - clients
 
      - helper
 
    box: debian/contrib-stretch64
 
    memory: 256
 
    cpus: 1
 
    interfaces:
 
      - auto_config: true
 
        ip: 10.31.127.11
 
        network_name: private_network
 
        type: static
 

	
 
  - name: parameters-mandatory-stretch64
 
    groups:
 
      - parameters-mandatory
 
    box: debian/contrib-stretch64
 
    memory: 256
 
    cpus: 1
 
    interfaces:
 
      - auto_config: true
 
        ip: 10.31.127.30
 
        network_name: private_network
 
        type: static
 

	
 
  - name: parameters-optional-stretch64
 
    groups:
 
      - parameters-optional
 
    box: debian/contrib-stretch64
 
    memory: 256
 
    cpus: 1
 
    interfaces:
 
      - auto_config: true
 
        ip: 10.31.127.31
 
        network_name: private_network
 
        type: static
 

	
 
  - name: parameters-no-incoming-stretch64
 
    groups:
 
      - parameters-no-incoming
 
    box: debian/contrib-stretch64
 
    memory: 256
 
    cpus: 1
 
    interfaces:
 
      - auto_config: true
 
        ip: 10.31.127.32
 
        network_name: private_network
 
        type: static
 

	
 
  - name: parameters-mandatory-buster64
 
    groups:
 
      - parameters-mandatory
 
    box: debian/contrib-buster64
 
    memory: 256
 
    cpus: 1
 
    interfaces:
 
      - auto_config: true
 
        ip: 10.31.127.20
 
        network_name: private_network
 
        type: static
 

	
 
  - name: parameters-optional-buster64
 
    groups:
 
      - parameters-optional
 
    box: debian/contrib-buster64
 
    memory: 256
 
    cpus: 1
 
    interfaces:
 
      - auto_config: true
 
        ip: 10.31.127.21
 
        network_name: private_network
 
        type: static
 

	
 
  - name: parameters-no-incoming-buster64
 
    groups:
 
      - parameters-no-incoming
 
    box: debian/contrib-buster64
 
    memory: 256
 
    cpus: 1
 
    interfaces:
 
      - auto_config: true
 
        ip: 10.31.127.22
 
        network_name: private_network
 
        type: static
 

	
 
provisioner:
 
  name: ansible
 
  playbooks:
 
    cleanup: cleanup.yml
 
  config_options:
 
    defaults:
 
      force_valid_group_names: "ignore"
 
      interpreter_python: "/usr/bin/python3"
 
    ssh_connection:
 
      pipelining: "True"
 
  lint:
 
    name: ansible-lint
 

	
 
scenario:
 
  name: default
 

	
 
verifier:
 
  name: testinfra
 
  lint:
 
    name: flake8
roles/mail_forwarder/molecule/default/prepare.yml
Show inline comments
 
---
 

	
 
- name: Set-up fixtures
 
  hosts: localhost
 
  connection: local
 
  gather_facts: false
 
  tasks:
 

	
 
    - name: Initialise CA hierarchy
 
      command: "gimmecert init"
 
      args:
 
        creates: ".gimmecert/ca/level1.cert.pem"
 
        chdir: "tests/data/"
 

	
 
    - name: Generate server private keys and certificates
 
      command:
 
      args:
 
        chdir: "tests/data/"
 
        creates: ".gimmecert/server/{{ item.name }}.cert.pem"
 
        argv:
 
          - "gimmecert"
 
          - "server"
 
          - "{{ item.name }}"
 
          - "{{ item.fqdn }}"
 
      with_items:
 
        - name: mail-server_smtp
 
          fqdn: mail-server
 

	
 
    - name: Set-up link to generated X.509 material
 
      file:
 
        src: ".gimmecert"
 
        dest: "tests/data/x509"
 
        state: link
 

	
 
- name: Prepare
 
  hosts: all
 
  gather_facts: false
 
  tasks:
 
    - name: Install python for Ansible
 
      raw: test -e /usr/bin/python3 || (apt -y update && apt install -y python3-minimal)
 
      become: true
 
      changed_when: false
 

	
 
- hosts: all
 
  become: true
 
  tasks:
 

	
 
    - name: Update all caches to avoid errors due to missing remote archives
 
      apt:
 
        update_cache: true
 
      changed_when: false
 

	
 
- hosts: all
 
  become: true
 
  tasks:
 

	
 
    - name: Set-up the hosts file
 
      lineinfile:
 
        path: /etc/hosts
 
        regexp: "^{{ item.key }}"
 
        line: "{{ item.key }} {{ item.value }}"
 
        owner: root
 
        group: root
 
        mode: 0644
 
        state: present
 
      with_dict:
 
        10.31.127.10: "mail-server domain1"
 
        10.31.127.11: "client1"
 
        10.31.127.30: "parameters-mandatory-stretch64"
 
        10.31.127.31: "parameters-optional-stretch64"
 
        10.31.127.32: "parameters-no-incoming-stretch64"
 
        10.31.127.20: "parameters-mandatory-buster64"
 
        10.31.127.21: "parameters-optional-buster64"
 
        10.31.127.22: "parameters-no-incoming-buster64"
 

	
 
    - name: Install tools for testing
 
      apt:
 
        name: gnutls-bin
 
        state: present
 

	
 
- hosts: clients
 
  become: true
 
  tasks:
 

	
 
    - name: Install SWAKS for testing SMTP capability
 
      apt:
 
        name: swaks
 
        state: present
 

	
 
    - name: Install tool for testing TCP connectivity
 
      apt:
 
        name: hping3
 
        state: present
 

	
 
    - name: Deploy CA certificate
 
      copy:
 
        src: tests/data/x509/ca/level1.cert.pem
 
        dest: /usr/local/share/ca-certificates/testca.crt
 
        owner: root
 
        group: root
 
        mode: 0644
 
      notify:
 
        - Update CA certificate cache
 

	
 
  handlers:
 

	
 
    - name: Update CA certificate cache
 
      command: /usr/sbin/update-ca-certificates --fresh
 

	
 
- hosts: mail-servers
 
  become: true
 
  tasks:
 

	
 
    - name: Deploy CA certificate
 
      copy:
 
        src: tests/data/x509/ca/level1.cert.pem
 
        dest: /usr/local/share/ca-certificates/testca.crt
 
        owner: root
 
        group: root
 
        mode: 0644
 
      notify:
 
        - Update CA certificate cache
 

	
 
    - name: Deploy SMTP private key and certificate
 
      copy:
 
        src: "tests/data/x509/server/{{ item }}"
 
        dest: "/etc/ssl/{{ item }}"
 
        owner: root
 
        group: root
 
        mode: 0600
 
      with_items:
 
        - mail-server_smtp.cert.pem
 
        - mail-server_smtp.key.pem
 

	
 
    - name: Install Postfix
 
      apt:
 
        name: "postfix"
 
        state: present
 

	
 
    - name: Purge Exim configuration
 
      apt:
 
        name: "exim4*"
 
        state: absent
 
        purge: true
 

	
 
    - name: Deploy Postfix configuration
 
      copy:
 
        src: tests/data/main.cf
 
        dest: /etc/postfix/main.cf
 
        owner: root
 
        group: root
 
        mode: 0644
 
      notify:
 
        - Restart Postfix
 

	
 
    - name: Install tool for testing TCP connectivity
 
      apt:
 
        name: hping3
 
        state: present
 

	
 
    - name: Install SWAKS for testing SMTP capability
 
      apt:
 
        name: swaks
 
        state: present
 

	
 
    - name: Set-up port forwarding
 
      command: "iptables -t nat -A PREROUTING -p tcp -m tcp --dport 27 -j REDIRECT --to-ports 25"
 
      changed_when: false
 

	
 
  handlers:
roles/mail_forwarder/templates/main.cf.j2
Show inline comments
 
# See /usr/share/postfix/main.cf.dist for a commented, more complete version
 

	
 

	
 
# Debian specific:  Specifying a file name will cause the first
 
# line of that file to be used as the name.  The Debian default
 
# is /etc/mailname.
 
#myorigin = /etc/mailname
 

	
 
smtpd_banner = $myhostname ESMTP $mail_name (Debian/GNU)
 
biff = no
 

	
 
# appending .domain is the MUA's job.
 
append_dot_mydomain = no
 

	
 
# Uncomment the next line to generate "delayed mail" warnings
 
#delay_warning_time = 4h
 

	
 
readme_directory = no
 

	
 
# TLS parameters
 
smtpd_tls_cert_file=/etc/ssl/certs/ssl-cert-snakeoil.pem
 
smtpd_tls_key_file=/etc/ssl/private/ssl-cert-snakeoil.key
 
smtpd_tls_dh1024_param_file = /etc/ssl/private/{{ inventory_hostname }}_smtp.dh.pem
 
smtpd_tls_dh512_param_file = /etc/ssl/private/{{ inventory_hostname }}_smtp.dh.pem
 
smtpd_use_tls=yes
 
smtpd_tls_session_cache_database = btree:${data_directory}/smtpd_scache
 
smtp_tls_session_cache_database = btree:${data_directory}/smtp_scache
 
{% if smtp_relay_host %}
 
smtp_tls_security_level=verify
 
smtp_tls_CAfile=/etc/ssl/certs/smtp_relay_truststore.pem
 
{% endif %}
 

	
 
# See /usr/share/doc/postfix/TLS_README.gz in the postfix-doc package for
 
# information on enabling SSL in the smtp client.
 

	
 
myhostname = {{ inventory_hostname }}
 
alias_maps = hash:/etc/aliases
 
alias_database = hash:/etc/aliases
 
myorigin = /etc/mailname
 
mydestination = {{ inventory_hostname }}, {{ inventory_hostname_short }}, localhost.localdomain, localhost
 
relayhost = {{ smtp_relay_host }}{% if smtp_relay_host and smtp_relay_host_port %}:{{ smtp_relay_host_port }}{% endif %}{{ '' }}
 
mynetworks = 127.0.0.0/8 [::ffff:127.0.0.0]/104 [::1]/128
 
mailbox_command = procmail -a "$EXTENSION"
 
mailbox_size_limit = 0
 
recipient_delimiter = +
 
inet_interfaces = all
 
inet_protocols = all
 

	
 
# Fall-back to using native lookups (/etc/hosts etc) if DNS lookup fails. Useful
 
# for local overrides of mail servers.
 
smtp_host_lookup = dns, native
 

	
 
# Explicitly set maximum allowed mail size that should be accepted.
 
message_size_limit = {{ mail_message_size_limit }}
 

	
 
# Allow relaying only from trusted networks. Do not relay mails for
 
# domains for which the mail server is not responsible.
 
smtpd_relay_restrictions = permit_mynetworks reject_unauth_destination
0 comments (0 inline, 0 general)