home-server/roles/dmz_exim/tasks/main.yml

587 lines
16 KiB
YAML
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

---
# The home-server project produces a multi-purpose setup using Ansible.
# Copyright © 2018 Y. Gablin, under the GPL-3.0-or-later license.
# Full licensing information in the LICENSE file, or gnu.org/licences/gpl-3.0.txt if the file is missing.
### UPSTREAM BEGIN ⇒ ###
- name: pull prerequisites from upstream
include_role: name=etckeeper.inc allow_duplicates=true tasks_from=upstream.yml
vars:
msg: Exim
### ⇐ UPSTREAM BEGIN ###
- name: install software
package:
name: "{{item}}"
state: present
with_items:
- exim
- spamassassin
# sa-compile from spamassassin needs make, gcc.
- make
- gcc
### UPSTREAM END ⇒ ###
- name: merge upstream
include_role: name=etckeeper.inc allow_duplicates=true tasks_from=merge.yml
vars:
msg: Exim
### ⇐ UPSTREAM END ###
- name: prepare overriding exim settings
file:
name: /etc/systemd/system/exim.service.d
state: directory
mode: 0755
- name: secure exim systemd settings
copy:
content: |
[Service]
CapabilityBoundingSet=CAP_AUDIT_WRITE CAP_BLOCK_SUSPEND CAP_CHOWN CAP_FSETID CAP_IPC_LOCK CAP_LEASE CAP_LINUX_IMMUTABLE CAP_NET_BIND_SERVICE CAP_NET_RAW CAP_SETGID CAP_SETFCAP CAP_SETPCAP CAP_SETUID CAP_SYS_CHROOT CAP_SYS_NICE CAP_SYS_PACCT CAP_SYS_RAWIO CAP_WAKE_ALARM
PrivateTmp=true
PrivateDevices=true
ProtectSystem=full
ProtectHome=true
NoNewPrivileges=true
dest: "/etc/systemd/system/exim.service.d/secure-{{nickname}}.conf"
mode: 0644
notify:
- restart exim.service
- name: declare automatic updating and compilation of SpamAssassin rules
copy:
content: |
[Unit]
Description=Update and compile SpamAssassin rules
[Service]
User=root
Group=spamd
Type=oneshot
ExecStart=/usr/bin/vendor_perl/sa-update --allowplugins
# Exit status: 0 = updated, 1 = no updates available
SuccessExitStatus=0 1
ExecStart=/usr/bin/vendor_perl/sa-compile
SuccessExitStatus=0
dest: /etc/systemd/system/spamassassin-update.service
mode: 0644
notify:
- restart spamassassin-update.timer
- name: plan automatic updating and compilation of SpamAssassin rules
copy:
content: |
[Unit]
Description=Update and compile SpamAssassin rules
[Timer]
OnCalendar=daily
Persistent=true
[Install]
WantedBy=timers.target
dest: /etc/systemd/system/spamassassin-update.timer
mode: 0644
notify:
- restart spamassassin-update.timer
- name: prepare overriding spamassassin settings
file:
name: /etc/systemd/system/spamassassin.service.d
state: directory
mode: 0755
- name: make spamassassin take into account changes in rules
copy:
content: |
[Unit]
PartOf=spamassassin-update.service
Wants=spamassassin-update.service
After=spamassassin-update.service
dest: /etc/systemd/system/spamassassin.service.d/restart-when-update.conf
mode: 0644
notify:
- restart spamassassin-update.timer
- name: secure spamassassin systemd settings
copy:
content: |
[Service]
ExecStart=
ExecStart=/usr/bin/vendor_perl/spamd -x -u spamd -g spamd --listen=/run/shared_sockets/spamd
CapabilityBoundingSet=CAP_AUDIT_WRITE CAP_LEASE CAP_SETGID CAP_SETUID CAP_SYS_CHROOT
PrivateTmp=true
PrivateDevices=true
ProtectSystem=full
ProtectHome=true
NoNewPrivileges=true
dest: /etc/systemd/system/spamassassin.service.d/secure-{{nickname}}.conf
mode: 0644
notify:
- restart spamassassin.service
- name: make spamassassin trust local machines
lineinfile:
path: /etc/mail/spamassassin/local.cf
regexp: '^trusted_networks\s'
line: "trusted_networks {{net_trusted_ranges}}"
insertafter: '^# trusted_networks'
notify:
- restart spamassassin.service
- name: be less tolerent with spam
lineinfile:
path: /etc/mail/spamassassin/local.cf
regexp: '^required_score\s'
line: 'required_score 4.0'
insertafter: '^# required_score'
notify:
- restart spamassassin.service
- name: leave spamd when the network is trusted
lineinfile:
path: /etc/mail/spamassassin/local.cf
regexp: '^shortcircuit\s+ALL_TRUSTED\s'
line: 'shortcircuit ALL_TRUSTED on'
insertafter: '^# shortcircuit\s+ALL_TRUSTED'
notify:
- restart spamassassin.service
- name: Aliases LDIF
ldap_entry:
server_uri: ldapi://%2Frun%2Fshared_sockets%2Fldapi/
bind_dn: "cn=root,{{ldap_root}}"
bind_pw: "{{ldap_rootpw}}"
dn: 'ou=Aliases,{{ldap_root}}'
objectClass:
- top
- organizationalUnit
attributes:
ou: Aliases
- name: declare existing aliases
ldap_entry:
server_uri: ldapi://%2Frun%2Fshared_sockets%2Fldapi/
bind_dn: "cn=root,{{ldap_root}}"
bind_pw: "{{ldap_rootpw}}"
dn: "cn={{item.alias}},ou=Aliases,{{ldap_root}}"
objectClass:
- top
- nisMailAlias
attributes:
cn: "{{item.alias}}"
with_items: "{{mail_alias_memberships}}"
- name: declare existing aliases members
ldap_attr:
server_uri: ldapi://%2Frun%2Fshared_sockets%2Fldapi/
bind_dn: "cn=root,{{ldap_root}}"
bind_pw: "{{ldap_rootpw}}"
dn: "cn={{item.alias}},ou=Aliases,{{ldap_root}}"
name: rfc822MailMember
values: "{{item.member}}"
state: present
with_items: "{{mail_alias_memberships}}"
- name: declare “dmarc” in system-aliases file
lineinfile:
path: /etc/mail/aliases
regexp: '^(?:#\s*)?dmarc:'
line: "dmarc: postmaster"
- name: finalize system-aliases file
lineinfile:
path: /etc/mail/aliases
regexp: '^(?:#\s*)?root:'
line: "root: {{mail_forward_root_to}}"
- name: send DKIM private key
copy:
src: files/{{net_soa}}_dkim.privk.pem
dest: /etc/mail/{{net_soa}}_dkim.privk.pem
owner: exim
group: exim
mode: 0400
notify:
- restart exim.service
- name: set log destination
lineinfile:
path: /etc/mail/exim.conf
regexp: '^log_file_path\s*='
line: |
log_file_path = syslog
insertafter: 'MAIN CONFIGURATION SETTINGS'
notify:
- restart exim.service
- name: disable log dupplicates
lineinfile:
path: /etc/mail/exim.conf
regexp: '^syslog_duplication\s*='
line: |
syslog_duplication = false
insertafter: '^log_file_path\s*='
notify:
- restart exim.service
- name: set LDAP URL
lineinfile:
path: /etc/mail/exim.conf
regexp: '^ldap_default_servers\s*='
line: |
ldap_default_servers = /run/shared_sockets/ldapi : {{SafeZone}}
insertafter: '^syslog_duplication\s*='
notify:
- restart exim.service
- name: set local domains
lineinfile:
path: /etc/mail/exim.conf
regexp: '^domainlist\s+local_domains\s*='
line: >
domainlist local_domains = @ :
{{mail_local_domains | replace(' ', ' : ')}}
notify:
- restart exim.service
- name: set relay hosts
lineinfile:
path: /etc/mail/exim.conf
regexp: '^hostlist\s+relay_from_hosts\s*='
line: >
hostlist relay_from_hosts = <; ;
{{net_trusted_ranges | replace(' ', ' ; ')}}
notify:
- restart exim.service
- name: use a Unix socket for SpamAssassin
lineinfile:
path: /etc/mail/exim.conf
regexp: '^(?:#\s*)?spamd_address\s*='
line: 'spamd_address = /run/shared_sockets/spamd'
notify:
- restart exim.service
- name: advertise TLS
lineinfile:
path: /etc/mail/exim.conf
regexp: '^(?:#\s*)?tls_advertise_hosts\s*='
line: 'tls_advertise_hosts = *'
notify:
- restart exim.service
- name: set TLS parameters for OpenSSL
blockinfile:
path: /etc/mail/exim.conf
marker: '# {mark} OpenSSL parameters'
block: |
tls_require_ciphers = {{tls_ciphers}}
insertafter: '^tls_advertise_hosts\s*='
- name: set TLS certificate
lineinfile:
path: /etc/mail/exim.conf
regexp: '^(?:#\s*)?tls_certificate\s*='
line: 'tls_certificate = /etc/mail/exim.crt'
notify:
- restart exim.service
- name: set TLS key
lineinfile:
path: /etc/mail/exim.conf
regexp: '^(?:#\s*)?tls_privatekey\s*='
line: 'tls_privatekey = /etc/mail/exim.pem'
notify:
- restart exim.service
- name: set SMTP ports
lineinfile:
path: /etc/mail/exim.conf
regexp: '^(?:#\s*)?daemon_smtp_ports\s*='
line: 'daemon_smtp_ports = 25 : 465 : 587'
notify:
- restart exim.service
- name: set TLS port
lineinfile:
path: /etc/mail/exim.conf
regexp: '^(?:#\s*)?tls_on_connect_ports\s*='
line: 'tls_on_connect_ports = 465'
notify:
- restart exim.service
- name: set qualified domain
lineinfile:
path: /etc/mail/exim.conf
regexp: '^(?:#\s*)?qualify_domain\s*='
line: "qualify_domain = {{net_soa}}"
notify:
- restart exim.service
- name: disable reverse-DNS lookups
lineinfile:
path: /etc/mail/exim.conf
regexp: '^(?:#\s*)?host_lookup\s*='
line: '# host_lookup = *'
notify:
- restart exim.service
- name: enable lenient message decoding
lineinfile:
path: /etc/mail/exim.conf
regexp: '^(?:#\s*)?check_rfc2047_length\s*='
line: 'check_rfc2047_length = false'
notify:
- restart exim.service
- name: set more lenient checks for local email
replace:
path: /etc/mail/exim.conf
regexp: '(control\s*=\s*submission)\s*$'
replace: '\1/sender_retain'
notify:
- restart exim.service
- name: allow recipient verification through LMTP
replace:
path: /etc/mail/exim.conf
regexp: '#?(\s*require\s+verify\s*=\s*recipient)$'
replace: '\1/callout=no_cache'
notify:
- restart exim.service
- name: deny mail RCPT from SpamHaus SBL
blockinfile:
path: /etc/mail/exim.conf
marker: ' # {mark} SpamHaus SBL ACL'
block: |
deny message = rejected because $sender_host_address is in a \
black list at SpamHaus SBL
dnslists = sbl.spamhaus.org
insertbefore: '^\s*#\s*warn\s+dnslists\s*='
notify:
- restart exim.service
- name: check mail DATA with SpamAssassin
blockinfile:
path: /etc/mail/exim.conf
marker: ' # {mark} SpamAssassin ACL'
block: |
accept condition = ${if >={$message_size}{500k}{yes}{no}}
accept hosts = +relay_from_hosts
warn spam = nobody/defer_ok
add_header = X-Spam_score: $spam_score ($spam_bar)\n\
X-Spam_score_int: $spam_score_int
warn spam = nobody/defer_ok
add_header = X-Spam_report: $spam_report
condition = ${if >{$spam_score_int}{0}{1}{0}}
deny spam = nobody:true/defer_ok
message = This message scored $spam_score spam points.
condition = ${if >{$spam_score_int}{120}{1}{0}}
insertbefore: '^\s*#\s*warn\s+spam\s*='
notify:
- restart exim.service
# TODO: https://github.com/Exim/exim/wiki/SimpleGreylisting (with SPAM≥1.0)
- name: disable the dnslookup router
replace:
path: /etc/mail/exim.conf
regexp: '^dnslookup:\n(?:.+\n)*'
replace: |
# dnslookup:
# driver = dnslookup
# domains = ! +local_domains
# transport = remote_smtp
# ignore_target_hosts = <; 0.0.0.0 ; 127.0.0.0/8 ; ::1
# no_more
notify:
- restart exim.service
- name: enable the smarthost router
replace:
path: /etc/mail/exim.conf
regexp: '^#\s*smarthost:\n(?:.+\n)*'
replace: |
smarthost:
driver = manualroute
domains = ! +local_domains
transport = remote_smtp
route_list = * ISP.SMART.HOST
ignore_target_hosts = <; 0.0.0.0 ; 127.0.0.0/8 ; ::1
no_more
notify:
- restart exim.service
- name: set the smarthost hostname
lineinfile:
path: /etc/mail/exim.conf
regexp: '^(\s*route_list\s*=)'
backrefs: true
line: "\\1 * {{mail_smtp_smarthost}}"
notify:
- restart exim.service
- name: set IP addresses to be ignored
lineinfile:
path: /etc/mail/exim.conf
regexp: '^(\s*ignore_target_hosts\s*=.*::1)(?! ; {{mail_ignore_ip | replace(" ", " ; ")}}$)'
backrefs: true
line: "\\1 ; {{mail_ignore_ip | replace(' ', ' ; ')}}"
when:
- mail_ignore_ip != ""
notify:
- restart exim.service
# http://www.openldap.org/lists/openldap-software/200209/msg00792.html
# http://www.exim.org/exim-html-current/doc/html/spec_html/ch-file_and_database_lookups.html
# https://www.howtoforge.com/setting-up-a-mail-server-using-exim4-clamav-dovecot-spamassassin-and-many-more-on-debian-p3
- name: read aliases in OpenLDAP
blockinfile:
path: /etc/mail/exim.conf
marker: ' # {mark} OpenLDAP aliases'
block: |
ldap_aliases:
driver = redirect
allow_fail
allow_defer
data = ${lookup ldap \
{ldapi:///cn=${quote_ldap_dn:$local_part},ou=Aliases,{{ldap_root}}\
?rfc822MailMember?sub?\
(&(objectClass=nisMailAlias))} \
}
insertbefore: 'forwarding using traditional .forward'
notify:
- restart exim.service
- name: disable the userforward router
replace:
path: /etc/mail/exim.conf
regexp: '^userforward:\n(?:.+\n)*'
replace: |
#userforward:
# driver = redirect
# check_local_user
## local_part_suffix = +* : -*
## local_part_suffix_optional
# file = $home/.forward
## allow_filter
# no_verify
# no_expn
# check_ancestor
# file_transport = address_file
# pipe_transport = address_pipe
# reply_transport = address_reply
notify:
- restart exim.service
- name: disable the localuser router
replace:
path: /etc/mail/exim.conf
regexp: '^localuser:\n(?:.+\n)*'
replace: |
#localuser:
# driver = accept
# check_local_user
## local_part_suffix = +* : -*
## local_part_suffix_optional
# transport = local_delivery
# cannot_route_message = Unknown user
notify:
- restart exim.service
- name: add a router to LMTP
blockinfile:
path: /etc/mail/exim.conf
marker: ' # {mark} LMTP router'
block: |
lmtp_user:
debug_print = "R: lmtp_user for $local_part@$domain"
driver = manualroute
domains = +local_domains
transport = lmtp_transport
route_list = * {{SafeZone_IP}} byname
cannot_route_message = Unknown user
insertbefore: '^#localuser:'
notify:
- restart exim.service
- name: add a transport for LMTP
blockinfile:
path: /etc/mail/exim.conf
marker: ' # {mark} LMTP transport'
block: |
lmtp_transport:
driver = smtp
protocol = lmtp
rcpt_include_affixes
port = 24
insertbefore: '^# This transport is used'
notify:
- restart exim.service
- name: enable DKIM on outgoing emails
blockinfile:
path: /etc/mail/exim.conf
marker: ' # {mark} outgoing DKIM signing'
block: |
dkim_canon = relaxed
dkim_domain = {{net_soa}}
dkim_private_key = /etc/mail/{{net_soa}}_dkim.privk.pem
dkim_selector = {{mail_dkim_selector}}
insertafter: '^\s*driver\s*=\s*smtp\s*$'
notify:
- restart exim.service
- name: add authenticators based on LDAP
blockinfile:
path: /etc/mail/exim.conf
marker: ' # {mark} LDAP authentication'
block: |
plain_server:
driver = plaintext
public_name = PLAIN
server_prompts = :
server_condition = ${if ldapauth \
{user="uid=${quote_ldap_dn:$2},ou=Users,{{ldap_root}}" \
pass=${quote:$3} \
ldapi:///}{yes}{no}}
server_set_id = $2
login_server:
driver = plaintext
public_name = LOGIN
server_prompts = "Username:: : Password::"
server_condition = ${if ldapauth \
{user="uid=${quote_ldap_dn:$1},ou=Users,{{ldap_root}}" \
pass=${quote:$2} \
ldapi:///}{yes}{no}}
server_set_id = $1
insertafter: '^begin\s+authenticators'
notify:
- restart exim.service
- name: enable spamassassin updater
systemd:
daemon_reload: true
name: spamassassin-update.timer
enabled: true
- name: enable spamassassin
systemd:
daemon_reload: true
name: spamassassin.service
enabled: true
- name: enable exim
systemd:
daemon_reload: true
name: exim.service
enabled: true
### LOCAL COMMIT ⇒ ###
- name: commit local changes
include_role: name=etckeeper.inc allow_duplicates=true tasks_from=local.yml
vars:
msg: Exim
### ⇐ LOCAL COMMIT ###
- meta: flush_handlers