diff options
author | Guilhem Moulin <guilhem@fripost.org> | 2016-07-09 23:46:21 +0200 |
---|---|---|
committer | Guilhem Moulin <guilhem@fripost.org> | 2016-07-10 01:07:39 +0200 |
commit | b441dd4a7c3ce72008968d324a12e5c342d164a3 (patch) | |
tree | 8375a25dfb8a91d3d16cf426851cd1049bb508b3 | |
parent | 418b3303f17776e64341f990d13e98ce6f662bf5 (diff) |
Route SMTP traffic from the webmail through IPsec.
-rw-r--r-- | group_vars/all.yml | 38 | ||||
-rw-r--r-- | roles/common/tasks/main.yml | 2 | ||||
-rw-r--r-- | roles/out/templates/etc/postfix/main.cf.j2 | 7 | ||||
-rw-r--r-- | roles/webmail/handlers/main.yml | 3 | ||||
-rw-r--r-- | roles/webmail/tasks/mail.yml | 32 | ||||
-rw-r--r-- | roles/webmail/tasks/main.yml | 6 | ||||
-rw-r--r-- | roles/webmail/tasks/roundcube.yml | 18 | ||||
-rw-r--r-- | roles/webmail/templates/etc/roundcube/plugins/managesieve/config.inc.php.j2 | 2 | ||||
-rw-r--r-- | roles/webmail/templates/etc/stunnel/smtp.conf.j2 | 58 | ||||
-rw-r--r-- | webmail.yml | 2 |
10 files changed, 44 insertions, 124 deletions
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,25 +1,41 @@ --- -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. ipsec_subnet: 172.16.0.0/24 ipsec: # Virtual (non-routable) addresses for IPsec. They all need to be # distinct and belong to the above subnet 'ipsec_subnet'. antilop: 172.16.0.1 benjamin: 172.16.0.2 civett: 172.16.0.3 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 @@ -1,38 +1,38 @@ --- - include: sysctl.yml tags: sysctl - include: hosts.yml - include: apt.yml tags: apt - name: Install intel-microcode apt: pkg=intel-microcode when: "ansible_processor[0] | search('^(Genuine)?Intel.*') and not (ansible_virtualization_role == 'guest' and ansible_virtualization_type == 'xen')" tags: intel - include: firewall.yml tags: - firewall - iptables - 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 tags: auditd - include: rkhunter.yml tags: rkhunter - include: clamav.yml tags: clamav - include: fail2ban.yml tags: fail2ban - include: smart.yml tags: - smartmontools - smart when: "not ((ansible_virtualization_role == 'guest' and ansible_virtualization_type == 'xen') or ansible_system_vendor == 'QEMU')" - include: haveged.yml tags: - haveged - entropy - name: Copy genkeypair.sh and gendhparam.sh 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 @@ -10,42 +10,45 @@ readme_directory = no mail_owner = postfix delay_warning_time = 1d maximal_queue_lifetime = 5d myorigin = /etc/mailname myhostname = outgoing{{ outgoingno | default('') }}.$mydomain mydomain = fripost.org append_dot_mydomain = no # Turn off all TCP/IP listener ports except that necessary for the # outgoing SMTP proxy. master_service_disable = !{{ postfix_instance.out.port }}.inet !127.0.0.1:10025.inet inet queue_directory = /var/spool/postfix-{{ postfix_instance[inst].name }} data_directory = /var/lib/postfix-{{ postfix_instance[inst].name }} 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 = local_transport = error:5.1.1 Mailbox unavailable alias_maps = alias_database = local_recipient_maps = message_size_limit = 0 recipient_delimiter = + relay_domains = relay_transport = error:5.3.2 Relay Transport unavailable # All header rewriting happens upstream local_header_rewrite_clients = smtp_tls_security_level = may smtp_tls_ciphers = medium 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,9 +1,6 @@ --- -- name: Restart stunnel@smtp - service: name=stunnel4@smtp state=restarted - - name: Restart stunnel@ldap service: name=stunnel4@ldap state=restarted - name: Restart Nginx service: name=nginx 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,15 +1,9 @@ -- include: mail.yml - when: "'out' not in group_names" - tags: - - postfix - - mail - - stunnel - include: ldap.yml when: "'LDAP-provider' not in group_names" tags: - ldap - stunnel - include: roundcube.yml tags: - roundcube - webmail 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 @@ -32,50 +32,50 @@ copy: src=usr/share/roundcube/skins/{{ item }}/images/fripost_logo.png dest=/usr/share/roundcube/skins/{{ item }}/images/fripost_logo.png owner=root group=root mode=0644 with_items: - classic - larry - name: Configure Roundcube lineinfile: dest=/etc/roundcube/config.inc.php regexp='^\\s*\\$config\\[\'{{ item.var }}\'\\]\\s*=' line='$config[\'{{ item.var }}\'] = {{ item.value }};' owner=root group=www-data mode=0640 with_items: # Logging/Debugging - { var: smtp_log, value: "false" } # 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" } - { var: skin_logo, value: "'/images/fripost_logo.png'" } - { var: username_domain, value: "'fripost.org'" } - { var: product_name, value: "'Fripost Webmail'" } # Plugins - { var: plugins, value: "array('archive','additional_message_headers','managesieve','password')" } # Spell Checking - { var: enable_spellcheck, value: "'true'" } - { var: spellcheck_engine, value: "'enchant'" } - { var: spellcheck_languages, value: "array('da','de','en','es','fr','no','sv')" } # User Interface - { var: skin, value: "'larry'" } - { var: language, value: "'sv_SE'" } - { var: create_default_folders, value: "true" } - { var: support_url, value: "'https://fripost.org/kontakt/'" } # User Preferences - { var: htmleditor, value: "3" } - { var: skip_deleted, value: "true" } 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 @@ -1,33 +1,33 @@ <?php // managesieve server port. When empty the port will be determined automatically // using getservbyname() function, with 4190 as a fallback. $config['managesieve_port'] = 4190; // managesieve server address, default is localhost. // Replacement variables supported in host name: // %h - user's IMAP hostname // %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. $config['managesieve_auth_type'] = 'PLAIN'; // Optional managesieve authentication identifier to be used as authorization proxy. // Authenticate as a different user but act on behalf of the logged in user. // Works with PLAIN and DIGEST-MD5 auth. $config['managesieve_auth_cid'] = null; // Optional managesieve authentication password to be used for imap_auth_cid $config['managesieve_auth_pw'] = null; // use or not TLS for managesieve server connection // Note: tls:// prefix in managesieve_host is also supported $config['managesieve_usetls'] = false; // Connection scket context options // See http://php.net/manual/en/context.ssl.php // The example below enables server certificate validation 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 @@ -1,5 +1,5 @@ --- - name: Configure the webmail hosts: webmail roles: - - { role: webmail, imapsvr: "{{ hostvars[groups.IMAP[0]] }}" } + - webmail |