summaryrefslogtreecommitdiffstats
path: root/roles/amavis
diff options
context:
space:
mode:
authorGuilhem Moulin <guilhem@fripost.org>2014-07-03 04:26:26 +0200
committerGuilhem Moulin <guilhem@fripost.org>2015-06-07 02:52:20 +0200
commit1c357b55931a0d4fbd15d51d61ec4e81d4f38aa5 (patch)
treed5f37b52487f75c3ffe40a39c94ea570c32816a5 /roles/amavis
parentdfe8b222dc5067e1019d7ab5744df55b2c314ce8 (diff)
Install amavisd-new on the outgoing SMTP proxy.
For DKIM signing and virus checking.
Diffstat (limited to 'roles/amavis')
-rw-r--r--roles/amavis/handlers/main.yml10
-rw-r--r--roles/amavis/tasks/main.yml62
-rw-r--r--roles/amavis/templates/etc/amavis/conf.d/50-user.j2182
3 files changed, 254 insertions, 0 deletions
diff --git a/roles/amavis/handlers/main.yml b/roles/amavis/handlers/main.yml
new file mode 100644
index 0000000..65287e3
--- /dev/null
+++ b/roles/amavis/handlers/main.yml
@@ -0,0 +1,10 @@
+---
+- name: Restart ClamAV
+ service: name=clamav-daemon state=restarted
+
+- name: Publish the public key in the DNS zone
+ # See the output of 'sudo genkeypair.sh dkim --privkey=/var/lib/dkim/outgoing.fripost.org.key'
+ fail: "msg={{ dkim.stdout }}"
+
+- name: Restart Amavis
+ service: name=amavis state=restarted
diff --git a/roles/amavis/tasks/main.yml b/roles/amavis/tasks/main.yml
new file mode 100644
index 0000000..354ade8
--- /dev/null
+++ b/roles/amavis/tasks/main.yml
@@ -0,0 +1,62 @@
+- name: Install amavis and its decoders
+ apt: pkg={{ item }}
+ with_items:
+ - amavisd-new
+ # Mail::DKIM
+ - libmail-dkim-perl
+ - gzip
+ - bzip2
+ - xz-utils
+ - lzop
+ - rpm2cpio
+ - pax
+ - binutils
+ - p7zip-full
+ - unrar-free
+ - arj
+ - nomarch
+ - zoo
+ - ripole
+ - cabextract
+ - unar
+ - tnef
+ notify:
+ - Restart Amavis
+
+- name: Add 'clamav' to the group 'amavis'
+ user: name=clamav groups=amavis append=yes
+ register: r1
+ notify:
+ - Restart ClamAV
+ - Restart Amavis
+
+- name: Create directory /var/lib/dkim
+ file: path=/var/lib/dkim
+ state=directory
+ owner=root group=root
+ mode=0755
+
+- name: Generate a private key for DKIM signing
+ command: genkeypair.sh dkim --privkey=/var/lib/dkim/outgoing.fripost.org.key --dns=outgoing -t rsa -b 2048
+ register: dkim
+ changed_when: dkim.rc == 0
+ failed_when: dkim.rc > 1
+ notify:
+ - Restart Amavis
+ - Publish the public key in the DNS zone
+ tags:
+ - genkey
+
+- name: Configure Amavis
+ template: src=etc/amavis/conf.d/50-user.j2
+ dest=/etc/amavis/conf.d/50-user
+ owner=root group=root
+ mode=0644
+ register: r3
+ notify:
+ - Restart Amavis
+
+- meta: flush_handlers
+
+- name: Start Amavis
+ service: name=amavis state=started
diff --git a/roles/amavis/templates/etc/amavis/conf.d/50-user.j2 b/roles/amavis/templates/etc/amavis/conf.d/50-user.j2
new file mode 100644
index 0000000..adafd7f
--- /dev/null
+++ b/roles/amavis/templates/etc/amavis/conf.d/50-user.j2
@@ -0,0 +1,182 @@
+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
+#
+
+# $max_servers: num of pre-forked children (2..30 is common). It *must*
+# match the number set in /etc/postfix/master.cf "maxproc" column for
+# the amavisfeed service.
+$max_servers = 5;
+$recipient_delimiter = '+';
+
+$mydomain = 'fripost.org';
+$X_HEADER_LINE = "Debian $myproduct_name at $mydomain";
+undef $undecipherable_subject_tag;
+
+@mynetworks_maps = ();
+@remove_existing_spam_headers_maps = ();
+@bypass_virus_checks_maps = (); # load virus checking code
+
+
+$enable_dkim_verification = 1; # load DKIM signing/verifying code
+{% if 'out' not in group_names %}
+undef $enable_dkim_signing;
+@bypass_spam_checks_maps = (); # load spam checking code
+{% else %}
+$enable_dkim_signing = 1;
+# Sign *all* outgoing mails with *our* key (yes, amavis complains, but this is
+# safe as we force our domain with the 'd' tag).
+dkim_key(qr'^', 'outgoing', '/var/lib/dkim/outgoing.'.$mydomain.'.key');
+@dkim_signature_options_bysender_maps = (
+ { '.' => { d => $mydomain
+ , a => 'rsa-sha256'
+ , ttl => 21*24*3600
+ , c => 'relaxed/simple' } } );
+# Conform to RFC 4871 and don't sign Received: headers.
+$signed_header_fields{received} = 0;
+{% endif %}
+
+
+
+# Defang viruses only
+%defang_maps_by_ccat = ( CC_VIRUS, 1
+ , CC_CATCHALL, undef
+ );
+
+# Never BCC / DSN; don't forget to disallow setting amavisSpamDsnCutoffLevel
+# and amavis*Admin, also
+%always_bcc_by_ccat = ( CC_CATCHALL, undef );
+%dsn_bcc_by_ccat = ( CC_CATCHALL, undef );
+
+# Never warn sender or recipient; don't forget to disallow setting
+# amavisWarn*Recip, also
+%warnsender_by_ccat = ( CC_CATCHALL, undef );
+%warnrecip_maps_by_ccat = ( CC_CATCHALL, undef );
+
+
+# A couple of common banned rules one might can refer by their name
+%banned_rules = (
+ 'NO-MS-EXEC'=> new_RE( qr'^\.exe-ms$' ),
+ 'PASSALL' => new_RE( [qr'^' => 0] ),
+ 'ALLOW_EXE' => new_RE( qr'.\.(vbs|pif|scr|bat)$'i, [qr'^\.exe$' => 0] ),
+ 'ALLOW_VBS' => new_RE( [qr'.\.vbs$' => 0] ),
+);
+
+
+{% if 'MDA' in group_names %}
+$enable_ldap = 1; # Load Net::LDAP
+$default_ldap = {
+ hostname => 'ldapi://',
+ sasl => 1,
+ sasl_mech => 'EXTERNAL',
+ deref => 'never',
+ timeout => 5,
+ scope => 'one',
+ base => 'fvd=%d,ou=virtual,o=mailHosting,dc=fripost,dc=org',
+ # XXX: ideally we would use %u in the base and the query_filter, but
+ # it's not supported as of amavis 2.7 (see the 'lookup_ldap'
+ # subroutine in /usr/sbin/amavisd-new)
+ query_filter => '(&(objectClass=amavisAccount)(ObjectClass=FripostVirtualUser)(fvl=%m))'
+};
+{% endif %}
+
+
+# http://www.ijs.si/software/amavisd/amavisd-new-docs.html#pbanks-ex
+
+$protocol = 'LMTP';
+$inet_socket_port = [];
+
+{% if 'out' in group_names %}
+push @$inet_socket_port, 10040;
+$interface_policy{'10040'} = 'OUTGOING';
+{% endif %}
+{% if 'MDA' in group_names %}
+push @$inet_socket_port, 10041;
+$interface_policy{'10041'} = 'INCOMING';
+{% endif %}
+
+$QUARANTINEDIR = "$MYHOME/virusmails";
+$notify_method = 'smtp:[127.0.0.1]:16132'; # notifications
+$forward_method = 'smtp:[127.0.0.1]:10025'; # reinject
+$requeue_method = $notify_method; # requeue after quarantine
+
+# some defaults for spam checking
+$sa_tag_level_deflt = undef;
+$sa_tag2_level_deflt = 5;
+$sa_kill_level_deflt = 5;
+$sa_dsn_cutoff_level = undef;
+$sa_quarantine_cutoff_level = undef;
+
+
+# Here is an overall picture (sequence of events) of how pieces fit together
+#
+# bypass_virus_checks set for all recipients? ==> PASS
+# no viruses? ==> PASS
+# log virus if $log_templ is nonempty
+# quarantine if $virus_quarantine_to is nonempty
+# notify admin if $virus_admin (lookup) nonempty
+# notify recips if $warnvirusrecip and (recipient is local or $warn_offsite)
+# add address extensions for local recipients (when enabled)
+# send (non-)delivery notifications
+# to sender if DSN needed (BOUNCE or ($warnvirussender and D_PASS))
+# virus_lovers or final_destiny==D_PASS ==> PASS
+# DISCARD (2xx) or REJECT (5xx) (depending on final_*_destiny)
+
+
+# Mandatory DKIM signing and virus checking only
+$policy_bank{'OUTGOING'} = {
+ originating => 1,
+ enable_dkim_verification => 0,
+ smtpd_greeting_banner => '${helo-name} ${protocol} ${product} OUTGOING service ready',
+ forward_method => $forward_method,
+
+ # No black or white lists
+ message_size_limit_maps => [],
+ whitelist_sender_maps => [],
+ blacklist_sender_maps => [],
+
+ # Check for viruses (regardless of the recipient), but bypass all other checks
+ bypass_virus_checks_maps => undef,
+ bypass_banned_checks_maps => 1,
+ bypass_header_checks_maps => 1,
+ bypass_spam_checks_maps => 1,
+
+ # If found, notify postmaster, quarantine and discard
+ quarantine_to_maps_by_ccat => { CC_VIRUS, [$virus_quarantine_to], CC_CATCHALL, undef },
+ quarantine_method_by_ccat => { CC_VIRUS, [$virus_quarantine_method], CC_CATCHALL, undef },
+ admin_maps_by_ccat => { CC_VIRUS, ["postmaster\@$mydomain"], CC_CATCHALL, undef },
+ addr_extension_maps_by_ccat=> { CC_CATCHALL, undef },
+ lovers_maps_by_ccat => { CC_VIRUS, undef, CC_CATCHALL, 1 },
+ final_destiny_by_ccat => { CC_VIRUS, D_DISCARD, CC_CATCHALL, D_PASS },
+};
+
+$policy_bank{'INCOMING'} = {
+ originating => 0,
+ enable_dkim_verification => 1,
+ smtpd_greeting_banner => '${helo-name} ${protocol} ${product} INCOMING service ready',
+ forward_method => $forward_method,
+ message_size_limit_maps => [],
+
+ # Per-recipient Bayes Database
+ sa_username_maps => [ new_RE ( [ qr'^(.+@.+)$'i => '$1' ] )
+ , 'amavis' # catch-all
+ ],
+
+ # Never quarantine
+ # (Remember to disallow setting amavisSpamQuarantineCutoffLevel and
+ # amavisVirusQuarantine*To in the LDAP schema.)
+ quarantine_method_by_ccat => { CC_CATCHALL, undef },
+ admin_maps_by_ccat => { CC_CATCHALL, undef },
+
+ # Always deliver messages
+ final_destiny_by_ccat => { CC_CATCHALL, D_PASS },
+ lovers_maps_by_ccat => { CC_CATCHALL, 1 },
+};
+
+#------------ Do not modify anything below this line -------------
+1; # ensure a defined return