From b441dd4a7c3ce72008968d324a12e5c342d164a3 Mon Sep 17 00:00:00 2001 From: Guilhem Moulin Date: Sat, 9 Jul 2016 23:46:21 +0200 Subject: Route SMTP traffic from the webmail through IPsec. --- group_vars/all.yml | 38 ++++++++++---- roles/common/tasks/main.yml | 2 +- roles/out/templates/etc/postfix/main.cf.j2 | 7 ++- roles/webmail/handlers/main.yml | 3 -- roles/webmail/tasks/mail.yml | 32 ------------ roles/webmail/tasks/main.yml | 6 --- roles/webmail/tasks/roundcube.yml | 18 +++---- .../plugins/managesieve/config.inc.php.j2 | 2 +- roles/webmail/templates/etc/stunnel/smtp.conf.j2 | 58 ---------------------- webmail.yml | 2 +- 10 files changed, 44 insertions(+), 124 deletions(-) delete mode 100644 roles/webmail/tasks/mail.yml delete mode 100644 roles/webmail/templates/etc/stunnel/smtp.conf.j2 diff --git a/group_vars/all.yml b/group_vars/all.yml index a9bfda9..96f723b 100644 --- a/group_vars/all.yml +++ b/group_vars/all.yml @@ -1,15 +1,4 @@ --- -postfix_instance: - # The keys are the group names associated with a Postfix role, and the - # values are the name and group (optional) of the instance dedicated - # to that role. - IMAP: { name: mda, port: 2526 } - MX: { name: mx, group: mta } - out: { name: out, group: mta, port: 2525 } - MSA: { name: msa } - lists: { name: lists, port: 2527 } - - # Virtual (non-routable) IPv4 subnet for IPsec. It is always nullrouted # in the absence of xfrm lookup (i.e., when there is no matching IPsec # Security Association) to avoid data leaks. @@ -23,3 +12,30 @@ ipsec: elefant: 172.16.0.4 giraff: 172.16.0.5 mistral: 172.16.0.6 + + +postfix_instance: + # The keys are the group names associated with a Postfix role, and the + # values are the name and group (optional) of the instance dedicated + # to that role. + # For internal services, we also specify its (non-routable) IP address + # and port. + # XXX it's unfortunate that we can only specify a single address, and + # therefore have to limit the number of outgoing SMTP proxy and + # IMAP server to one. Since hosts(5) files cannot map and IP + # address to multiple hostnames, a workaround would be to use + # round-robin DNS, but we can't rely on DNS as long as our zone is + # unsigned. + IMAP: { name: mda + , addr: "{{ (groups.all | length > 1) | ternary( ipsec[ hostvars[groups.IMAP[0]].inventory_hostname_short ], '127.0.0.1') }}" + , port: 2526 } + MX: { name: mx, group: mta } + out: { name: out, group: mta + , addr: "{{ (groups.all | length > 1) | ternary( ipsec[ hostvars[groups.out[0]].inventory_hostname_short ], '127.0.0.1') }}" + , port: 2525 } + MSA: { name: msa } + lists: { name: lists + , addr: "{{ (groups.all | length > 1) | ternary( ipsec[ hostvars[groups.lists[0]].inventory_hostname_short ], '127.0.0.1') }}" + , port: 2527 } + +imapsvr_addr: "{{ postfix_instance.IMAP.addr | ipaddr }}" diff --git a/roles/common/tasks/main.yml b/roles/common/tasks/main.yml index e419bf3..2fe7a0e 100644 --- a/roles/common/tasks/main.yml +++ b/roles/common/tasks/main.yml @@ -15,7 +15,7 @@ - include: stunnel.yml tags: stunnel - when: "'webmail' in group_names and ('LDAP-provider' not in group_names or 'out' not in group_names)" + when: "'webmail' in group_names and 'LDAP-provider' not in group_names" - include: samhain.yml tags: samhain - include: auditd.yml diff --git a/roles/out/templates/etc/postfix/main.cf.j2 b/roles/out/templates/etc/postfix/main.cf.j2 index ddd46d5..34ac84e 100644 --- a/roles/out/templates/etc/postfix/main.cf.j2 +++ b/roles/out/templates/etc/postfix/main.cf.j2 @@ -27,8 +27,11 @@ multi_instance_group = {{ postfix_instance[inst].group | default('') }} multi_instance_name = postfix-{{ postfix_instance[inst].name }} multi_instance_enable = yes -mynetworks_style = host -inet_interfaces = all +mynetworks = 127.0.0.0/8, [::1]/128 +{%- if groups.all | length > 1 -%} + , {{ ipsec_subnet }} +{% endif %} +inet_interfaces = all # No local delivery mydestination = diff --git a/roles/webmail/handlers/main.yml b/roles/webmail/handlers/main.yml index 17a0dc4..d02cdda 100644 --- a/roles/webmail/handlers/main.yml +++ b/roles/webmail/handlers/main.yml @@ -1,7 +1,4 @@ --- -- name: Restart stunnel@smtp - service: name=stunnel4@smtp state=restarted - - name: Restart stunnel@ldap service: name=stunnel4@ldap state=restarted diff --git a/roles/webmail/tasks/mail.yml b/roles/webmail/tasks/mail.yml deleted file mode 100644 index 78eee38..0000000 --- a/roles/webmail/tasks/mail.yml +++ /dev/null @@ -1,32 +0,0 @@ -- name: Create /etc/stunnel/certs - file: path=/etc/stunnel/certs - state=directory - owner=root group=root - mode=0755 - -- name: Copy the SMTP outgoing proxy's X.509 certificate - assemble: src=certs/postfix regexp="{{ groups.out | difference([inventory_hostname]) | join('|') }}\.pem$" remote_src=no - dest=/etc/stunnel/certs/smtp.pem - owner=root group=root - mode=0644 - register: r1 - notify: - - Restart stunnel@smtp - -- name: Configure stunnel - template: src=etc/stunnel/smtp.conf.j2 - dest=/etc/stunnel/smtp.conf - owner=root group=root - mode=0644 - register: r2 - notify: - - Restart stunnel@smtp - -- name: Enable stunnel@smtp - service: name=stunnel4@smtp enabled=yes - -- name: Start stunnel@smtp - service: name=stunnel4@smtp state=started - when: not (r1.changed or r2.changed) - -- meta: flush_handlers diff --git a/roles/webmail/tasks/main.yml b/roles/webmail/tasks/main.yml index 9c40a34..cd9f0c7 100644 --- a/roles/webmail/tasks/main.yml +++ b/roles/webmail/tasks/main.yml @@ -1,9 +1,3 @@ -- include: mail.yml - when: "'out' not in group_names" - tags: - - postfix - - mail - - stunnel - include: ldap.yml when: "'LDAP-provider' not in group_names" tags: diff --git a/roles/webmail/tasks/roundcube.yml b/roles/webmail/tasks/roundcube.yml index 41ef907..d1fb8a2 100644 --- a/roles/webmail/tasks/roundcube.yml +++ b/roles/webmail/tasks/roundcube.yml @@ -49,16 +49,16 @@ # IMAP # WARNING: After hostname change update of mail_host column in users # table is required to match old user data records with the new host. - - { var: default_host, value: "'{{ ipsec[imapsvr.inventory_hostname_short] }}'" } - - { var: default_port, value: "143" } - - { var: imap_auth_type, value: "'PLAIN'" } - - { var: imap_cache, value: "null" } - - { var: imap_timeout, value: "180" } - - { var: imap_force_ns, value: "true" } - - { var: messages_cache, value: "false" } + - { var: default_host, value: "'{{ imapsvr_addr | ipaddr }}'" } + - { var: default_port, value: "143" } + - { var: imap_auth_type, value: "'PLAIN'" } + - { var: imap_cache, value: "null" } + - { var: imap_timeout, value: "180" } + - { var: imap_force_ns, value: "true" } + - { var: messages_cache, value: "false" } # SMTP - - { var: smtp_server, value: "'localhost'" } - - { var: smtp_port, value: "2525" } + - { var: smtp_server, value: "'{{ postfix_instance.out.addr | ipaddr }}'" } + - { var: smtp_port, value: "{{ postfix_instance.out.port }}" } # System - { var: force_https, value: "true" } - { var: login_autocomplete, value: "2" } diff --git a/roles/webmail/templates/etc/roundcube/plugins/managesieve/config.inc.php.j2 b/roles/webmail/templates/etc/roundcube/plugins/managesieve/config.inc.php.j2 index dcaca06..66af466 100644 --- a/roles/webmail/templates/etc/roundcube/plugins/managesieve/config.inc.php.j2 +++ b/roles/webmail/templates/etc/roundcube/plugins/managesieve/config.inc.php.j2 @@ -10,7 +10,7 @@ $config['managesieve_port'] = 4190; // %n - http hostname ($_SERVER['SERVER_NAME']) // %d - domain (http hostname without the first part) // For example %n = mail.domain.tld, %d = domain.tld -$config['managesieve_host'] = '{{ ipsec[imapsvr.inventory_hostname_short] }}'; +$config['managesieve_host'] = '{{ imapsvr_addr | ipaddr }}'; // authentication method. Can be CRAM-MD5, DIGEST-MD5, PLAIN, LOGIN, EXTERNAL // or none. Optional, defaults to best method supported by server. diff --git a/roles/webmail/templates/etc/stunnel/smtp.conf.j2 b/roles/webmail/templates/etc/stunnel/smtp.conf.j2 deleted file mode 100644 index ba38bfa..0000000 --- a/roles/webmail/templates/etc/stunnel/smtp.conf.j2 +++ /dev/null @@ -1,58 +0,0 @@ -; ************************************************************************** -; * Global options * -; ************************************************************************** - -; setuid()/setgid() to the specified user/group in daemon mode -setuid = stunnel4 -setgid = stunnel4 - -; PID is created inside the chroot jail -pid = -foreground = yes - -; Only log messages at severity warning (4) and higher -debug = 4 - -; ************************************************************************** -; * Service defaults may also be specified in individual service sections * -; ************************************************************************** - -; Certificate/key is needed in server mode and optional in client mode -cert = /etc/postfix/ssl/{{ ansible_fqdn }}.pem -key = /etc/postfix/ssl/{{ ansible_fqdn }}.key -client = yes -socket = a:SO_BINDTODEVICE=lo - -; Some performance tunings -socket = l:TCP_NODELAY=1 -socket = r:TCP_NODELAY=1 - -; Prevent MITM attacks -verify = 4 - -; Disable support for insecure protocols -options = NO_SSLv2 -options = NO_SSLv3 -options = NO_TLSv1 -options = NO_TLSv1.1 - -options = NO_COMPRESSION - -; These options provide additional security at some performance degradation -options = SINGLE_ECDH_USE -options = SINGLE_DH_USE - -; Select permitted SSL ciphers -ciphers = EECDH+AESGCM:!MEDIUM:!LOW:!EXP:!aNULL:!eNULL - -; ************************************************************************** -; * Service definitions (remove all services for inetd mode) * -; ************************************************************************** - -[smtp] -accept = localhost:2525 -connect = outgoing.fripost.org:{{ postfix_instance.out.port }} -CAfile = /etc/stunnel/certs/smtp.pem -protocol = smtp - -; vim:ft=dosini diff --git a/webmail.yml b/webmail.yml index cd5100f..0ef0487 100644 --- a/webmail.yml +++ b/webmail.yml @@ -2,4 +2,4 @@ - name: Configure the webmail hosts: webmail roles: - - { role: webmail, imapsvr: "{{ hostvars[groups.IMAP[0]] }}" } + - webmail -- cgit v1.2.3