diff --git a/defaults/main.yml b/defaults/main.yml index d9d0ff7..ca9a798 100644 --- a/defaults/main.yml +++ b/defaults/main.yml @@ -54,6 +54,7 @@ postfix_reject_unknown_sender_domain: True ############################################################################# postfix_relay_server: False # +## Milter (antispam, antivirus) postfix_use_milter: False postfix_milter_connect_timeout: '30s' postfix_milter_command_timeout: '30s' @@ -65,6 +66,40 @@ postfix_clamav_milter: False postfix_clamav_milter_socket: 'unix:/run/clamav-milter/clamav-milter.socket' # Specify accept, reject, tempfail, quarantine postfix_milter_action: tempfail +## SPF policyd +postfix_spf_policy_install: False +postfix_spy_deb_pkg: + - 'postfix-policyd-spf-python' +postfix_spy_el_pkg: + - 'pypolicyd-spf' +postfix_spf_policy_skip_addresses: '127.0.0.0/8,::ffff:127.0.0.0/104,::1' +# From 0 to 4 +postfix_spf_policy_debug_level: 1 +# Set to 0 for test only mode +postfix_spf_policy_default_seed: 1 +postfix_spf_perm_error_reject: False +postfix_spf_temp_error_defer: False +# HELO check rejection policy. Options are: +# HELO_reject = SPF_Not_Pass (default) - Reject if result not Pass/None/Tempfail. +# HELO_reject = Softfail - Reject if result Softfail and Fail +# HELO_reject = Fail - Reject on HELO Fail +# HELO_reject = Null - Only reject HELO Fail for Null sender (SPF Classic) +# HELO_reject = False - Never reject/defer on HELO, append header only. +# HELO_reject = No_Check - Never check HELO. +postfix_spf_policy_helo_reject: 'SPF_Not_Pass' +# Mail From rejection policy. Options are: +# Mail_From_reject = SPF_Not_Pass - Reject if result not Pass/None/Tempfail. +# Mail_From_reject = Softfail - Reject if result Softfail and Fail +# Mail_From_reject = Fail - Reject on Mail From Fail (default) +# Mail_From_reject = False - Never reject/defer on Mail From, append header only +# Mail_From_reject = No_Check - Never check Mail From/Return Path. +postfix_spf_policy_mail_from_reject: 'Fail' +# CIDR notation, 192.168.0.0/31,192.168.1.12 +postfix_spf_policy_whitelist: '' +postfix_spf_policy_domain_whitelist: '' +postfix_spf_policy_lookup_time: 20 +postfix_spf_policy_void_limit: 2 + ############################################################################# # SMTP server that not accept authenticated clients. ############################################################################# diff --git a/tasks/main.yml b/tasks/main.yml index 52033f9..85b0050 100644 --- a/tasks/main.yml +++ b/tasks/main.yml @@ -1,5 +1,7 @@ --- - import_tasks: smtp-common-packages.yml +- import_tasks: postfix_spf_policy.yml + when: postfix_spf_policy_install - import_tasks: smtp-configuration.yml - import_tasks: postfix_pflogsumm.yml - import_tasks: postfix_firewalld.yml diff --git a/tasks/postfix_spf_policy.yml b/tasks/postfix_spf_policy.yml new file mode 100644 index 0000000..303a89e --- /dev/null +++ b/tasks/postfix_spf_policy.yml @@ -0,0 +1,54 @@ +--- +- name: Set the spf policy's environment and install the packages on EL + block: + - name: Set the spf policy conf file path in EL distributions + set_fact: + postfix_spf_policy_conf_dir: '/etc/python-policyd-spf' + postfix_spf_policy_conf_file: '/etc/python-policyd-spf/policyd-spf.conf' + postfix_spf_policy_exec: '/usr/libexec/postfix/policyd-spf' + + - name: The EL package does not provide a user. Create one + ansible.builtin.user: + name: policyd-spf + home: '{{ postfix_spf_policy_conf_dir }}' + create_home: no + system: yes + shell: /sbin/nologin + + - name: Install the postfix-perl-scripts package on EL + ansible.builtin.yum: + pkg: '{{ postfix_spy_el_pkg }}' + state: present + + when: ansible_distribution_file_variety == "RedHat" + tags: [ 'postfix', 'postfix_spf_policy' ] + +- name: Set the spf policy's environment and install the packages on deb + block: + - name: Set the spf policy conf file path in deb distributions + set_fact: + postfix_spf_policy_conf_dir: '/etc/policyd-spf' + postfix_spf_policy_conf_file: '/etc/policyd-spf/policyd-spf.conf' + postfix_spf_policy_exec: '/usr/bin/policyd-spf' + + - name: Install the policyd-spf package on deb + ansible.builtin.apt: + pkg: '{{ postfix_spy_deb_pkg }}' + state: present + cache_valid_time: 1800 + + when: ansible_distribution_file_variety == "Debian" + tags: [ 'postfix', 'postfix_spf_policy' ] + +- name: Configure policyd-spf + block: + - name: Install the policyd configuration + ansible.builtin.template: + src: policyd-spf.conf.j2 + dest: '{{ postfix_spf_policy_conf_file }}' + owner: root + group: root + mode: 0644 + + tags: [ 'postfix', 'postfix_spf_policy' ] + diff --git a/tasks/smtp-configuration.yml b/tasks/smtp-configuration.yml index f6ebdb8..65e89e9 100644 --- a/tasks/smtp-configuration.yml +++ b/tasks/smtp-configuration.yml @@ -3,14 +3,14 @@ block: - 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 + notify: Restart postfix - name: The postfix master.cf file adapts to the service role template: src=master.cf.j2 dest=/etc/postfix/master.cf owner=root group=root mode=0444 - register: postfix_master_restart_needed + notify: Restart postfix when: postfix_enabled | bool - tags: [ 'postfix', 'postfix_conf' ] + tags: [ 'postfix', 'postfix_conf', 'postfix_spf_policy' ] - name: Postfix maps installation block: @@ -46,9 +46,8 @@ - name: Ensure that postfix is started and enabled service: name=postfix state=started enabled=yes - - name: Restart postfix - service: name=postfix state=restarted - when: ( postfix_main_restart_needed is changed ) or ( postfix_master_restart_needed is changed ) - when: postfix_enabled | bool tags: [ 'postfix', 'postfix_conf' ] + +- name: Flush all the handlers related to postfix + ansible.builtin.meta: flush_handlers \ No newline at end of file diff --git a/templates/main.cf.j2 b/templates/main.cf.j2 index c579bce..9c98f7e 100644 --- a/templates/main.cf.j2 +++ b/templates/main.cf.j2 @@ -591,6 +591,9 @@ smtpd_recipient_restrictions = {% for recipient_rule in postfix_smtpd_server_restrictions %} {{ recipient_rule }} {% endfor %} +{% if postfix_spf_policy_install %} + check_policy_service unix:private/policyd-spf +{% endif %} {% if postfix_spamhaus_dbl_enabled %} reject_rhsbl_helo dbl.spamhaus.org reject_rhsbl_reverse_client dbl.spamhaus.org diff --git a/templates/master.cf.j2 b/templates/master.cf.j2 index 2fc6f16..4a73612 100644 --- a/templates/master.cf.j2 +++ b/templates/master.cf.j2 @@ -88,6 +88,15 @@ scache unix - - n - 1 scache # agent. See the pipe(8) man page for information about ${recipient} # and other message envelope options. # ==================================================================== +{% if postfix_spf_policy_install %} +# +# policyd-spf. The package must be installed and configured +# +policyd-spf unix - n n - 0 spawn + user=policyd-spf argv={{ postfix_spf_policy_exec }} {{ postfix_spf_policy_conf_file }} +# +# ==================================================================== +{% endif %} # # maildrop. See the Postfix MAILDROP_README file for details. # Also specify in main.cf: maildrop_destination_recipient_limit=1 diff --git a/templates/policyd-spf.conf.j2 b/templates/policyd-spf.conf.j2 new file mode 100644 index 0000000..dbe123b --- /dev/null +++ b/templates/policyd-spf.conf.j2 @@ -0,0 +1,20 @@ +# For a fully commented sample config file see policyd-spf.conf.commented + +debugLevel = {{ postfix_spf_policy_debug_level }} +defaultSeedOnly = {{ postfix_spf_policy_default_seed }} + +HELO_reject = {{ postfix_spf_policy_helo_reject }} +Mail_From_reject = {{ postfix_spf_policy_mail_from_reject }} + +PermError_reject = {{ postfix_spf_perm_error_reject }} +TempError_Defer = {{ postfix_spf_temp_error_defer }} + +skip_addresses = {{ postfix_spf_policy_skip_addresses}} +{% if postfix_spf_policy_whitelist != '' %} +Whitelist = {{ postfix_spf_policy_whitelist }} +{% endif %} +{% if postfix_spf_policy_domain_whitelist != '' %} +Domain_Whitelist = {{ postfix_spf_policy_domain_whitelist }} +{% endif %} +Lookup_Time = {{ postfix_spf_policy_lookup_time }} +Void_Limit = {{ postfix_spf_policy_void_limit }}