diff --git a/roles/mail/files/default/spamassassin b/roles/mail/files/default/spamassassin deleted file mode 100644 index aff448e..0000000 --- a/roles/mail/files/default/spamassassin +++ /dev/null @@ -1,34 +0,0 @@ -# /etc/default/spamassassin -# Duncan Findlay - -# WARNING: please read README.spamd before using. -# There may be security risks. - -# If you're using systemd (default for jessie), the ENABLED setting is -# not used. Instead, enable spamd by issuing: -# systemctl enable spamassassin.service -# Change to "1" to enable spamd on systems using sysvinit: -ENABLED=0 - -# Options -# See man spamd for possible options. The -d option is automatically added. - -# SpamAssassin uses a preforking model, so be careful! You need to -# make sure --max-children is not set to anything higher than 5, -# unless you know what you're doing. - -OPTIONS="--create-prefs --max-children 5 --helper-home-dir" - -# Pid file -# Where should spamd write its PID to file? If you use the -u or -# --username option above, this needs to be writable by that user. -# Otherwise, the init script will not be able to shut spamd down. -PIDFILE="/var/run/spamd.pid" - -# Set nice level of spamd -#NICE="--nicelevel 15" - -# Cronjob -# Set to anything but 0 to enable the cron job to automatically update -# spamassassin's rules on a nightly basis -CRON=1 diff --git a/roles/mail/files/dovecot/learn-ham.sh b/roles/mail/files/dovecot/learn-ham.sh new file mode 100755 index 0000000..c30528f --- /dev/null +++ b/roles/mail/files/dovecot/learn-ham.sh @@ -0,0 +1,2 @@ +#!/bin/sh +exec /usr/bin/rspamc learn_ham diff --git a/roles/mail/files/dovecot/learn-spam.sh b/roles/mail/files/dovecot/learn-spam.sh new file mode 100755 index 0000000..da8e276 --- /dev/null +++ b/roles/mail/files/dovecot/learn-spam.sh @@ -0,0 +1,2 @@ +#!/bin/sh +exec /usr/bin/rspamc learn_spam diff --git a/roles/mail/files/dovecot/move-spam.sieve b/roles/mail/files/dovecot/move-spam.sieve new file mode 100644 index 0000000..1709203 --- /dev/null +++ b/roles/mail/files/dovecot/move-spam.sieve @@ -0,0 +1,5 @@ +require ["fileinto","mailbox"]; + +if header :contains "X-Spam" "Yes" { + fileinto :create "INBOX.Junk"; +} diff --git a/roles/mail/files/dovecot/report-ham.sieve b/roles/mail/files/dovecot/report-ham.sieve new file mode 100644 index 0000000..82973c7 --- /dev/null +++ b/roles/mail/files/dovecot/report-ham.sieve @@ -0,0 +1,2 @@ +require ["vnd.dovecot.pipe", "copy", "imapsieve"]; +pipe :copy ".learn-ham.sh"; diff --git a/roles/mail/files/dovecot/report-spam.sieve b/roles/mail/files/dovecot/report-spam.sieve new file mode 100644 index 0000000..512b132 --- /dev/null +++ b/roles/mail/files/dovecot/report-spam.sieve @@ -0,0 +1,2 @@ +require ["vnd.dovecot.pipe", "copy", "imapsieve"]; +pipe :copy ".learn-spam.sh"; diff --git a/roles/mail/files/postfix-policyd-spf-python/policyd-spf.conf b/roles/mail/files/postfix-policyd-spf-python/policyd-spf.conf deleted file mode 100644 index 166dda1..0000000 --- a/roles/mail/files/postfix-policyd-spf-python/policyd-spf.conf +++ /dev/null @@ -1,14 +0,0 @@ -# For a fully commented sample config file see policyd-spf.conf.commented - -debugLevel = 1 -defaultSeedOnly = 1 - -HELO_reject = No_Check -Mail_From_reject = False - -Mail_From_pass_restriction = OK - -PermError_reject = False -TempError_Defer = False - -skip_addresses = 127.0.0.0/8,::ffff:127.0.0.0/104,::1/128 diff --git a/roles/mail/files/redis.conf b/roles/mail/files/redis.conf new file mode 100644 index 0000000..2318b4c --- /dev/null +++ b/roles/mail/files/redis.conf @@ -0,0 +1,60 @@ +bind 127.0.0.1 ::1 +protected-mode yes +port 6379 +tcp-backlog 511 +timeout 0 +tcp-keepalive 300 +daemonize yes +supervised no +pidfile /var/run/redis/redis-server.pid +loglevel notice +logfile /var/log/redis/redis-server.log +databases 16 +always-show-logo yes +save 900 1 +save 300 10 +save 60 10000 +stop-writes-on-bgsave-error yes +rdbcompression yes +rdbchecksum yes +dbfilename dump.rdb +dir /var/lib/redis +slave-serve-stale-data yes +slave-read-only yes +repl-diskless-sync no +repl-diskless-sync-delay 5 +repl-disable-tcp-nodelay no +slave-priority 100 +maxmemory 500mb +maxmemory-policy volatile-lru +lazyfree-lazy-eviction no +lazyfree-lazy-expire no +lazyfree-lazy-server-del no +slave-lazy-flush no +appendonly yes +appendfilename "appendonly.aof" +appendfsync everysec +no-appendfsync-on-rewrite no +auto-aof-rewrite-percentage 100 +auto-aof-rewrite-min-size 64mb +aof-load-truncated yes +aof-use-rdb-preamble no +lua-time-limit 5000 +slowlog-log-slower-than 10000 +slowlog-max-len 128 +latency-monitor-threshold 0 +notify-keyspace-events "" +hash-max-ziplist-entries 512 +hash-max-ziplist-value 64 +list-max-ziplist-size -2 +list-compress-depth 0 +set-max-intset-entries 512 +zset-max-ziplist-entries 128 +zset-max-ziplist-value 64 +hll-sparse-max-bytes 3000 +activerehashing yes +client-output-buffer-limit normal 0 0 0 +client-output-buffer-limit slave 256mb 64mb 60 +client-output-buffer-limit pubsub 32mb 8mb 60 +hz 10 +aof-rewrite-incremental-fsync yes diff --git a/roles/mail/files/rspamd/local.d/antivirus.conf b/roles/mail/files/rspamd/local.d/antivirus.conf new file mode 100644 index 0000000..db0a12a --- /dev/null +++ b/roles/mail/files/rspamd/local.d/antivirus.conf @@ -0,0 +1,9 @@ +clamav { + servers = "/var/run/clamav/clamd.ctl"; + symbol = "CLAMAV_VIRUS"; + attachments_only = false; + patterns { + JUST_EICAR = nan; #Disable EICAR handling + } + action = "reject"; +} diff --git a/roles/mail/files/rspamd/local.d/classifier-bayes.conf b/roles/mail/files/rspamd/local.d/classifier-bayes.conf new file mode 100644 index 0000000..8a60b20 --- /dev/null +++ b/roles/mail/files/rspamd/local.d/classifier-bayes.conf @@ -0,0 +1,3 @@ +backend = "redis"; +new_schema = true; +expire = 8640000; diff --git a/roles/mail/files/rspamd/local.d/greylist.conf b/roles/mail/files/rspamd/local.d/greylist.conf new file mode 100644 index 0000000..bc91906 --- /dev/null +++ b/roles/mail/files/rspamd/local.d/greylist.conf @@ -0,0 +1,2 @@ +expire=30d; +timeout=120s; diff --git a/roles/mail/files/rspamd/local.d/logging.inc b/roles/mail/files/rspamd/local.d/logging.inc new file mode 100644 index 0000000..230783b --- /dev/null +++ b/roles/mail/files/rspamd/local.d/logging.inc @@ -0,0 +1,4 @@ +type = "file"; +filename = "/var/log/rspamd/rspamd.log"; +level = "notice"; +debug_modules = ["antivirus","dkim_signing","arc","greylist","fuzzy_check"]; diff --git a/roles/mail/files/rspamd/local.d/milter_headers.conf b/roles/mail/files/rspamd/local.d/milter_headers.conf new file mode 100644 index 0000000..32ad1ad --- /dev/null +++ b/roles/mail/files/rspamd/local.d/milter_headers.conf @@ -0,0 +1,2 @@ +use = ["authentication-results","x-spam-status","x-spam-level","x-spamd-bar", "x-spamd-result", "x-rspamd-server","x-rspamd-queue-id"]; +authenticated_headers = ["authentication-results"]; diff --git a/roles/mail/files/rspamd/local.d/rbl.conf b/roles/mail/files/rspamd/local.d/rbl.conf new file mode 100644 index 0000000..f0e217f --- /dev/null +++ b/roles/mail/files/rspamd/local.d/rbl.conf @@ -0,0 +1,14 @@ +rbls { + nixspam { + symbol = "RBL_NIXSPAM"; + rbl = "ix.dnsbl.manitu.net"; + ipv4 = true; + ipv6 = true; + } + gbudb { + symbol = "RBL_GBUDB"; + rbl = "truncate.gbudb.net"; + ipv4 = true; + ipv6 = true; + } +} diff --git a/roles/mail/files/rspamd/local.d/rbl_group.conf b/roles/mail/files/rspamd/local.d/rbl_group.conf new file mode 100644 index 0000000..b32ae4e --- /dev/null +++ b/roles/mail/files/rspamd/local.d/rbl_group.conf @@ -0,0 +1,10 @@ +symbols = { + "RBL_GBUDB" { + weight = 4.0; + description = "From address is listed in GBUDB BL"; + } + "RBL_NIXSPAM" { + weight = 4.0; + description = "From address is listed in NIXSPAM BL"; + } +} diff --git a/roles/mail/files/rspamd/local.d/redis.conf b/roles/mail/files/rspamd/local.d/redis.conf new file mode 100644 index 0000000..a47448b --- /dev/null +++ b/roles/mail/files/rspamd/local.d/redis.conf @@ -0,0 +1,2 @@ +write_servers = "127.0.0.1"; +read_servers = "127.0.0.1"; diff --git a/roles/mail/files/rspamd/local.d/worker-controller.inc b/roles/mail/files/rspamd/local.d/worker-controller.inc new file mode 100644 index 0000000..6f9b875 --- /dev/null +++ b/roles/mail/files/rspamd/local.d/worker-controller.inc @@ -0,0 +1,3 @@ +password = "$2$tgahjcep7dkczanwry7hnyozswpbi9fx$f6acdtn47w35sek85znopneeko7fp8gmamnxxaf31ryo18dp333y"; +enable_password = "$2$tgahjcep7dkczanwry7hnyozswpbi9fx$f6acdtn47w35sek85znopneeko7fp8gmamnxxaf31ryo18dp333y"; +bind_socket = "localhost:11334"; diff --git a/roles/mail/files/rspamd/local.d/worker-normal.inc b/roles/mail/files/rspamd/local.d/worker-normal.inc new file mode 100644 index 0000000..27dc8cb --- /dev/null +++ b/roles/mail/files/rspamd/local.d/worker-normal.inc @@ -0,0 +1,2 @@ +bind_socket = "localhost:11333"; +count = 1; diff --git a/roles/mail/files/rspamd/local.d/worker-proxy.inc b/roles/mail/files/rspamd/local.d/worker-proxy.inc new file mode 100644 index 0000000..e49b3ec --- /dev/null +++ b/roles/mail/files/rspamd/local.d/worker-proxy.inc @@ -0,0 +1,7 @@ +bind_socket = "localhost:11332"; +milter = yes; +timeout = 120s; +upstream "local" { + default = yes; + self_scan = yes; +} diff --git a/roles/mail/handlers/main.yml b/roles/mail/handlers/main.yml index 49b03bd..ab3d510 100644 --- a/roles/mail/handlers/main.yml +++ b/roles/mail/handlers/main.yml @@ -1,8 +1,4 @@ --- - -- name: Restart amavis - service: name=amavis state=restarted - - name: Restart dovecot service: name=dovecot state=restarted @@ -12,8 +8,11 @@ - name: Restart postfix service: name=postfix state=restarted -- name: Restart postgrey - service: name=postgrey state=restarted +- name: Restart redis + service: name=redis state=restarted + +- name: Restart rspamd + service: name=rspamd state=restarted - name: Run acertmgr command: /opt/acertmgr/acertmgr.py diff --git a/roles/mail/tasks/main.yml b/roles/mail/tasks/main.yml index c6801a6..4b9ec84 100644 --- a/roles/mail/tasks/main.yml +++ b/roles/mail/tasks/main.yml @@ -1,4 +1,13 @@ --- +- name: add an apt rspamd key + apt_key: + url: https://rspamd.com/apt-stable/gpg.key + state: present + +- name: add rspamd repository + apt_repository: + repo: deb http://rspamd.com/apt-stable/ {{ ansible_distribution_release }} main + state: present - name: Install packages apt: name={{ item }} @@ -7,6 +16,7 @@ - bsd-mailx - dovecot-core - dovecot-imapd + - dovecot-lmtpd - dovecot-ldap - dovecot-managesieved - dovecot-sieve @@ -14,11 +24,9 @@ - mailman - postfix - postfix-ldap - - postfix-policyd-spf-python - - postgrey - - pyzor - - razor - - spamassassin + - redis-server + - redis-tools + - rspamd - name: Create vmail group group: name=vmail gid=500 state=present @@ -26,19 +34,41 @@ - name: Create vmail user user: name=vmail group=vmail uid=500 createhome=yes home=/var/vmail shell=/bin/false state=present -- name: Configure amavis - template: src={{ item }}.j2 dest=/etc/{{ item }} - with_items: - - amavis/conf.d/15-content_filter_mode - - amavis/conf.d/50-user - notify: Restart amavis - - name: Create dovecot ssl directory file: path=/etc/dovecot/ssl state=directory mode=0750 owner=dovecot group=dovecot - name: Create dovecot log directory file: path=/var/log/dovecot state=directory mode=0750 owner=vmail group=vmail +- name: Create vmail sieve directory + file: path=/var/vmail/.sieve state=directory mode=0750 owner=vmail group=vmail + +- name: Copy redis config + copy: src=redis.conf dest=/etc/redis/redis.conf + notify: Restart redis + +- name: Copy static rspamd config + copy: src={{ item }} dest=/etc/rspamd/local.d/ + notify: Restart rspamd + with_fileglob: "rspamd/local.d/*" + +- name: Render rspamd config templates + template: src=rspamd/local.d/{{ item }}.j2 dest=/etc/rspamd/local.d/{{ item }} + notify: Restart rspamd + loop: + - "options.inc" + - "arc.conf" + - "dkim_signing.conf" + +- name: Copy spam learn/unlearn sieve and shell scripts + copy: src=dovecot/{{ item }} dest=/var/vmail/.sieve/.{{ item }} + with_items: + - learn-spam.sh + - learn-ham.sh + - move-spam.sieve + - report-spam.sieve + - report-ham.sieve + - name: Configure dovecot template: src={{ item }}.j2 dest=/etc/{{ item }} with_items: @@ -46,6 +76,19 @@ - dovecot/local.conf notify: Restart dovecot +- name: Compile sieve scripts + shell: sievec /var/vmail/.sieve/.{{ item|basename }} + with_items: + - move-spam.sieve + - report-spam.sieve + - report-ham.sieve + +- name: Ensure learn scripts are executable + file: mode=0750 path=/var/vmail/.sieve/.{{ item }} + with_items: + - learn-spam.sh + - learn-ham.sh + - name: Configure logrotate for dovecot copy: src=logrotate.d/dovecot dest=/etc/logrotate.d/dovecot @@ -79,11 +122,6 @@ file: path=/etc/nginx/ssl/{{ mailman_domain }}.key owner=root mode=0400 notify: Restart nginx -- name: Configure policyd - copy: src={{ item }} dest=/etc/{{ item }} - with_items: - - postfix-policyd-spf-python/policyd-spf.conf - - name: Create postfix ssl directory file: path=/etc/postfix/ssl state=directory mode=0750 owner=postfix group=postfix @@ -116,32 +154,6 @@ file: path=/etc/postfix/ssl/{{ mail_server }}.key owner=postfix mode=0400 notify: Restart postfix -- name: Create razor directory structure - command: razor-admin -create chdir=/var/lib/amavis creates=/var/lib/amavis/.razor - become: yes - become_user: amavis - -- name: Register razor - command: razor-admin -register chdir=/var/lib/amavis creates=/var/lib/amavis/.razor/identity - become: yes - become_user: amavis - -- name: Download GPG key for Sought ruleset - get_url: url=http://yerp.org/rules/GPG.KEY dest=/etc/spamassassin/sought.key - -- name: Import GPG key for Sought ruleset - become: yes - become_user: debian-spamd - shell: sa-update --gpghomedir /var/lib/spamassassin/sa-update-keys --import /etc/spamassassin/sought.key && touch sought.imported chdir=/var/lib/spamassassin creates=sought.imported - -- name: Enable sa-update cron-job - cron: name=sa-update minute="0" hour="*/6" job="/usr/bin/sa-update -v --gpghomedir /var/lib/spamassassin/sa-update-keys --gpgkey 6C6191E3 --channel sought.rules.yerp.org --channel updates.spamassassin.org" - -- name: Enable spamd cron-job - copy: src={{ item }} dest=/etc/{{ item }} - with_items: - - default/spamassassin - - name: Configure certificate manager template: src=certs.j2 dest=/etc/acertmgr/{{ mail_server }}_mail.conf notify: Run acertmgr @@ -150,10 +162,6 @@ template: src=mailman/certs.j2 dest=/etc/acertmgr/{{ mailman_domain }}_mailman.conf notify: Run acertmgr -- name: Start amavis - service: name=amavis state=started enabled=yes - tags: mail - - name: Start dovecot service: name=dovecot state=started enabled=yes tags: mail @@ -166,6 +174,10 @@ service: name=postfix state=started enabled=yes tags: mail -- name: Start postgrey - service: name=postgrey state=started enabled=yes +- name: Start redis + service: name=rspamd state=started enabled=yes + tags: mail + +- name: Start rspamd + service: name=rspamd state=started enabled=yes tags: mail diff --git a/roles/mail/templates/amavis/conf.d/15-content_filter_mode.j2 b/roles/mail/templates/amavis/conf.d/15-content_filter_mode.j2 deleted file mode 100644 index 1d5ffab..0000000 --- a/roles/mail/templates/amavis/conf.d/15-content_filter_mode.j2 +++ /dev/null @@ -1,27 +0,0 @@ -use strict; - -# You can modify this file to re-enable SPAM checking through spamassassin -# and to re-enable antivirus checking. - -# -# Default antivirus checking mode -# Please note, that anti-virus checking is DISABLED by -# default. -# If You wish to enable it, please uncomment the following lines: - - -#@bypass_virus_checks_maps = ( -# \%bypass_virus_checks, \@bypass_virus_checks_acl, \$bypass_virus_checks_re); - - -# -# Default SPAM checking mode -# Please note, that anti-spam checking is DISABLED by -# default. -# If You wish to enable it, please uncomment the following lines: - - -@bypass_spam_checks_maps = ( - \%bypass_spam_checks, \@bypass_spam_checks_acl, \$bypass_spam_checks_re); - -1; # ensure a defined return diff --git a/roles/mail/templates/amavis/conf.d/50-user.j2 b/roles/mail/templates/amavis/conf.d/50-user.j2 deleted file mode 100644 index 7f80dde..0000000 --- a/roles/mail/templates/amavis/conf.d/50-user.j2 +++ /dev/null @@ -1,37 +0,0 @@ -use strict; - -# -# Place your configuration directives here. They will override those in -# earlier files. -# -# See /usr/share/doc/amavisd-new/ for documentation and examples of -# the directives you can use in this file -# - -$remove_existing_spam_headers = 1; - -$sa_tag_level_deflt = undef; -$sa_tag2_level_deflt = 5.0; -$sa_kill_level_deflt = $sa_tag2_level_deflt; -$sa_spam_subject_tag = undef; - -$final_virus_destiny = D_PASS; -$final_banned_destiny = D_PASS; -$final_spam_destiny = D_PASS; -$final_bad_header_destiny = D_PASS; - -$virus_admin = undef; - -$virus_quarantine_to = undef; -$spam_quarantine_to = undef; - -$X_HEADER_LINE = "$myproduct_name at $mydomain"; - -@local_domains_acl = ("{{ mail_domain }}" -{%- for domain in mail_domains %} -, "{{ domain }}" -{%- endfor %} -); - -#------------ Do not modify anything below this line ------------- -1; # ensure a defined return diff --git a/roles/mail/templates/dovecot/dovecot-ldap.conf.ext.j2 b/roles/mail/templates/dovecot/dovecot-ldap.conf.ext.j2 index a8f5048..fa76f60 100644 --- a/roles/mail/templates/dovecot/dovecot-ldap.conf.ext.j2 +++ b/roles/mail/templates/dovecot/dovecot-ldap.conf.ext.j2 @@ -108,7 +108,7 @@ scope = subtree # There are also other special fields which can be returned, see # http://wiki2.dovecot.org/UserDatabase/ExtraFields #user_attrs = homeDirectory=home,uidNumber=uid,gidNumber=gid -user_attrs = +user_attrs = uid=user # Filter for user lookup. Some variables can be used (see # http://wiki2.dovecot.org/Variables for full list): @@ -116,7 +116,7 @@ user_attrs = # %n - user part in user@domain, same as %u if there's no domain # %d - domain part in user@domain, empty if user there's no domain #user_filter = (&(objectClass=posixAccount)(uid=%u)) -user_filter = (&(objectClass=posixAccount)(uid=%u)) +user_filter = (&(objectClass=posixAccount)(uid=%n)) # Password checking attributes: # user: Virtual user name (user@domain), if you wish to change the @@ -124,7 +124,7 @@ user_filter = (&(objectClass=posixAccount)(uid=%u)) # password: Password, may optionally start with {type}, eg. {crypt} # There are also other special fields which can be returned, see # http://wiki2.dovecot.org/PasswordDatabase/ExtraFields -#pass_attrs = uid=user,userPassword=password +pass_attrs = uid=user # If you wish to avoid two LDAP lookups (passdb + userdb), you can use # userdb prefetch instead of userdb ldap in dovecot.conf. In that case you'll @@ -135,6 +135,7 @@ user_filter = (&(objectClass=posixAccount)(uid=%u)) # Filter for password lookups #pass_filter = (&(objectClass=posixAccount)(uid=%u)) +pass_filter = (&(objectClass=posixAccount)(uid=%n)) # Attributes and filter to get a list of all users #iterate_attrs = uid=user diff --git a/roles/mail/templates/dovecot/local.conf.j2 b/roles/mail/templates/dovecot/local.conf.j2 index 34a44a8..739bc9b 100644 --- a/roles/mail/templates/dovecot/local.conf.j2 +++ b/roles/mail/templates/dovecot/local.conf.j2 @@ -15,6 +15,8 @@ mail_home = maildir:/var/vmail/%u mail_uid = vmail mail_gid = vmail +postmaster_address = postmaster@binary-kitchen.de + ssl = yes ssl_cert =