diff --git a/pillar/secrets/dkim.sls.sample b/pillar/secrets/dkim.sls.sample new file mode 100644 index 0000000..0e4832e --- /dev/null +++ b/pillar/secrets/dkim.sls.sample @@ -0,0 +1,25 @@ +dkim: + dkim_bear-cave: | + -----BEGIN OPENSSH PRIVATE KEY----- + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB + CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC + DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD + EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE== + -----END OPENSSH PRIVATE KEY----- + dkim_cryhavoc: | + -----BEGIN OPENSSH PRIVATE KEY----- + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB + CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC + DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD + EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE== + -----END OPENSSH PRIVATE KEY----- + dkim_lunch: | + -----BEGIN OPENSSH PRIVATE KEY----- + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB + CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC + DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD + EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE== + -----END OPENSSH PRIVATE KEY----- diff --git a/pillar/top.sls b/pillar/top.sls index 2564c9f..3777ed9 100644 --- a/pillar/top.sls +++ b/pillar/top.sls @@ -4,6 +4,7 @@ base: - secrets/mariadb - secrets/wordpress 'scabbers.lunch.org.uk': + - secrets/dkim - secrets/dnsapi - secrets/gitea - secrets/webmail diff --git a/states/debian/init.sls b/states/debian/init.sls index 3081d28..2d3291c 100644 --- a/states/debian/init.sls +++ b/states/debian/init.sls @@ -1,3 +1,9 @@ +bullseye_backports: + pkgrepo.managed: + - name: deb http://deb.debian.org/debian bullseye-backports main + - dist: bullseye-backports + - file: /etc/apt/sources.list.d/bullseye-backports.list + deploy_sshd_config: file.managed: - name: /etc/ssh/sshd_config diff --git a/states/email/dovecot.sls b/states/email/dovecot.sls new file mode 100644 index 0000000..61af949 --- /dev/null +++ b/states/email/dovecot.sls @@ -0,0 +1,29 @@ +dovecot: + pkg.installed: + - pkgs: + - dovecot-core + - dovecot-imapd + - dovecot-sieve + - dovecot-managesieved + +dovecot_certs_group: + group.present: + - name: ssl-cert + - system: true + - addusers: + - dovecot + +dovecot_conf: + file.managed: + - mode: 0644 + - names: + - /etc/dovecot/local.conf: + - source: salt://email/dovecot_local.conf + +dovecot_service: + service.running: + - name: dovecot + - enable: true + - watch: + - pkg: dovecot + - file: /etc/dovecot/local.conf diff --git a/states/email/dovecot_local.conf b/states/email/dovecot_local.conf new file mode 100644 index 0000000..fdd30a3 --- /dev/null +++ b/states/email/dovecot_local.conf @@ -0,0 +1,20 @@ +# We use Maildir. +mail_location = maildir:~/Maildir + +# Require SSL for all auth. +ssl = required + +# SSL certificate locations. +ssl_cert = !LEYm9[LF0 diff --git a/states/email/exim4/conf.d/main/20_localconfig b/states/email/exim4/conf.d/main/20_localconfig new file mode 100644 index 0000000..fcc5c9d --- /dev/null +++ b/states/email/exim4/conf.d/main/20_localconfig @@ -0,0 +1,13 @@ +# Use rspamd as spam scanner. +spamd_address = 127.0.0.1 11333 variant=rspamd + +# Timeout for virus and spam scans +local_scan_timeout = 4m + +# Allow all users to see mail queue +no_queue_list_requires_admin + +# Listen in ports 25, 465 and 587. +daemon_smtp_ports = smtp : submission : submissions +tls_on_connect_ports = submissions + diff --git a/states/email/exim4/conf.d/router/180_srs b/states/email/exim4/conf.d/router/180_srs new file mode 100644 index 0000000..a2011e0 --- /dev/null +++ b/states/email/exim4/conf.d/router/180_srs @@ -0,0 +1,24 @@ + outbound: + driver = dnslookup + # if outbound, and forwarding has been done, use an alternate transport + domains = ! +local_domains + transport = ${if eq {$local_part@$domain} \ + {$original_local_part@$original_domain} \ + {remote_smtp} {remote_forwarded_smtp}} + + inbound_srs: + driver = redirect + senders = : + domains = +local_domains + # detect inbound bounces which are SRS'd, and decode them + condition = ${if inbound_srs {$local_part} {SRS_SECRET}} + data = $srs_recipient + + inbound_srs_failure: + driver = redirect + senders = : + domains = +local_domains + # detect inbound bounces which look SRS'd but are invalid + condition = ${if inbound_srs {$local_part} {}} + allow_fail + data = :fail: Invalid SRS recipient address diff --git a/states/email/exim4/conf.d/router/390_throwaway_local_part b/states/email/exim4/conf.d/router/390_throwaway_local_part new file mode 100644 index 0000000..f008d6b --- /dev/null +++ b/states/email/exim4/conf.d/router/390_throwaway_local_part @@ -0,0 +1,12 @@ +# Allow a throwaway suffix to the local part. Might help spot who sells +# email addresses. +suffix_rewrite: + driver = redirect + allow_defer + allow_fail + data = ${local_part}@${domain} + local_part_suffix = "_*" + local_part_suffix_optional + qualify_preserve_domain + retry_use_local_part + diff --git a/states/email/exim4/conf.d/router/980_local_domain_aliases b/states/email/exim4/conf.d/router/980_local_domain_aliases new file mode 100644 index 0000000..b3177e4 --- /dev/null +++ b/states/email/exim4/conf.d/router/980_local_domain_aliases @@ -0,0 +1,35 @@ + +# cryhavoc.org.uk has its own aliases. These are separate to the system +# ones - see system_aliases. +cryhavoc_aliases: + driver = redirect + allow_defer + allow_fail + data = ${lookup{$local_part}lsearch{/etc/aliases.cryhavoc.org.uk}} + domains = cryhavoc.org.uk + qualify_preserve_domain + pipe_transport = address_pipe + no_more + +# cowboybuilder.org.uk has its own aliases. These are separate to the system +# ones - see system_aliases. +cowboybuilder_aliases: + driver = redirect + allow_defer + allow_fail + data = ${lookup{$local_part}lsearch{/etc/aliases.cowboybuilder.org.uk}} + domains = cowboybuilder.org.uk + qualify_preserve_domain + pipe_transport = address_pipe + no_more + +# lunch.org.uk has its own aliases. These are separate to the system +# ones - see system_aliases. +lunch_aliases: + driver = redirect + allow_defer + allow_fail + data = ${lookup{$local_part}lsearch{/etc/aliases.lunch.org.uk}} + domains = lunch.org.uk + qualify_preserve_domain + retry_use_local_part diff --git a/states/email/exim4/conf.d/transport/30_dovecot_home b/states/email/exim4/conf.d/transport/30_dovecot_home new file mode 100644 index 0000000..0276592 --- /dev/null +++ b/states/email/exim4/conf.d/transport/30_dovecot_home @@ -0,0 +1,16 @@ + +# Use this to deliver to system users. +# Exim runs this as the user from the local_user router. +dovecot_home: + debug_print = "T: dovecot_home for $local_part@$domain" + driver = pipe + #command = sh -c "/usr/bin/bogofilter -e -u -p | /usr/lib/dovecot/deliver" + command = /usr/lib/dovecot/deliver + message_prefix = + message_suffix = + log_output + delivery_date_add + envelope_to_add + return_path_add + temp_errors = 64 : 69 : 70: 71 : 72 : 73 : 74 : 75 : 78 + diff --git a/states/email/exim4/conf.d/transport/32_srs b/states/email/exim4/conf.d/transport/32_srs new file mode 100644 index 0000000..8cc7678 --- /dev/null +++ b/states/email/exim4/conf.d/transport/32_srs @@ -0,0 +1,7 @@ + # transport; should look like the non-forward outbound + # one, plus the max_rcpt and return_path options + remote_forwarded_smtp: + driver = smtp + # modify the envelope from, for mails that we forward + max_rcpt = 1 + return_path = ${srs_encode {SRS_SECRET} {$return_path} {$original_domain}} diff --git a/states/email/exim4/dkim/20160621.bear-cave.org.uk.pem.txt b/states/email/exim4/dkim/20160621.bear-cave.org.uk.pem.txt new file mode 100644 index 0000000..0a36bd8 --- /dev/null +++ b/states/email/exim4/dkim/20160621.bear-cave.org.uk.pem.txt @@ -0,0 +1 @@ +k=rsa;p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC97rpW4HWK3q4TIjQnWO6WQZxa1EPPRCJJp3yYcjej8ierPPA420RWm3hyUbfPvwN9ynUXPVfrYYj7FJWMR8W3/dGJGOEjaBvL4pITwSg5WZt/7fDpGYkro4P//TnMMcF3iRAOm+XQywatNISuBYKQvOdy16Lw0XQyhV37pt0ixwIDAQAB diff --git a/states/email/exim4/dkim/20160621.cryhavoc.org.uk.pem.txt b/states/email/exim4/dkim/20160621.cryhavoc.org.uk.pem.txt new file mode 100644 index 0000000..64aa471 --- /dev/null +++ b/states/email/exim4/dkim/20160621.cryhavoc.org.uk.pem.txt @@ -0,0 +1 @@ +k=rsa;p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDoEgY4ekHBKJFey4JtZOO9K0bc25aYKGZiUMd+ESgwZfB3uP0JYxdII8CKLYpHFopmPs8mBW9pNs9L2Iyl6U4v4EE+LwHAhz7uZJfpLylmjQrfb9x72AQONGb4AiK7drc4jbcHr80gMorr27RE9RuYe00U4HdERGwjWcU7rJaRzQIDAQAB diff --git a/states/email/exim4/dkim/20160621.lunch.org.uk.pem.txt b/states/email/exim4/dkim/20160621.lunch.org.uk.pem.txt new file mode 100644 index 0000000..d6947e5 --- /dev/null +++ b/states/email/exim4/dkim/20160621.lunch.org.uk.pem.txt @@ -0,0 +1 @@ +k=rsa;p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDT6tLjGtCGeZz7MtLq2AazdP7CojC1Vk6CrY+qvM7/rdhIaL++y28+l6WYQhEO0+0kUYNtGewjhvUuq9nEVPvTEh370xOOSDlfAsMTZXZnJFmZGVDegF8mbOg+CQSWqmKRPCmDFsTy1ablh9JnxCIk6q/hiMLfsM1qEO51Wafw/wIDAQAB diff --git a/states/email/exim4/dkim/bear-cave.org.uk.pem b/states/email/exim4/dkim/bear-cave.org.uk.pem new file mode 100644 index 0000000..e35a4a0 --- /dev/null +++ b/states/email/exim4/dkim/bear-cave.org.uk.pem @@ -0,0 +1,6 @@ +-----BEGIN PUBLIC KEY----- +MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC97rpW4HWK3q4TIjQnWO6WQZxa +1EPPRCJJp3yYcjej8ierPPA420RWm3hyUbfPvwN9ynUXPVfrYYj7FJWMR8W3/dGJ +GOEjaBvL4pITwSg5WZt/7fDpGYkro4P//TnMMcF3iRAOm+XQywatNISuBYKQvOdy +16Lw0XQyhV37pt0ixwIDAQAB +-----END PUBLIC KEY----- diff --git a/states/email/exim4/dkim/cryhavoc.org.uk.pem b/states/email/exim4/dkim/cryhavoc.org.uk.pem new file mode 100644 index 0000000..02aa642 --- /dev/null +++ b/states/email/exim4/dkim/cryhavoc.org.uk.pem @@ -0,0 +1,6 @@ +-----BEGIN PUBLIC KEY----- +MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDoEgY4ekHBKJFey4JtZOO9K0bc +25aYKGZiUMd+ESgwZfB3uP0JYxdII8CKLYpHFopmPs8mBW9pNs9L2Iyl6U4v4EE+ +LwHAhz7uZJfpLylmjQrfb9x72AQONGb4AiK7drc4jbcHr80gMorr27RE9RuYe00U +4HdERGwjWcU7rJaRzQIDAQAB +-----END PUBLIC KEY----- diff --git a/states/email/exim4/dkim/lunch.org.uk.pem b/states/email/exim4/dkim/lunch.org.uk.pem new file mode 100644 index 0000000..06c2be6 --- /dev/null +++ b/states/email/exim4/dkim/lunch.org.uk.pem @@ -0,0 +1,6 @@ +-----BEGIN PUBLIC KEY----- +MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDT6tLjGtCGeZz7MtLq2AazdP7C +ojC1Vk6CrY+qvM7/rdhIaL++y28+l6WYQhEO0+0kUYNtGewjhvUuq9nEVPvTEh37 +0xOOSDlfAsMTZXZnJFmZGVDegF8mbOg+CQSWqmKRPCmDFsTy1ablh9JnxCIk6q/h +iMLfsM1qEO51Wafw/wIDAQAB +-----END PUBLIC KEY----- diff --git a/states/email/exim4/local_check_data b/states/email/exim4/local_check_data new file mode 100644 index 0000000..2c7bb38 --- /dev/null +++ b/states/email/exim4/local_check_data @@ -0,0 +1,41 @@ + # From rspamd docs. + + # skip scanning for authenticated users (if desired?) + accept authenticated = * + + # scan the message with rspamd + warn spam = Debian-exim:true + # This will set variables as follows: + # $spam_action is the action recommended by rspamd + # $spam_score is the message score (we unlikely need it) + # $spam_score_int is spam score multiplied by 10 + # $spam_report lists symbols matched & protocol messages + # $spam_bar is a visual indicator of spam/ham level + + # use greylisting available in rspamd v1.3+ + #defer message = Please try again later + # condition = ${if eq{$spam_action}{soft reject}} + + #deny message = Message discarded as high-probability spam + # condition = ${if eq{$spam_action}{reject}} + + # Remove foreign headers + warn remove_header = x-spam-bar : x-spam-score : x-spam-report : x-spam-status + + # add spam-score and spam-report header when "add header" action is recommended by rspamd + warn + condition = ${if eq{$spam_action}{add header}} + add_header = X-Spam-Score: $spam_score ($spam_bar) + add_header = X-Spam-Report: $spam_report + + # add x-spam-status header if message is not ham + warn + ! condition = ${if match{$spam_action}{^no action\$|^greylist\$}} + add_header = X-Spam-Status: Yes + + # add x-spam-bar header if score is positive + warn + condition = ${if >{$spam_score_int}{0}} + add_header = X-Spam-Bar: $spam_bar + + diff --git a/states/email/exim4/update-exim4.conf.conf b/states/email/exim4/update-exim4.conf.conf new file mode 100644 index 0000000..c58ddd5 --- /dev/null +++ b/states/email/exim4/update-exim4.conf.conf @@ -0,0 +1,31 @@ +# /etc/exim4/update-exim4.conf.conf +# +# Edit this file and /etc/mailname by hand and execute update-exim4.conf +# yourself or use 'dpkg-reconfigure exim4-config' +# +# Please note that this is _not_ a dpkg-conffile and that automatic changes +# to this file might happen. The code handling this will honor your local +# changes, so this is usually fine, but will break local schemes that mess +# around with multiple versions of the file. +# +# update-exim4.conf uses this file to determine variable values to replace +# the DEBCONFsomethingDEBCONF strings in the configuration template files. +# +# Most settings found in here do have corresponding questions in the +# Debconf configuration, but not all of them. +# +# This is a Debian specific file + +dc_eximconfig_configtype='smarthost' +dc_other_hostnames='bear-cave.org.uk:*.bear-cave.org.uk:lunch.org.uk:*.lunch.org.uk:cryhavoc.org.uk:cowboybuilder.org.uk:oxfordbeginnersession.org.uk' +dc_local_interfaces='' +dc_readhost='' +dc_relay_domains='' +dc_minimaldns='false' +dc_relay_nets='' +dc_smarthost='smtpout.mythic-beasts.com' +CFILEMODE='644' +dc_use_split_config='true' +dc_hide_mailname='false' +dc_mailname_in_oh='true' +dc_localdelivery='dovecot_home' diff --git a/states/email/init.sls b/states/email/init.sls new file mode 100644 index 0000000..77c2cd5 --- /dev/null +++ b/states/email/init.sls @@ -0,0 +1,4 @@ +include: + - email/dovecot + - email/rspamd + - email/exim4 diff --git a/states/email/rspamd.sls b/states/email/rspamd.sls new file mode 100644 index 0000000..14e8134 --- /dev/null +++ b/states/email/rspamd.sls @@ -0,0 +1,20 @@ +# Stock bullseye rspamd doesn't start. +rspamd: + pkg.installed: + - name: rspamd + - fromrepo: bullseye-backports + +rspamd_conf: + file.recurse: + - name: /etc/rspamd/local.d + - dir_mode: '0755' + - file_mode: '0644' + - source: salt://email/rspamd/local.d + +rspamd_service: + service.running: + - name: rspamd + - enable: true + - watch: + - pkg: rspamd + - file: /etc/rspamd/local.d diff --git a/states/email/rspamd/local.d/ip_whitelist.map b/states/email/rspamd/local.d/ip_whitelist.map new file mode 100644 index 0000000..c94f0bc --- /dev/null +++ b/states/email/rspamd/local.d/ip_whitelist.map @@ -0,0 +1 @@ +# 2a00:1098:8:d6::1/64 diff --git a/states/email/rspamd/local.d/multimap.conf b/states/email/rspamd/local.d/multimap.conf new file mode 100644 index 0000000..c3899d8 --- /dev/null +++ b/states/email/rspamd/local.d/multimap.conf @@ -0,0 +1,6 @@ +IP_WHITELIST { + type = "ip"; + prefilter = "true"; + map = "/${LOCAL_CONFDIR}/local.d/ip_whitelist.map"; + action = "accept"; +} diff --git a/states/email/rspamd/local.d/redis.conf b/states/email/rspamd/local.d/redis.conf new file mode 100644 index 0000000..6b6c00d --- /dev/null +++ b/states/email/rspamd/local.d/redis.conf @@ -0,0 +1,2 @@ +write_servers = "localhost"; +read_servers = "localhost"; diff --git a/states/firewalls/scabbers.sls b/states/firewalls/scabbers.sls index 87ccc9c..831bb63 100644 --- a/states/firewalls/scabbers.sls +++ b/states/firewalls/scabbers.sls @@ -5,6 +5,12 @@ scabbers_public: - services: - dhcpv6-client - ssh + - imap + - imaps + - managesieve + - smtp + - smtps + - smtp-submission - prune_services: True - require: - firewalld diff --git a/states/top.sls b/states/top.sls index dc1af42..65fd404 100644 --- a/states/top.sls +++ b/states/top.sls @@ -22,6 +22,7 @@ base: - backup - backup/scabbers - dottes_website + - email - fail2ban - firewalls/scabbers - gitea