diff options
-rw-r--r-- | all.yml | 1 | ||||
-rw-r--r-- | group_vars/all.yml | 12 | ||||
-rw-r--r-- | out.yml | 8 | ||||
-rw-r--r-- | roles/IMAP/templates/etc/amavis/conf.d/50-user.j2 | 6 | ||||
-rw-r--r-- | roles/MSA/templates/etc/postfix/main.cf.j2 | 8 | ||||
-rw-r--r-- | roles/MX/templates/etc/postfix/main.cf.j2 | 8 | ||||
-rw-r--r-- | roles/common/files/etc/postfix/master.cf | 1 | ||||
-rw-r--r-- | roles/common/templates/etc/iptables/services.j2 | 3 | ||||
-rw-r--r-- | roles/common/templates/etc/postfix/main.cf.j2 | 8 | ||||
-rw-r--r-- | roles/lists/templates/etc/postfix/main.cf.j2 | 8 | ||||
-rw-r--r-- | roles/out/handlers/main.yml | 9 | ||||
-rw-r--r-- | roles/out/tasks/main.yml | 17 | ||||
-rw-r--r-- | roles/out/templates/etc/postfix/main.cf.j2 | 78 | ||||
-rw-r--r-- | roles/webmail/templates/etc/postfix/main.cf.j2 | 8 |
14 files changed, 146 insertions, 29 deletions
@@ -1,10 +1,11 @@ --- # Example: # ansible-playbook -i stage_vms all.yml -t rkhunter - include: common.yml - include: IMAP.yml - include: MX.yml - include: MSA.yml +- include: out.yml - include: webmail.yml - include: lists.yml diff --git a/group_vars/all.yml b/group_vars/all.yml index 351aa09..ef9fc82 100644 --- a/group_vars/all.yml +++ b/group_vars/all.yml @@ -1,11 +1,11 @@ --- 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 } - MTA-out: { name: mta-out,group: mta, port: 2525 } - MSA: { name: msa } - webmail: { name: webmail } - lists: { name: lists, port: 2527 } + IMAP: { name: mda, port: 2526 } + MX: { name: mx, group: mta } + out: { name: out, group: mta, port: 2525 } + MSA: { name: msa } + webmail: { name: webmail } + lists: { name: lists, port: 2527 } @@ -0,0 +1,8 @@ +--- +- name: Configure the outgoing SMTP proxy + hosts: out + roles: + - { role: out, inst: out } + tags: + - mail + - postfix diff --git a/roles/IMAP/templates/etc/amavis/conf.d/50-user.j2 b/roles/IMAP/templates/etc/amavis/conf.d/50-user.j2 index 503907e..b3ae7a9 100644 --- a/roles/IMAP/templates/etc/amavis/conf.d/50-user.j2 +++ b/roles/IMAP/templates/etc/amavis/conf.d/50-user.j2 @@ -93,43 +93,43 @@ $default_ldap = { query_filter => '(&(objectClass=amavisAccount)(ObjectClass=FripostVirtualUser)(fvl=%m))' }; $recipient_delimiter = '+'; $enable_dkim_verification = 1; # enable DKIM signatures verification # Per-recipient Bayes Database. @sa_username_maps = ( new_RE ( [ qr'^(.+@[^@]+)$'i => '$1' ] ), 'amavis' # catch-all ); # http://www.ijs.si/software/amavisd/amavisd-new-docs.html#pbanks-ex $inet_socket_port = 10041; $interface_policy{'10041'} = 'INBOUND'; -{% if 'MTA-out' in group_names %} -$notify_method = 'smtp:[127.0.0.1]:{{ postfix_instance["MTA-out"].port }}'; +{% if 'out' in group_names %} +$notify_method = 'smtp:[127.0.0.1]:{{ postfix_instance.out.port }}'; {% else %} -$notify_method = 'smtp:[outgoing.fripost.org]:{{ postfix_instance["MTA-out"].port }}'; +$notify_method = 'smtp:[outgoing.fripost.org]:{{ postfix_instance.out.port }}'; {% endif %} $forward_method = 'lmtp:/var/run/dovecot/lmtp'; $requeue_method = $forward_method; $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; $policy_bank{'INBOUND'} = { originating => 0, # indicates a remote client, allows checking smtpd_greeting_banner => '${helo-name} ${protocol} ${product} INBOUND service ready', mynetworks_maps => [], # avoids loading MYNETS policy unnecessarily }; #------------ Do not modify anything below this line ------------- 1; # ensure a defined return diff --git a/roles/MSA/templates/etc/postfix/main.cf.j2 b/roles/MSA/templates/etc/postfix/main.cf.j2 index e363d70..e3014aa 100644 --- a/roles/MSA/templates/etc/postfix/main.cf.j2 +++ b/roles/MSA/templates/etc/postfix/main.cf.j2 @@ -24,61 +24,61 @@ 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 # This server is a Mail Submission Agent mynetworks_style = host 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 = 67108864 recipient_delimiter = + # Forward everything to our internal mailhub -{% if 'MTA-out' in group_names %} -relayhost = [127.0.0.1]:{{ postfix_instance["MTA-out"].port }} +{% if 'out' in group_names %} +relayhost = [127.0.0.1]:{{ postfix_instance.out.port }} {% else %} -relayhost = [outgoing.fripost.org]:{{ postfix_instance["MTA-out"].port }} +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 smtp_destination_recipient_limit = 1000 # Tolerate occasional high latency smtp_data_done_timeout = 1200s # Anonymize the (authenticated) sender; pass the mail to the antivirus header_checks = pcre:$config_directory/anonymize_sender.pcre #content_filter = amavisfeed:unix:public/amavisfeed-antivirus # Tunnel everything through IPSec smtp_tls_security_level = none -{% if 'MTA-out' in group_names %} +{% if 'out' in group_names %} smtp_bind_address = 127.0.0.1 {% else %} smtp_bind_address = 172.16.0.1 {% 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_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 smtpd_sasl_authenticated_header = no smtpd_sasl_local_domain = diff --git a/roles/MX/templates/etc/postfix/main.cf.j2 b/roles/MX/templates/etc/postfix/main.cf.j2 index 4dbbbcb..34e38a0 100644 --- a/roles/MX/templates/etc/postfix/main.cf.j2 +++ b/roles/MX/templates/etc/postfix/main.cf.j2 @@ -25,78 +25,78 @@ 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 # This server is a Mail eXchange mynetworks_style = host 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 = 67108864 recipient_delimiter = + # Forward everything to our internal mailhub -{% if 'MTA-out' in group_names %} -relayhost = [127.0.0.1]:{{ postfix_instance["MTA-out"].port }} +{% if 'out' in group_names %} +relayhost = [127.0.0.1]:{{ postfix_instance.out.port }} {% else %} -relayhost = [outgoing.fripost.org]:{{ postfix_instance["MTA-out"].port }} +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 # tranport_maps. virtual_transport = error:5.1.1 Virtual transport unavailable virtual_mailbox_domains = ldap:$config_directory/virtual/mailbox_domains.cf virtual_alias_maps = pcre:$config_directory/virtual/reserved_alias.pcre # first we do the alias resolution... ldap:$config_directory/virtual/alias.cf # ...and unless there is matching mailbox/list... ldap:$config_directory/virtual/mailbox.cf ldap:$config_directory/virtual/list.cf # ...we resolve alias domains and catch alls ldap:$config_directory/virtual/alias_domains.cf ldap:$config_directory/virtual/catchall.cf 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 smtp_send_xforward_command = yes # Avoid splitting the envelope and scanning messages multiple times smtp_destination_recipient_limit = 1000 reserved-alias_recipient_limit = 1 # Tolerate occasional high latency smtp_data_done_timeout = 1200s # Tunnel everything through IPSec smtp_tls_security_level = none -{% if 'MTA-out' in group_names %} +{% if 'out' in group_names %} smtp_bind_address = 127.0.0.1 {% else %} smtp_bind_address = 172.16.0.1 {% endif %} # 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 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 # http://www.howtoforge.com/block_spam_at_mta_level_postfix diff --git a/roles/common/files/etc/postfix/master.cf b/roles/common/files/etc/postfix/master.cf index 4fdbff3..e845371 100644 --- a/roles/common/files/etc/postfix/master.cf +++ b/roles/common/files/etc/postfix/master.cf @@ -22,34 +22,35 @@ verify unix - - - - 1 verify flush unix n - - 1000? 0 flush proxymap unix - - n - - proxymap 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 error unix - - - - - error retry unix - - - - - error discard unix - - - - - discard local unix - n n - - local virtual unix - n n - - virtual lmtp unix - - - - - lmtp anvil unix - - - - 1 anvil scache unix - - - - 1 scache 127.0.0.1:16132 inet n - - - - smtpd +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 flags=Rhu user=mlmmj argv=/usr/bin/mlmmj-receive -L /var/spool/mlmmj/${domain}/${user} amavisfeed unix - - n - 2 lmtp -o lmtp_destination_recipient_limit=1000 -o lmtp_send_xforward_command=yes -o lmtp_data_done_timeout=1200s diff --git a/roles/common/templates/etc/iptables/services.j2 b/roles/common/templates/etc/iptables/services.j2 index 4e21dfc..923aa35 100644 --- a/roles/common/templates/etc/iptables/services.j2 +++ b/roles/common/templates/etc/iptables/services.j2 @@ -2,30 +2,33 @@ # Do NOT edit this file directly! # # 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 {% if 'NTP-master' in group_names %} out udp 123 123 # NTP {% endif %} in tcp {{ ansible_ssh_port|default('22') }} # SSH {% if 'MX' in group_names %} in tcp 25 # SMTP {% endif %} +{% if 'out' in group_names %} +#out tcp 25 # SMTP +{% endif %} {% if 'IMAP' in group_names %} in tcp 993 # IMAPS in tcp 4190 # ManageSieve {% endif %} {% if 'MSA' in group_names %} in tcp 587 # SMTP-AUTH {% endif %} {% if 'webmail' in group_names %} in tcp 80,443 # HTTP/HTTPS {% endif %} diff --git a/roles/common/templates/etc/postfix/main.cf.j2 b/roles/common/templates/etc/postfix/main.cf.j2 index e594c1e..70d4b98 100644 --- a/roles/common/templates/etc/postfix/main.cf.j2 +++ b/roles/common/templates/etc/postfix/main.cf.j2 @@ -14,50 +14,50 @@ myhostname = {{ ansible_fqdn }} mydomain = {{ ansible_domain }} 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 = local_transport = error:5.1.1 Mailbox unavailable alias_maps = local_recipient_maps = # All aliases are virtual default_database_type = cdb virtual_alias_maps = cdb:/etc/aliases alias_database = $virtual_alias_maps # Forward everything to our internal mailhub -{% if 'MTA-out' in group_names %} -relayhost = [127.0.0.1]:{{ postfix_instance["MTA-out"].port }} +{% if 'out' in group_names %} +relayhost = [127.0.0.1]:{{ postfix_instance.out.port }} {% else %} -relayhost = [outgoing.fripost.org]:{{ postfix_instance["MTA-out"].port }} +relayhost = [outgoing.fripost.org]:{{ postfix_instance.out.port }} {% endif %} relay_domains = # Tunnel everything through IPSec smtp_tls_security_level = none -{% if 'MTA-out' in group_names %} +{% if 'out' in group_names %} smtp_bind_address = 127.0.0.1 {% else %} smtp_bind_address = 172.16.0.1 {% endif %} 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. master_service_disable = !127.0.0.1:16132.inet inet {% set multi_instance = False %} {%- for g in postfix_instance.keys() | sort -%} {%- if g in group_names -%} {%- if not multi_instance -%} {%- set multi_instance = True -%} ## Other postfix instances multi_instance_wrapper = $command_directory/postmulti -p -- multi_instance_enable = yes multi_instance_directories = {%- endif %} /etc/postfix-{{ postfix_instance[g].name }} diff --git a/roles/lists/templates/etc/postfix/main.cf.j2 b/roles/lists/templates/etc/postfix/main.cf.j2 index 45e66aa..083fa2b 100644 --- a/roles/lists/templates/etc/postfix/main.cf.j2 +++ b/roles/lists/templates/etc/postfix/main.cf.j2 @@ -30,47 +30,47 @@ 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 # No local delivery mydestination = local_transport = error:5.1.1 Mailbox unavailable alias_maps = alias_database = local_recipient_maps = message_size_limit = 67108864 recipient_delimiter = + # Forward everything to our internal mailhub -{% if 'MTA-out' in group_names %} -relayhost = [127.0.0.1]:{{ postfix_instance["MTA-out"].port }} +{% if 'out' in group_names %} +relayhost = [127.0.0.1]:{{ postfix_instance.out.port }} {% else %} -relayhost = [outgoing.fripost.org]:{{ postfix_instance["MTA-out"].port }} +relayhost = [outgoing.fripost.org]:{{ postfix_instance.out.port }} {% endif %} relay_domains = # Virtual transport (the alias resolution is already done by the MX:es) transport_maps = ldap:$config_directory/virtual/transport_list.cf mlmmj_destination_recipient_limit = 1 # Don't rewrite remote headers local_header_rewrite_clients = # Avoid splitting the envelope and scanning messages multiple times smtp_destination_recipient_limit = 1000 # Tolerate occasional high latency smtp_data_done_timeout = 1200s smtpd_timeout = 1200s # Tunnel everything through IPSec smtp_tls_security_level = none -{% if 'MTA-out' in group_names %} +{% if 'out' in group_names %} smtp_bind_address = 127.0.0.1 {% else %} smtp_bind_address = 172.16.0.1 {% endif %} smtpd_tls_security_level = none diff --git a/roles/out/handlers/main.yml b/roles/out/handlers/main.yml new file mode 100644 index 0000000..21c736a --- /dev/null +++ b/roles/out/handlers/main.yml @@ -0,0 +1,9 @@ +--- +- name: Restart Postgrey + service: name=postgrey state=restarted + +- name: Restart Postfix + service: name=postfix state=restarted + +- name: Reload Postfix + service: name=postfix state=reloaded diff --git a/roles/out/tasks/main.yml b/roles/out/tasks/main.yml new file mode 100644 index 0000000..4bf4363 --- /dev/null +++ b/roles/out/tasks/main.yml @@ -0,0 +1,17 @@ +- name: Install Postfix + apt: pkg=postfix + +- name: Configure Postfix + template: src=etc/postfix/main.cf.j2 + dest=/etc/postfix-{{ postfix_instance[inst].name }}/main.cf + owner=root group=root + mode=0644 + register: r + notify: + - Restart Postfix + +- name: Start Postfix + service: name=postfix state=started + when: not r.changed + +- meta: flush_handlers diff --git a/roles/out/templates/etc/postfix/main.cf.j2 b/roles/out/templates/etc/postfix/main.cf.j2 new file mode 100644 index 0000000..1a7985f --- /dev/null +++ b/roles/out/templates/etc/postfix/main.cf.j2 @@ -0,0 +1,78 @@ +######################################################################## +# Outgoing MTA configuration +# +# {{ ansible_managed }} +# Do NOT edit this file directly! + +smtpd_banner = $myhostname ESMTP $mail_name (Debian/GNU) +biff = no +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 = !2525.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 + +# 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 + +# No local delivery +mydestination = +local_transport = error:5.1.1 Mailbox unavailable +alias_maps = +alias_database = +local_recipient_maps = + +message_size_limit = 67108864 +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_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 + + +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 + reject_unauth_destination + +smtpd_data_restrictions = + reject_unauth_pipelining diff --git a/roles/webmail/templates/etc/postfix/main.cf.j2 b/roles/webmail/templates/etc/postfix/main.cf.j2 index 76efb59..b070881 100644 --- a/roles/webmail/templates/etc/postfix/main.cf.j2 +++ b/roles/webmail/templates/etc/postfix/main.cf.j2 @@ -24,60 +24,60 @@ 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 # This server is a nullclient mynetworks_style = host inet_interfaces = loopback-only # No local delivery mydestination = local_transport = error:5.1.1 Mailbox unavailable alias_maps = alias_database = local_recipient_maps = message_size_limit = 67108864 recipient_delimiter = + # Forward everything to our internal mailhub -{% if 'MTA-out' in group_names %} -relayhost = [127.0.0.1]:{{ postfix_instance["MTA-out"].port }} +{% if 'out' in group_names %} +relayhost = [127.0.0.1]:{{ postfix_instance.out.port }} {% else %} -relayhost = [outgoing.fripost.org]:{{ postfix_instance["MTA-out"].port }} +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 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 'MTA-out' in group_names %} +{% if 'out' in group_names %} smtp_bind_address = 127.0.0.1 {% else %} smtp_bind_address = 172.16.0.1 {% endif %} smtpd_tls_security_level = none strict_rfc821_envelopes = yes smtpd_delay_reject = yes disable_vrfy_command = yes # UCE control unknown_client_reject_code = 554 smtpd_client_restrictions = permit_mynetworks reject smtpd_helo_required = yes smtpd_helo_restrictions = |