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

587 lines
16 KiB
YAML
Raw Normal View History

2018-09-03 20:06:05 +02:00
---
# 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
2018-09-03 20:06:05 +02:00
domains = +local_domains
transport = lmtp_transport
route_list = * {{SafeZone_IP}} byname
2018-09-03 20:06:05 +02:00
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
2018-09-03 20:06:05 +02:00
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