Changeset - 441a70c073b9
[Not reviewed]
0 9 0
Branko Majic (branko) - 1 month ago 2024-03-07 22:41:28
branko@majic.rs
MAR-232: Switch to using IP addreses in firewall rules for mail_forwarder role:

- Perform lookups on managed machine for the passed-in SMTP relay
host, and use those values when populating the firewall rules.
9 files changed with 77 insertions and 24 deletions:
0 comments (0 inline, 0 general)
docs/about.rst
Show inline comments
 
@@ -17,10 +17,9 @@ supported releases, see :ref:`rolereference`.
 
At the moment, the roles have been written for and tested against **Ansible
 
2.9.x**.
 

	
 
The roles also utilise the ``dig`` and ``ipv4/ipv6`` lookup plugins
 
which require ``dnspython`` and ``netaddr`` packages (respectively) to
 
be installed. Make sure you have the packages available on controller
 
machine.
 
The roles also utilise the ``ipv4/ipv6`` lookup plugins which require
 
``netaddr`` package to be installed. Make sure you have the packages
 
available on controller machine.
 

	
 

	
 
Why were these roles created?
docs/index.rst
Show inline comments
 
@@ -17,10 +17,9 @@ supported releases, see :ref:`rolereference`.
 
At the moment, the roles have been written for and tested against **Ansible
 
2.9.x**.
 

	
 
The roles also utilise the ``dig`` and ``ipv4/ipv6`` lookup plugins
 
which require ``dnspython`` and ``netaddr`` packages (respectively) to
 
be installed. Make sure you have the packages available on controller
 
machine.
 
The roles also utilise the ``ipv4/ipv6`` lookup plugins which require
 
``netaddr`` package to be installed. Make sure you have the packages
 
available on controller machine.
 

	
 

	
 
Contents
docs/releasenotes.rst
Show inline comments
 
@@ -15,6 +15,8 @@ Debian 12 Bookworm. Some minor improvements and fixes.
 
  * Dropped support for Debian 10 (Buster).
 
  * Added support for Debian 12 (Bookworm).
 
  * ``netaddr`` Python package is now required for using the roles.
 
  * ``dnspython`` Python package is no longer required for using the
 
    roles.
 

	
 
* ``backup_client`` role
 

	
 
@@ -43,9 +45,7 @@ Debian 12 Bookworm. Some minor improvements and fixes.
 
  * Parameter ``maintenance_allowed_hosts`` has been dropped and
 
    replaced with parameter ``maintenance_allowed_sources``. The new
 
    parameter expects a list of IPv4 and IPv6 addresses (or
 
    subnets). Resolvable names can no longer be specified (and this
 
    particular role no longe relies on presence of the ``dnspython``
 
    package).
 
    subnets). Resolvable names can no longer be specified.
 

	
 
  * NTP server configuration is now based on use of pools instead of
 
    servers. Parameter ``ntp_servers`` has been deprecated and
 
@@ -61,6 +61,20 @@ Debian 12 Bookworm. Some minor improvements and fixes.
 
    LDAP server logs can be read via ``journalctl -u slapd`` when
 
    necessary.
 

	
 
* ``mail_forwarder`` role
 

	
 
  * Firewall rules for incoming connections from the SMTP relay server
 
    are now based on relay's IPv4 and IPv6 addresses as resolved on
 
    managed machine during deployment time.
 

	
 
    In case the SMTP relay server's IP addresses change, the role
 
    needs to get reapplied against managed machines for those changes
 
    to take place.
 

	
 
    This change in behaviour was introduced to avoid firewall-related
 
    errors due to inability to resolve names via DNS servers during
 
    boot time.
 

	
 
* ``mail_server`` role
 

	
 
  * Parameter ``mail_server_tls_protocols`` has been dropped and
docs/rolereference.rst
Show inline comments
 
@@ -1315,8 +1315,15 @@ The role implements the following:
 
* 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.
 
* Configures firewall to accept SMTP connections from SMTP relay (if
 
  one has been configured). This allows for delivery of bounced
 
  e-mails.
 

	
 
  .. note::
 
     Firewall rules are based on IPv4 and IPv6 addresses resolved via
 
     managed server at time of deployment. If the SMTP relay changes
 
     its IP addresess, this role needs to be reapplied against the
 
     managed machines.
 

	
 
Postfix is configured as follows:
 

	
docs/usage.rst
Show inline comments
 
@@ -148,12 +148,11 @@ packages, and to prepare the environment a bit on the Ansible server:
 
     mkdir ~/mysite/
 
     mkvirtualenv -p /usr/bin/python3 -a ~/mysite/ mysite
 
     pip install -U pip setuptools
 
     pip install 'ansible~=2.9.0' dnspython netaddr
 
     pip install 'ansible~=2.9.0' netaddr
 

	
 
