summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGuilhem Moulin <guilhem@fripost.org>2014-07-01 23:02:45 +0200
committerGuilhem Moulin <guilhem@fripost.org>2015-06-07 02:52:13 +0200
commitde4859456f1de54540c96ad97f62858dd089a980 (patch)
tree4b4904258ae3daf6a6b4f852cbc9821acdfa8cc4
parent170dc68f9275dffb48fbe3f8ebb2183cd7ddf111 (diff)
Replace IPSec tunnels by app-level ephemeral TLS sessions.
For some reason giraff doesn't like IPSec. App-level TLS sessions are less efficient, but thanks to ansible it still scales well.
-rw-r--r--roles/IMAP/files/etc/dovecot/conf.d/10-master.conf5
-rw-r--r--roles/IMAP/files/etc/dovecot/conf.d/10-ssl.conf12
-rw-r--r--roles/IMAP/tasks/imap.yml8
-rw-r--r--roles/IMAP/tasks/mda.yml26
-rw-r--r--roles/IMAP/templates/etc/postfix/main.cf.j249
l---------roles/IMAP/templates/etc/postfix/relay_clientcerts.j21
-rw-r--r--roles/MSA/templates/etc/postfix/main.cf.j225
-rw-r--r--roles/MX/templates/etc/postfix/main.cf.j222
-rw-r--r--roles/MX/templates/etc/postfix/virtual/transport.j24
-rw-r--r--roles/common/files/etc/postfix/master.cf5
-rw-r--r--roles/common/tasks/ipsec.yml6
-rw-r--r--roles/common/tasks/mail.yml59
-rw-r--r--roles/common/tasks/main.yml3
-rw-r--r--roles/common/templates/etc/iptables/services.j213
-rw-r--r--roles/common/templates/etc/postfix/main.cf.j217
-rw-r--r--roles/common/templates/etc/postfix/tls_policy.j26
-rw-r--r--roles/lists/templates/etc/postfix/main.cf.j223
-rw-r--r--roles/out/tasks/main.yml24
-rw-r--r--roles/out/templates/etc/postfix/main.cf.j243
-rw-r--r--roles/out/templates/etc/postfix/relay_clientcerts.j25
-rw-r--r--roles/webmail/tasks/roundcube.yml2
-rw-r--r--roles/webmail/templates/etc/postfix/main.cf.j220
-rw-r--r--roles/webmail/templates/usr/share/roundcube/plugins/managesieve/config.inc.php.j22
23 files changed, 283 insertions, 97 deletions
diff --git a/roles/IMAP/files/etc/dovecot/conf.d/10-master.conf b/roles/IMAP/files/etc/dovecot/conf.d/10-master.conf
index d477d01..30a6f8b 100644
--- a/roles/IMAP/files/etc/dovecot/conf.d/10-master.conf
+++ b/roles/IMAP/files/etc/dovecot/conf.d/10-master.conf
@@ -15,11 +15,6 @@ default_login_user = dovenull
default_internal_user = dovecot
service imap-login {
- inet_listener imap {
- address = 172.16.0.1
- port = 143
- ssl = no
- }
inet_listener imaps {
port = 993
ssl = yes
diff --git a/roles/IMAP/files/etc/dovecot/conf.d/10-ssl.conf b/roles/IMAP/files/etc/dovecot/conf.d/10-ssl.conf
index c5e61d7..526da9c 100644
--- a/roles/IMAP/files/etc/dovecot/conf.d/10-ssl.conf
+++ b/roles/IMAP/files/etc/dovecot/conf.d/10-ssl.conf
@@ -5,18 +5,6 @@
# SSL/TLS support: yes, no, required. <doc/wiki/SSL.txt>
ssl = required
-# No need for SSL if the packets are protected by IPSec.
-local 172.16.0.1 {
- protocol imap {
- disable_plaintext_auth = no
- ssl = no
- }
- protocol sieve {
- disable_plaintext_auth = no
- ssl = no
- }
-}
-
# PEM encoded X.509 SSL/TLS certificate and private key. They're opened before
# dropping root privileges, so keep the key file unreadable by anyone but
# root. Included doc/mkcert.sh can be used to easily generate self-signed
diff --git a/roles/IMAP/tasks/imap.yml b/roles/IMAP/tasks/imap.yml
index 5424485..3e93c53 100644
--- a/roles/IMAP/tasks/imap.yml
+++ b/roles/IMAP/tasks/imap.yml
@@ -62,6 +62,12 @@
owner=vmail group=vmail
mode=0700
+- name: Create directory /etc/dovecot/ssl
+ file: path=/etc/dovecot/ssl
+ state=directory
+ owner=root group=root
+ mode=0755
+
- name: Generate a private key and a X.509 certificate for Dovecot
command: genkeypair.sh x509
--pubkey=/etc/dovecot/ssl/imap.fripost.org.pem
@@ -73,6 +79,8 @@
failed_when: r1.rc > 1
notify:
- Restart Dovecot
+ tags:
+ - genkey
- name: Configure Dovecot
copy: src=etc/dovecot/{{ item }}
diff --git a/roles/IMAP/tasks/mda.yml b/roles/IMAP/tasks/mda.yml
index 0358f12..4a74ed3 100644
--- a/roles/IMAP/tasks/mda.yml
+++ b/roles/IMAP/tasks/mda.yml
@@ -9,7 +9,7 @@
dest=/etc/postfix-{{ postfix_instance[inst].name }}/main.cf
owner=root group=root
mode=0644
- register: r
+ register: r1
notify:
- Restart Postfix
@@ -35,8 +35,30 @@
owner=root group=root
mode=0644
+- name: Build the Postfix relay clientcerts map
+ sudo: False
+ # smtpd_tls_fingerprint_digest MUST be sha256!
+ local_action: shell openssl x509 -in certs/postfix/{{ item }}.pem -noout -fingerprint -sha256 | sed -nr 's/^.*=(.*)/\1 {{ item }}/p'
+ with_items: groups.MX | difference([inventory_hostname]) | sort
+ register: relay_clientcerts
+ changed_when: False
+
+- name: Copy the Postfix relay clientcerts map
+ template: src=etc/postfix/relay_clientcerts.j2
+ dest=/etc/postfix-{{ postfix_instance[inst].name }}/relay_clientcerts
+ owner=root group=root
+ mode=0644
+
+- name: Compile the Postfix relay clientcerts map
+ postmap: cmd=postmap src=/etc/postfix-{{ postfix_instance[inst].name }}/relay_clientcerts db=cdb
+ owner=root group=root
+ mode=0644
+ register: r2
+ notify:
+ - Restart Postfix
+
- name: Start Postfix
service: name=postfix state=started
- when: not r.changed
+ when: not (r1.changed or r2.changed)
- meta: flush_handlers
diff --git a/roles/IMAP/templates/etc/postfix/main.cf.j2 b/roles/IMAP/templates/etc/postfix/main.cf.j2
index 46f64aa..40c8d32 100644
--- a/roles/IMAP/templates/etc/postfix/main.cf.j2
+++ b/roles/IMAP/templates/etc/postfix/main.cf.j2
@@ -28,11 +28,8 @@ multi_instance_enable = yes
# This server is a Mail Delivery Agent
mynetworks_style = host
-inet_interfaces = 172.16.0.1
-{% if 'MX' in group_names %}
- 127.0.0.1
-{% endif %}
-inet_protocols = ipv4
+inet_interfaces = all
+
# No local delivery
mydestination =
@@ -64,3 +61,45 @@ recipient_canonical_maps = pcre:$config_directory/recipient_canonical.pcre
local_header_rewrite_clients =
# Tolerate occasional high latency
smtpd_timeout = 1200s
+
+
+relay_clientcerts = cdb:$config_directory/relay_clientcerts
+smtpd_tls_security_level = may
+smtpd_tls_cert_file = /etc/postfix/ssl/{{ ansible_fqdn }}.pem
+smtpd_tls_key_file = /etc/postfix/ssl/{{ ansible_fqdn }}.key
+smtpd_tls_session_cache_database= btree:$data_directory/smtpd_tls_session_cache
+smtpd_tls_received_header = yes
+smtpd_tls_ask_ccert = yes
+smtpd_tls_session_cache_timeout = 3600s
+smtpd_tls_fingerprint_digest = sha256
+
+
+strict_rfc821_envelopes = yes
+smtpd_delay_reject = yes
+disable_vrfy_command = yes
+
+smtpd_client_restrictions =
+ permit_mynetworks
+ permit_tls_clientcerts
+ # We are the only ones using this proxy, but if things go wrong we
+ # want to know why
+ defer
+
+smtpd_helo_required = yes
+smtpd_helo_restrictions =
+ reject_invalid_helo_hostname
+
+smtpd_sender_restrictions =
+ reject_non_fqdn_sender
+ reject_unknown_sender_domain
+
+smtpd_recipient_restrictions =
+ # RFC requirements
+ reject_non_fqdn_recipient
+ reject_unknown_recipient_domain
+ permit_mynetworks
+ permit_tls_clientcerts
+ reject
+
+smtpd_data_restrictions =
+ reject_unauth_pipelining
diff --git a/roles/IMAP/templates/etc/postfix/relay_clientcerts.j2 b/roles/IMAP/templates/etc/postfix/relay_clientcerts.j2
new file mode 120000
index 0000000..b375aa0
--- /dev/null
+++ b/roles/IMAP/templates/etc/postfix/relay_clientcerts.j2
@@ -0,0 +1 @@
+../../../../out/templates/etc/postfix/relay_clientcerts.j2 \ No newline at end of file
diff --git a/roles/MSA/templates/etc/postfix/main.cf.j2 b/roles/MSA/templates/etc/postfix/main.cf.j2
index e3014aa..036a887 100644
--- a/roles/MSA/templates/etc/postfix/main.cf.j2
+++ b/roles/MSA/templates/etc/postfix/main.cf.j2
@@ -40,7 +40,7 @@ local_recipient_maps =
message_size_limit = 67108864
recipient_delimiter = +
-# Forward everything to our internal mailhub
+# Forward everything to our internal outgoing proxy
{% if 'out' in group_names %}
relayhost = [127.0.0.1]:{{ postfix_instance.out.port }}
{% else %}
@@ -48,6 +48,7 @@ relayhost = [outgoing.fripost.org]:{{ postfix_instance.out.port }}
{% endif %}
relay_domains =
+
# Don't rewrite remote headers
local_header_rewrite_clients =
# Avoid splitting the envelope and scanning messages multiple times
@@ -59,24 +60,26 @@ smtp_data_done_timeout = 1200s
header_checks = pcre:$config_directory/anonymize_sender.pcre
#content_filter = amavisfeed:unix:public/amavisfeed-antivirus
-# Tunnel everything through IPSec
-smtp_tls_security_level = none
+
+# TLS
{% if 'out' in group_names %}
-smtp_bind_address = 127.0.0.1
+smtp_tls_security_level = none
+smtp_bind_address = 127.0.0.1
{% else %}
-smtp_bind_address = 172.16.0.1
+smtp_tls_security_level = encrypt
+smtp_tls_cert_file = /etc/postfix/ssl/{{ ansible_fqdn }}.pem
+smtp_tls_key_file = /etc/postfix/ssl/{{ ansible_fqdn }}.key
+smtp_tls_session_cache_database = btree:$data_directory/smtp_tls_session_cache
+smtp_tls_policy_maps = cdb:/etc/postfix/tls_policy
+smtp_tls_fingerprint_digest = sha256
{% endif %}
-# TLS
smtpd_tls_security_level = encrypt
-smtpd_tls_cert_file = /etc/ssl/certs/ssl-cert-snakeoil.pem
-smtpd_tls_key_file = /etc/ssl/private/ssl-cert-snakeoil.key
+smtpd_tls_cert_file = /etc/postfix/ssl/smtp.fripost.org.pem
+smtpd_tls_key_file = /etc/postfix/ssl/private/smtp.fripost.org.key
smtpd_tls_session_cache_database= btree:$data_directory/smtpd_tls_session_cache
smtpd_tls_received_header = yes
smtpd_tls_ask_ccert = yes
-smtpd_tls_fingerprint_digest = sha1
-smtpd_tls_eecdh_grade = strong
-tls_random_source = dev:/dev/urandom
# SASL
smtpd_sasl_auth_enable = yes
diff --git a/roles/MX/templates/etc/postfix/main.cf.j2 b/roles/MX/templates/etc/postfix/main.cf.j2
index 34e38a0..4d8e53e 100644
--- a/roles/MX/templates/etc/postfix/main.cf.j2
+++ b/roles/MX/templates/etc/postfix/main.cf.j2
@@ -41,7 +41,7 @@ local_recipient_maps =
message_size_limit = 67108864
recipient_delimiter = +
-# Forward everything to our internal mailhub
+# Forward everything to our internal outgoing proxy
{% if 'out' in group_names %}
relayhost = [127.0.0.1]:{{ postfix_instance.out.port }}
{% else %}
@@ -49,6 +49,7 @@ relayhost = [outgoing.fripost.org]:{{ postfix_instance.out.port }}
{% endif %}
relay_domains =
+
# Virtual transport
# We use a dedicated "virtual" domain to decongestion potential
# bottlenecks on trivial_rewrite(8) due to slow LDAP lookups in
@@ -67,6 +68,7 @@ virtual_alias_maps = pcre:$config_directory/virtual/reserved_alias.pcre
virtual_mailbox_maps =
transport_maps = cdb:$config_directory/virtual/transport
+
# Don't rewrite remote headers
local_header_rewrite_clients =
# Pass the client information along to the content filter
@@ -77,15 +79,20 @@ reserved-alias_recipient_limit = 1
# Tolerate occasional high latency
smtp_data_done_timeout = 1200s
-# Tunnel everything through IPSec
-smtp_tls_security_level = none
+
{% if 'out' in group_names %}
-smtp_bind_address = 127.0.0.1
+smtp_tls_security_level = none
+smtp_bind_address = 127.0.0.1
{% else %}
-smtp_bind_address = 172.16.0.1
+smtp_tls_security_level = encrypt
+smtp_tls_cert_file = /etc/postfix/ssl/{{ ansible_fqdn }}.pem
+smtp_tls_key_file = /etc/postfix/ssl/{{ ansible_fqdn }}.key
+smtp_tls_session_cache_database = btree:$data_directory/smtp_tls_session_cache
+smtp_tls_policy_maps = cdb:/etc/postfix/tls_policy
+smtp_tls_fingerprint_digest = sha256
{% endif %}
+smtpd_tls_security_level = none
-# TLS
smtpd_tls_security_level = may
smtpd_tls_cert_file = /etc/ssl/certs/ssl-cert-snakeoil.pem
smtpd_tls_key_file = /etc/ssl/private/ssl-cert-snakeoil.key
@@ -93,9 +100,6 @@ smtpd_tls_CApath = /etc/ssl/certs/
smtpd_tls_session_cache_database= btree:$data_directory/smtpd_tls_session_cache
smtpd_tls_received_header = yes
smtpd_tls_ask_ccert = yes
-smtpd_tls_fingerprint_digest = sha1
-smtpd_tls_eecdh_grade = strong
-tls_random_source = dev:/dev/urandom
# http://en.linuxreviews.org/HOWTO_Stop_spam_using_Postfix
diff --git a/roles/MX/templates/etc/postfix/virtual/transport.j2 b/roles/MX/templates/etc/postfix/virtual/transport.j2
index 2250a71..a34dcad 100644
--- a/roles/MX/templates/etc/postfix/virtual/transport.j2
+++ b/roles/MX/templates/etc/postfix/virtual/transport.j2
@@ -3,11 +3,11 @@ reserved.locahost.localdomain reserved-alias:
{% if 'LDA' in group_names %}
mda.fripost.org smtpl:[127.0.0.1]:{{ postfix_instance.IMAP.port }}
{% else %}
-mda.fripost.org smtps:[mda.fripost.org]:{{ postfix_instance.IMAP.port }}
+mda.fripost.org smtp:[mda.fripost.org]:{{ postfix_instance.IMAP.port }}
{% endif %}
{% if 'lists' in group_names %}
lists.fripost.org smtpl:[127.0.0.1]:{{ postfix_instance.lists.port }}
{% else %}
-lists.fripost.org smtps:[lists.fripost.org]:{{ postfix_instance.lists.port }}
+lists.fripost.org smtp:[lists.fripost.org]:{{ postfix_instance.lists.port }}
{% endif %}
diff --git a/roles/common/files/etc/postfix/master.cf b/roles/common/files/etc/postfix/master.cf
index e845371..70f7f4e 100644
--- a/roles/common/files/etc/postfix/master.cf
+++ b/roles/common/files/etc/postfix/master.cf
@@ -25,8 +25,6 @@ proxywrite unix - - n - 1 proxymap
smtp unix - - - - - smtp
smtpl unix - - - - - smtp
-o smtp_bind_address=127.0.0.1
-smtps unix - - - - - smtp
- -o smtp_bind_address=172.16.0.1
relay unix - - - - - smtp
# -o smtp_helo_timeout=5 -o smtp_connect_timeout=5
showq unix n - - - - showq
@@ -42,10 +40,7 @@ scache unix - - - - 1 scache
2525 inet n - - - - smtpd
2526 inet n - - - - smtpd
2527 inet n - - - - smtpd
- -o mynetworks=0.0.0.0/0
127.0.0.1:2580 inet n - - - - smtpd
-127.0.0.1:smtp inet n - - - - smtpd
- -o inet_interfaces=127.0.0.1
reserved-alias unix - n n - - pipe
flags=Rhu user=nobody argv=/usr/local/sbin/reserved-alias.pl ${sender} ${original_recipient} @fripost.org
mlmmj unix - n n - - pipe
diff --git a/roles/common/tasks/ipsec.yml b/roles/common/tasks/ipsec.yml
index 51d717f..36807d2 100644
--- a/roles/common/tasks/ipsec.yml
+++ b/roles/common/tasks/ipsec.yml
@@ -12,14 +12,18 @@
failed_when: r1.rc > 1
notify:
- Restart IPSec
+ tags:
+ - genkey
- name: Fetch the public part of IPSec's host key
- sudo: False
# Ensure we don't fetch private data
+ sudo: False
fetch: src=/etc/ipsec.d/certs/{{ inventory_hostname }}.pem
dest=certs/ipsec/
fail_on_missing=yes
flat=yes
+ tags:
+ - genkey
# Don't copy our pubkey due to a possible race condition. Only the
# remote machine has authority regarding its key.
diff --git a/roles/common/tasks/mail.yml b/roles/common/tasks/mail.yml
index 8572784..74919c8 100644
--- a/roles/common/tasks/mail.yml
+++ b/roles/common/tasks/mail.yml
@@ -44,7 +44,37 @@
notify:
- Restart Postfix
-- name: Update the static local Postfix database
+- name: Create directory /etc/postfix/ssl
+ file: path=/etc/postfix/ssl
+ state=directory
+ owner=root group=root
+ mode=0755
+ tags:
+ - genkey
+
+- name: Generate a private key and a X.509 certificate for Postfix
+ command: genkeypair.sh x509
+ --pubkey=/etc/postfix/ssl/{{ ansible_fqdn }}.pem
+ --privkey=/etc/postfix/ssl/{{ ansible_fqdn }}.key
+ --dns={{ ansible_fqdn }}
+ -t ecdsa -b secp384r1 -h sha512
+ register: r4
+ changed_when: r4.rc == 0
+ failed_when: r4.rc > 1
+ tags:
+ - genkey
+
+- name: Fetch Postfix's X.509 certificate
+ # Ensure we don't fetch private data
+ sudo: False
+ fetch: src=/etc/postfix/ssl/{{ ansible_fqdn }}.pem
+ dest=certs/postfix/
+ fail_on_missing=yes
+ flat=yes
+ tags:
+ - genkey
+
+- name: Compile the static local Postfix database
postmap: cmd=postalias src=/etc/aliases db=cdb
owner=root group=root
mode=0644
@@ -53,8 +83,33 @@
- name: Delete /etc/aliases.db
file: path=/etc/aliases.db state=absent
+- name: Build the Postfix TLS policy map
+ sudo: False
+ # smtp_tls_fingerprint_digest MUST be sha256!
+ local_action: shell openssl x509 -in certs/postfix/{{ item }}.pem -noout -fingerprint -sha256 | cut -d= -f2
+ with_items: groups.out | sort
+ register: tls_policy
+ changed_when: False
+ when: "'out' not in group_names"
+
+- name: Copy the Postfix TLS policy map
+ template: src=etc/postfix/tls_policy.j2
+ dest=/etc/postfix/tls_policy
+ owner=root group=root
+ mode=0644
+ when: "'out' not in group_names"
+
+- name: Compile the Postfix TLS policy map
+ postmap: cmd=postmap src=/etc/postfix/tls_policy db=cdb
+ owner=root group=root
+ mode=0644
+ when: "'out' not in group_names"
+ register: r5
+ notify:
+ - Restart Postfix
+
- name: Start Postfix
service: name=postfix state=started
- when: not (r1.changed or r2.changed or r3.changed)
+ when: not (r1.changed or r2.changed or r3.changed or r5.changed)
- meta: flush_handlers
diff --git a/roles/common/tasks/main.yml b/roles/common/tasks/main.yml
index 0048443..464abd0 100644
--- a/roles/common/tasks/main.yml
+++ b/roles/common/tasks/main.yml
@@ -15,8 +15,7 @@
owner=root group=root
mode=0755
tags:
- - genkeypair
-- include: ipsec.yml tags=strongswan,ipsec
+ - genkey
- include: logging.yml tags=logging
- include: ntp.yml tags=ntp
- include: mail.yml tags=mail,postfix
diff --git a/roles/common/templates/etc/iptables/services.j2 b/roles/common/templates/etc/iptables/services.j2
index 923aa35..3e31f04 100644
--- a/roles/common/templates/etc/iptables/services.j2
+++ b/roles/common/templates/etc/iptables/services.j2
@@ -4,9 +4,6 @@
# direction protocol destination port source port
# (in|out|inout)[46]? (tcp|udp|..) (port|port:port|port,port) (port|port:port|port,port)
-inout udp 500 500 # ISAKMP
-#inout udp 4500 4500 # IPSec NAT Traversal
-
out tcp 80,443 # HTTP/HTTPS
out udp 53 # DNS
out udp 67 # DHCP
@@ -20,15 +17,23 @@ in tcp {{ ansible_ssh_port|default('22') }} # SSH
in tcp 25 # SMTP
{% endif %}
{% if 'out' in group_names %}
-#out tcp 25 # SMTP
+in tcp {{ postfix_instance.out.port }}
+out tcp 25 # SMTP
+{% else %}
+out tcp {{ postfix_instance.out.port }}
{% endif %}
{% if 'IMAP' in group_names %}
in tcp 993 # IMAPS
in tcp 4190 # ManageSieve
{% endif %}
+{% if 'MDA' in group_names %}
+in tcp {{ postfix_instance.mda.port }}
+{% endif %}
{% if 'MSA' in group_names %}
in tcp 587 # SMTP-AUTH
{% endif %}
{% if 'webmail' in group_names %}
in tcp 80,443 # HTTP/HTTPS
+out tcp 993 # IMAP # TODO imapc
+out tcp 4190
{% endif %}
diff --git a/roles/common/templates/etc/postfix/main.cf.j2 b/roles/common/templates/etc/postfix/main.cf.j2
index 70d4b98..1abce71 100644
--- a/roles/common/templates/etc/postfix/main.cf.j2
+++ b/roles/common/templates/etc/postfix/main.cf.j2
@@ -17,7 +17,6 @@ append_dot_mydomain = no
# This server is for internal use only
mynetworks_style = host
inet_interfaces = loopback-only
-inet_protocols = ipv4
# No local delivery
mydestination =
@@ -30,7 +29,7 @@ default_database_type = cdb
virtual_alias_maps = cdb:/etc/aliases
alias_database = $virtual_alias_maps
-# Forward everything to our internal mailhub
+# Forward everything to our internal outgoing proxy
{% if 'out' in group_names %}
relayhost = [127.0.0.1]:{{ postfix_instance.out.port }}
{% else %}
@@ -38,14 +37,18 @@ relayhost = [outgoing.fripost.org]:{{ postfix_instance.out.port }}
{% endif %}
relay_domains =
-# Tunnel everything through IPSec
-smtp_tls_security_level = none
{% if 'out' in group_names %}
-smtp_bind_address = 127.0.0.1
+smtp_tls_security_level = none
+smtp_bind_address = 127.0.0.1
{% else %}
-smtp_bind_address = 172.16.0.1
+smtp_tls_security_level = encrypt
+smtp_tls_cert_file = $config_directory/ssl/{{ ansible_fqdn }}.pem
+smtp_tls_key_file = $config_directory/ssl/{{ ansible_fqdn }}.key
+smtp_tls_session_cache_database = btree:$data_directory/smtp_tls_session_cache
+smtp_tls_policy_maps = cdb:$config_directory/tls_policy
+smtp_tls_fingerprint_digest = sha256
{% endif %}
-smtpd_tls_security_level = none
+smtpd_tls_security_level = none
# Turn off all TCP/IP listener ports except that dedicated to
# samhain(8), which sadly cannot use pickup through the sendmail binary.
diff --git a/roles/common/templates/etc/postfix/tls_policy.j2 b/roles/common/templates/etc/postfix/tls_policy.j2
new file mode 100644
index 0000000..b4fc453
--- /dev/null
+++ b/roles/common/templates/etc/postfix/tls_policy.j2
@@ -0,0 +1,6 @@
+# {{ ansible_managed }}
+
+[outgoing.fripost.org]:{{ postfix_instance.out.port }} fingerprint ciphers=high protocols=TLSv1.2
+{% for x in tls_policy.results %}
+ match={{ x.stdout }}
+{% endfor %}
diff --git a/roles/lists/templates/etc/postfix/main.cf.j2 b/roles/lists/templates/etc/postfix/main.cf.j2
index 083fa2b..b7a82fe 100644
--- a/roles/lists/templates/etc/postfix/main.cf.j2
+++ b/roles/lists/templates/etc/postfix/main.cf.j2
@@ -66,11 +66,24 @@ smtp_destination_recipient_limit = 1000
smtp_data_done_timeout = 1200s
smtpd_timeout = 1200s
-# Tunnel everything through IPSec
-smtp_tls_security_level = none
+
+# Forward everything to our internal outgoing proxy
+{% if 'out' in group_names %}
+relayhost = [127.0.0.1]:{{ postfix_instance.out.port }}
+{% else %}
+relayhost = [outgoing.fripost.org]:{{ postfix_instance.out.port }}
+{% endif %}
+relay_domains =
+
{% if 'out' in group_names %}
-smtp_bind_address = 127.0.0.1
+smtp_tls_security_level = none
+smtp_bind_address = 127.0.0.1
{% else %}
-smtp_bind_address = 172.16.0.1
+smtp_tls_security_level = encrypt
+smtp_tls_cert_file = $config_directory/ssl/{{ ansible_fqdn }}.pem
+smtp_tls_key_file = $config_directory/ssl/{{ ansible_fqdn }}.key
+smtp_tls_session_cache_database = btree:$data_directory/smtp_tls_session_cache
+smtp_tls_policy_maps = cdb:$config_directory/tls_policy
+smtp_tls_fingerprint_digest = sha256
{% endif %}
-smtpd_tls_security_level = none
+smtpd_tls_security_level = none
diff --git a/roles/out/tasks/main.yml b/roles/out/tasks/main.yml
index 4bf4363..8bd8bbb 100644
--- a/roles/out/tasks/main.yml
+++ b/roles/out/tasks/main.yml
@@ -10,8 +10,30 @@
notify:
- Restart Postfix
+- name: Build the Postfix relay clientcerts map
+ sudo: False
+ # smtpd_tls_fingerprint_digest MUST be sha256!
+ local_action: shell openssl x509 -in certs/postfix/{{ item }}.pem -noout -fingerprint -sha256 | sed -nr 's/^.*=(.*)/\1 {{ item }}/p'
+ with_items: groups.all | difference([inventory_hostname]) | sort
+ register: relay_clientcerts
+ changed_when: False
+
+- name: Copy the Postfix relay clientcerts map
+ template: src=etc/postfix/relay_clientcerts.j2
+ dest=/etc/postfix-{{ postfix_instance[inst].name }}/relay_clientcerts
+ owner=root group=root
+ mode=0644
+
+- name: Compile the Postfix relay clientcerts map
+ postmap: cmd=postmap src=/etc/postfix-{{ postfix_instance[inst].name }}/relay_clientcerts db=cdb
+ owner=root group=root
+ mode=0644
+ register: r2
+ notify:
+ - Restart Postfix
+
- name: Start Postfix
service: name=postfix state=started
- when: not r.changed
+ when: not (r1.changed or r2.changed)
- meta: flush_handlers
diff --git a/roles/out/templates/etc/postfix/main.cf.j2 b/roles/out/templates/etc/postfix/main.cf.j2
index 1a7985f..11bcc10 100644
--- a/roles/out/templates/etc/postfix/main.cf.j2
+++ b/roles/out/templates/etc/postfix/main.cf.j2
@@ -1,5 +1,5 @@
########################################################################
-# Outgoing MTA configuration
+# Outgoing MTA (outgoing SMTP proxy) configuration
#
# {{ ansible_managed }}
# Do NOT edit this file directly!
@@ -19,7 +19,7 @@ append_dot_mydomain = no
# Turn off all TCP/IP listener ports except that necessary for the
# outgoing SMTP proxy.
-master_service_disable = !2525.inet inet
+master_service_disable = !{{ postfix_instance.out.port }}.inet inet
queue_directory = /var/spool/postfix-{{ postfix_instance[inst].name }}
data_directory = /var/lib/postfix-{{ postfix_instance[inst].name }}
@@ -27,10 +27,8 @@ multi_instance_group = {{ postfix_instance[inst].group | default('') }}
multi_instance_name = postfix-{{ postfix_instance[inst].name }}
multi_instance_enable = yes
-# Accept everything coming through IPSec.
-# TODO: this should our virtual private subnetwork
-mynetworks = 0.0.0.0/0
-inet_interfaces = 172.16.0.1, 127.0.0.1
+mynetworks_style = host
+inet_interfaces = all
# No local delivery
mydestination =
@@ -42,8 +40,8 @@ local_recipient_maps =
message_size_limit = 67108864
recipient_delimiter = +
-relay_domains =
-relay_transport = error:5.3.2 Relay Transport unavailable
+relay_domains =
+relay_transport = error:5.3.2 Relay Transport unavailable
# All header rewriting happens upstream
local_header_rewrite_clients =
@@ -51,13 +49,29 @@ local_header_rewrite_clients =
smtp_tls_security_level = may
smtp_tls_note_starttls_offer = yes
-smtp_tls_cert_file = /etc/postfix-out/ssl/smtp.fripost.org.pem
-smtp_tls_key_file = /etc/postfix-out/ssl/smtp.fripost.org.key
-smtp_tls_CApath = /etc/ssl/certs/
smtp_tls_session_cache_database = btree:$data_directory/smtp_tls_session_cache
-smtp_tls_fingerprint_digest = sha1
-tls_random_source = dev:/dev/urandom
+relay_clientcerts = cdb:$config_directory/relay_clientcerts
+smtpd_tls_security_level = may
+smtpd_tls_cert_file = /etc/postfix/ssl/{{ ansible_fqdn }}.pem
+smtpd_tls_key_file = /etc/postfix/ssl/{{ ansible_fqdn }}.key
+smtpd_tls_session_cache_database= btree:$data_directory/smtpd_tls_session_cache
+smtpd_tls_received_header = yes
+smtpd_tls_ask_ccert = yes
+smtpd_tls_session_cache_timeout = 3600s
+smtpd_tls_fingerprint_digest = sha256
+
+
+strict_rfc821_envelopes = yes
+smtpd_delay_reject = yes
+disable_vrfy_command = yes
+
+smtpd_client_restrictions =
+ permit_mynetworks
+ permit_tls_clientcerts
+ # We are the only ones using this proxy, but if things go wrong we
+ # want to know why
+ defer
smtpd_helo_required = yes
smtpd_helo_restrictions =
@@ -72,7 +86,8 @@ smtpd_recipient_restrictions =
reject_non_fqdn_recipient
reject_unknown_recipient_domain
permit_mynetworks
- reject_unauth_destination
+ permit_tls_clientcerts
+ reject
smtpd_data_restrictions =
reject_unauth_pipelining
diff --git a/roles/out/templates/etc/postfix/relay_clientcerts.j2 b/roles/out/templates/etc/postfix/relay_clientcerts.j2
new file mode 100644
index 0000000..3f724ea
--- /dev/null
+++ b/roles/out/templates/etc/postfix/relay_clientcerts.j2
@@ -0,0 +1,5 @@
+# {{ ansible_managed }}
+
+{% for x in relay_clientcerts.results %}
+{{ x.stdout }}
+{% endfor %}
diff --git a/roles/webmail/tasks/roundcube.yml b/roles/webmail/tasks/roundcube.yml
index 2085974..feb38ee 100644
--- a/roles/webmail/tasks/roundcube.yml
+++ b/roles/webmail/tasks/roundcube.yml
@@ -89,6 +89,8 @@
failed_when: r1.rc > 1
notify:
- Restart Nginx
+ tags:
+ - genkey
- name: Copy /etc/nginx/sites-available/roundcube
copy: src=etc/nginx/sites-available/roundcube
diff --git a/roles/webmail/templates/etc/postfix/main.cf.j2 b/roles/webmail/templates/etc/postfix/main.cf.j2
index b070881..595f618 100644
--- a/roles/webmail/templates/etc/postfix/main.cf.j2
+++ b/roles/webmail/templates/etc/postfix/main.cf.j2
@@ -40,7 +40,7 @@ local_recipient_maps =
message_size_limit = 67108864
recipient_delimiter = +
-# Forward everything to our internal mailhub
+# Forward everything to our internal outgoing proxy
{% if 'out' in group_names %}
relayhost = [127.0.0.1]:{{ postfix_instance.out.port }}
{% else %}
@@ -48,6 +48,7 @@ relayhost = [outgoing.fripost.org]:{{ postfix_instance.out.port }}
{% endif %}
relay_domains =
+
# Don't rewrite remote headers
local_header_rewrite_clients =
# Avoid splitting the envelope and scanning messages multiple times
@@ -55,17 +56,18 @@ smtp_destination_recipient_limit = 1000
# Tolerate occasional high latency
smtp_data_done_timeout = 1200s
-# Pass the mail to the antivirus
-#content_filter = amavisfeed:unix:public/amavisfeed-antivirus
-
-# Tunnel everything through IPSec
-smtp_tls_security_level = none
{% if 'out' in group_names %}
-smtp_bind_address = 127.0.0.1
+smtp_tls_security_level = none
+smtp_bind_address = 127.0.0.1
{% else %}
-smtp_bind_address = 172.16.0.1
+smtp_tls_security_level = encrypt
+smtp_tls_cert_file = /etc/postfix/ssl/{{ ansible_fqdn }}.pem
+smtp_tls_key_file = /etc/postfix/ssl/{{ ansible_fqdn }}.key
+smtp_tls_session_cache_database = btree:$data_directory/smtp_tls_session_cache
+smtp_tls_policy_maps = cdb:/etc/postfix/tls_policy
+smtp_tls_fingerprint_digest = sha256
{% endif %}
-smtpd_tls_security_level = none
+smtpd_tls_security_level = none
strict_rfc821_envelopes = yes
diff --git a/roles/webmail/templates/usr/share/roundcube/plugins/managesieve/config.inc.php.j2 b/roles/webmail/templates/usr/share/roundcube/plugins/managesieve/config.inc.php.j2
index c716ddc..d88a09a 100644
--- a/roles/webmail/templates/usr/share/roundcube/plugins/managesieve/config.inc.php.j2
+++ b/roles/webmail/templates/usr/share/roundcube/plugins/managesieve/config.inc.php.j2
@@ -26,7 +26,7 @@ $rcmail_config['managesieve_auth_pw'] = null;
// use or not TLS for managesieve server connection
// it's because I've problems with TLS and dovecot's managesieve plugin
// and it's not needed on localhost
-$rcmail_config['managesieve_usetls'] = FALSE;
+$rcmail_config['managesieve_usetls'] = TRUE;
// default contents of filters script (eg. default spam filter)
$rcmail_config['managesieve_default'] = '/etc/dovecot/sieve/global';