.. warning::
 
   The ``dnspython`` and ``netaddr`` packages are needed since they
 
   are used internally by some of the roles for the ``dig`` and
 
   ``ipv4/ipv6`` lookup plugins.
 
   The ``netaddr`` package is needed for ``ipv4/ipv6`` lookup plugins
 
   which is used internally by some of the roles.
 

	
 

	
 
Cloning the *Majic Ansible Roles*
requirements.in
Show inline comments
 
ansible~=2.9.0
 
defusedxml
 
dnspython
 
gimmecert~=0.5.0
 
molecule~=2.22.0
 
netaddr
requirements.txt
Show inline comments
 
@@ -68,8 +68,6 @@ defusedxml==0.7.1
 
    # via -r requirements.in
 
distlib==0.3.8
 
    # via virtualenv
 
dnspython==2.6.1
 
    # via -r requirements.in
 
docutils==0.20.1
 
    # via
 
    #   sphinx
 
@@ -126,7 +124,7 @@ pathspec==0.12.1
 
    # via yamllint
 
pexpect==4.9.0
 
    # via molecule
 
pip-tools==7.4.0
 
pip-tools==7.4.1
 
    # via -r requirements.in
 
platformdirs==4.2.0
 
    # via virtualenv
roles/mail_forwarder/tasks/main.yml
Show inline comments
 
@@ -70,6 +70,38 @@
 
    state: started
 
    enabled: true
 

	
 
- name: Retrieve IPv4 addresses of SMTP relay host
 
  shell: "getent ahostsv4 '{{ smtp_relay_host }}' | awk '{ print $1 }' | sort -u"  # noqa 306
 
  # [306] Shells that use pipes should set the pipefail option
 
  #   The getent ahostsv4 command has non-zero exit code if the
 
  #   supplies name cannot be resolved. However, that is a valid
 
  #   use-case for extracting this information. It effectively means
 
  #   that no IPv4 firewall rules will be deployed for allowing
 
  #   incoming connections from the SMTP relay host.
 
  changed_when: false
 
  register: smtp_relay_host_ipv4
 

	
 
- name: Retrieve IPv6 addresses of SMTP relay host
 
  shell: "getent ahostsv6 '{{ smtp_relay_host }}' | awk '{ print $1 }' | grep -v '^::ffff:' | sort -u"  # noqa 306
 
  # [306] Shells that use pipes should set the pipefail option
 
  #   The getent ahostsv6 command has non-zero exit code if the
 
  #   supplies name cannot be resolved. However, that is a valid
 
  #   use-case for extracting this information. It effectively means
 
  #   that no IPv6 firewall rules will be deployed for allowing
 
  #   incoming connections from the SMTP relay host.
 
  changed_when: false
 
  register: smtp_relay_host_ipv6
 

	
 
- name: Normalise the SMTP relay host IPv4 addresses variable
 
  set_fact:
 
    smtp_relay_host_ipv4: "{{ smtp_relay_host_ipv4.stdout_lines | reject('equalto', '') | list }}"
 
  when: "smtp_relay_host | length != 0"
 

	
 
- name: Normalise the SMTP relay host IPv6 addresses variable
 
  set_fact:
 
    smtp_relay_host_ipv6: "{{ smtp_relay_host_ipv6.stdout_lines | reject('equalto', '') | list }}"
 
  when: "smtp_relay_host | length != 0"
 

	
 
- name: Deploy firewall configuration for mail forwader
 
  template:
 
    src: "ferm_mail.conf.j2"
roles/mail_forwarder/templates/ferm_mail.conf.j2
Show inline comments
 
{% if smtp_relay_host and smtp_from_relay_allowed %}
 
{% if smtp_relay_host_ipv4 %}
 
domain ip {
 
    # Accept incoming connections on port 25 from SMTP relay host.
 
    table filter {
 
        chain INPUT {
 
            # SMTP for server communication.
 
            proto tcp dport 25 {
 
                saddr {{ smtp_relay_host }} ACCEPT;
 
{% for address in smtp_relay_host_ipv4 %}
 
                saddr {{ address }} ACCEPT;
 
{% endfor %}
 
            }
 
        }
 
    }
 
}
 
{% endif %}
 

	
 
{% if lookup('dig', smtp_relay_host + '/AAAA') not in ['NXDOMAIN', ''] %}
 
{% if smtp_relay_host_ipv6 %}
 
domain ip6 {
 
    # Accept incoming connections on port 25 from SMTP relay host.
 
    table filter {
 
        chain INPUT {
 
            # SMTP for server communication.
 
            proto tcp dport 25 {
 
                saddr {{ smtp_relay_host }} ACCEPT;
 
{% for address in smtp_relay_host_ipv6 %}
 
                saddr {{ address }} ACCEPT;
 
{% endfor %}
 
            }
 
        }
 
    }
0 comments (0 inline, 0 general)