From 4a841439606768e8b8783f4a1bd32096a7bbcd9c Mon Sep 17 00:00:00 2001 From: Guilhem Moulin Date: Wed, 4 Apr 2018 16:20:03 +0200 Subject: Harden anti spam on the MX:es. --- .../etc/postfix/reject-unknown-client-hostname.cf | 10 +++++ roles/MX/tasks/main.yml | 9 ++++ roles/MX/templates/etc/postfix/access-list.cidr.j2 | 16 +++++++ roles/MX/templates/etc/postfix/main.cf.j2 | 51 ++++++++++++++-------- .../etc/logcheck/ignore.d.server/postfix-local | 5 ++- 5 files changed, 71 insertions(+), 20 deletions(-) create mode 100644 roles/MX/files/etc/postfix/reject-unknown-client-hostname.cf create mode 100644 roles/MX/templates/etc/postfix/access-list.cidr.j2 (limited to 'roles') diff --git a/roles/MX/files/etc/postfix/reject-unknown-client-hostname.cf b/roles/MX/files/etc/postfix/reject-unknown-client-hostname.cf new file mode 100644 index 0000000..6969f75 --- /dev/null +++ b/roles/MX/files/etc/postfix/reject-unknown-client-hostname.cf @@ -0,0 +1,10 @@ +server_host = ldapi://%2Fvar%2Fspool%2Fpostfix-mx%2Fprivate%2Fldapi/ +version = 3 +search_base = fvd=%d,ou=virtual,dc=fripost,dc=org +domain = static:all +scope = one +bind = sasl +sasl_mechs = EXTERNAL +query_filter = (&(objectClass=FripostVirtualList)(!(objectClass=FripostPendingEntry))(fvl=%u)(fripostIsStatusActive=TRUE)) +result_attribute = fvl +result_format = reject_unknown_client_hostname diff --git a/roles/MX/tasks/main.yml b/roles/MX/tasks/main.yml index bd6f088..78362ca 100644 --- a/roles/MX/tasks/main.yml +++ b/roles/MX/tasks/main.yml @@ -17,6 +17,7 @@ with_items: - main.cf - master.cf + - access-list.cidr notify: - Reload Postfix @@ -61,6 +62,14 @@ owner=root group=root mode=0644 +- name: Copy recipient access(5) map + copy: src=etc/postfix/reject-unknown-client-hostname.cf + dest=/etc/postfix-{{ postfix_instance[inst].name }}/reject-unknown-client-hostname.cf + owner=root group=root + mode=0644 + notify: + - Reload Postfix + - name: Compile the Postfix transport maps # trivial-rewrite(8) is a long-running process, so it's safer to reload postmap: instance={{ postfix_instance[inst].name }} diff --git a/roles/MX/templates/etc/postfix/access-list.cidr.j2 b/roles/MX/templates/etc/postfix/access-list.cidr.j2 new file mode 100644 index 0000000..bd6e3d8 --- /dev/null +++ b/roles/MX/templates/etc/postfix/access-list.cidr.j2 @@ -0,0 +1,16 @@ +######################################################################## +# Access list, see cidr_table(5) +# +# {{ ansible_managed }} +# Do NOT edit this file directly! + +{% if ipsec_subnet is defined %} +{{ ipsec_subnet }} permit +{% endif %} + +{% for ip in lookup('pipe', 'dig +short outgoing.fripost.org A').splitlines() | sort -%} +{{ ip }}/32 permit +{% endfor %} +{% for ip in lookup('pipe', 'dig +short outgoing.fripost.org AAAA').splitlines() | sort -%} +{{ ip }}/128 permit +{% endfor %} diff --git a/roles/MX/templates/etc/postfix/main.cf.j2 b/roles/MX/templates/etc/postfix/main.cf.j2 index 8e6040f..e5792c4 100644 --- a/roles/MX/templates/etc/postfix/main.cf.j2 +++ b/roles/MX/templates/etc/postfix/main.cf.j2 @@ -93,40 +93,44 @@ invalid_hostname_reject_code = 554 multi_recipient_bounce_reject_code = 554 non_fqdn_reject_code = 554 relay_domains_reject_code = 554 -unknown_address_reject_code = 554 -unknown_client_reject_code = 554 -unknown_hostname_reject_code = 554 unknown_local_recipient_reject_code = 554 unknown_relay_recipient_reject_code = 554 unknown_virtual_alias_reject_code = 554 unknown_virtual_mailbox_reject_code = 554 +postscreen_access_list = + permit_mynetworks + cidr:$config_directory/access-list.cidr postscreen_dnsbl_whitelist_threshold = -1 + postscreen_blacklist_action = drop -postscreen_dnsbl_threshold = 3 +postscreen_dnsbl_threshold = 8 postscreen_dnsbl_action = enforce postscreen_dnsbl_sites = - zen.spamhaus.org*2 + zen.spamhaus.org=127.0.0.[10;11]*8 + zen.spamhaus.org=127.0.0.[4..7]*6 + zen.spamhaus.org=127.0.0.3*4 + zen.spamhaus.org=127.0.0.2*3 #swl.spamhaus.org*-4 - b.barracudacentral.org*2 - bl.spameatingmonkey.net*2 - bl.spamcop.net - dnsbl.sorbs.net - psbl.surriel.com - bl.mailspike.net + b.barracudacentral.org=127.0.0.2*7 + bl.mailspike.net=127.0.0.2*5 + bl.mailspike.net=127.0.0.[10..12]*4 + wl.mailspike.net=127.0.0.[18..20]*-2 + bl.spameatingmonkey.net=127.0.0.2*4 + bl.spamcop.net=127.0.0.2*2 + dnsbl.sorbs.net=127.0.0.10*8 + dnsbl.sorbs.net=127.0.0.5*6 + dnsbl.sorbs.net=127.0.0.7*3 + dnsbl.sorbs.net=127.0.0.8*2 + dnsbl.sorbs.net=127.0.0.6*2 + dnsbl.sorbs.net=127.0.0.9*2 list.dnswl.org=127.0.[0..255].0*-2 list.dnswl.org=127.0.[0..255].1*-3 list.dnswl.org=127.0.[0..255].[2..3]*-4 postscreen_greet_action = enforce -postscreen_whitelist_interfaces = -{%- for ip in lookup('pipe', 'dig +short '+ postfix_instance.MX.backup +' A').splitlines() %} - !{{ ip }} -{%- endfor %} -{%- for ip in lookup('pipe', 'dig +short '+ postfix_instance.MX.backup +' AAAA').splitlines() %} - ![{{ ip }}] -{%- endfor %} - static:all +postscreen_whitelist_interfaces = static:all + smtpd_client_restrictions = permit_mynetworks @@ -139,6 +143,7 @@ smtpd_helo_restrictions = smtpd_sender_restrictions = reject_non_fqdn_sender + reject_unknown_sender_domain smtpd_relay_restrictions = reject_non_fqdn_recipient @@ -146,6 +151,14 @@ smtpd_relay_restrictions = reject_unauth_destination reject_unlisted_recipient +smtpd_recipient_restrictions = + check_client_access cidr:$config_directory/access-list.cidr + check_recipient_access ldap:$config_directory/reject-unknown-client-hostname.cf + reject_rhsbl_reverse_client dbl.spamhaus.org=127.0.1.[2..99] + reject_rhsbl_sender dbl.spamhaus.org=127.0.1.[2..99] + defer_if_reject reject_rhsbl_reverse_client dbl.spamhaus.org=127.0.1.[100..254] + defer_if_reject reject_rhsbl_sender dbl.spamhaus.org=127.0.1.[100..254] + smtpd_data_restrictions = reject_unauth_pipelining diff --git a/roles/common/files/etc/logcheck/ignore.d.server/postfix-local b/roles/common/files/etc/logcheck/ignore.d.server/postfix-local index 2ca704d..e32fce6 100644 --- a/roles/common/files/etc/logcheck/ignore.d.server/postfix-local +++ b/roles/common/files/etc/logcheck/ignore.d.server/postfix-local @@ -29,7 +29,10 @@ ^\w{3} [ :[:digit:]]{11} [._[:alnum:]-]+ postfix-(msa|mx)/smtpd\[[[:digit:]]+\]: improper command pipelining after (EHLO|HELO|MAIL|QUIT) from [._[:alnum:]-]+\[[[:xdigit:].:]{3,39}\]: ^\w{3} [ :[:digit:]]{11} [._[:alnum:]-]+ postfix-(msa|mx)/smtpd\[[[:digit:]]+\]: warning: hostname [._[:alnum:]-]+ does not resolve to address [[:xdigit:].:]{3,39}(: Name or service not known)?$ ^\w{3} [ :[:digit:]]{11} [._[:alnum:]-]+ postfix-mx/smtpd\[[[:digit:]]+\]: warning: Connection concurrency limit exceeded: [0-9]+ from [._[:alnum:]-]+\[[[:xdigit:].:]{3,39}\] for service smtpd$ -^\w{3} [ :[:digit:]]{11} [._[:alnum:]-]+ postfix-mx/smtpd\[[[:digit:]]+\]: NOQUEUE: reject: RCPT from [._[:alnum:]-]+\[[[:xdigit:].:]{3,39}\]: 5[[:digit:]]{2} 5(\.[[:digit:]]){2} <[^>]+>: Helo command rejected: need fully-qualified hostname;( from=<[^>]*> to=<[^>]+>)? proto=E?SMTP( helo=<[^>]+>)? +^\w{3} [ :[:digit:]]{11} [._[:alnum:]-]+ postfix-mx/smtpd\[[[:digit:]]+\]: NOQUEUE: reject: RCPT from [._[:alnum:]-]+\[[[:xdigit:].:]{3,39}\]: 5[[:digit:]]{2} 5(\.[[:digit:]]){2} <[^>]+>: Helo command rejected: need fully-qualified hostname;( from=<[^>]*> to=<[^>]+>)? proto=E?SMTP( helo=<[^>]+>)?$ +^\w{3} [ :[:digit:]]{11} [._[:alnum:]-]+ postfix-mx/smtpd\[[[:digit:]]+\]: NOQUEUE: reject: RCPT from [._[:alnum:]-]+\[[[:xdigit:].:]{3,39}\]: 4[[:digit:]]{2} 4(\.[[:digit:]]){2} <[^>]+>: Sender address rejected: Domain not found;( from=<[^>]*> to=<[^>]+>)? proto=E?SMTP( helo=<[^>]+>)?$ +^\w{3} [ :[:digit:]]{11} [._[:alnum:]-]+ postfix-mx/smtpd\[[[:digit:]]+\]: NOQUEUE: reject: RCPT from [._[:alnum:]-]+\[[[:xdigit:].:]{3,39}\]: 5[[:digit:]]{2} 5(\.[[:digit:]]){2} Service unavailable; (Unverified Client host|Sender address) \[\S+\] blocked using [._[:alnum:]-]+; https?://[^[:blank:];]+; from=<[^>]*> to=<[^>]+> proto=E?SMTP( helo=<[^>]+>)?$ +^\w{3} [ :[:digit:]]{11} [._[:alnum:]-]+ postfix-mx/smtpd\[[[:digit:]]+\]: NOQUEUE: reject: RCPT from [._[:alnum:]-]+\[([[:xdigit:].:]{3,39})\]: 4[[:digit:]]{2} 4(\.[[:digit:]]){2} Client host rejected: cannot find your hostname, \[\1\]; from=<[^>]*> to=<[^>]+> proto=E?SMTP( helo=<[^>]+>)?$ ^\w{3} [ :[:digit:]]{11} [._[:alnum:]-]+ postfix-(msa|mx)/smtpd\[[[:digit:]]+\]: timeout after [-[:upper:]]+( \([[:digit:]]+ bytes\))? from [^[:space:]]+$ ^\w{3} [ :[:digit:]]{11} [._[:alnum:]-]+ postfix-((msa|mx)/smtpd|out/smtp)\[[[:digit:]]+\]: warning: (tls_text_name: [-._[:alnum:]]+\[[[:xdigit:].:]{3,39}\]: )?peer certificate has no (subject CN|issuer Organization)$ ^\w{3} [ :[:digit:]]{11} [._[:alnum:]-]+ postfix-msa/smtpd\[[[:digit:]]+\]: (NOQUEUE|[[:xdigit:]]+): reject: [[:upper:]]+ from [^[:space:]]+: 450( 4\.1\.2)? <[^>]*>: Recipient address rejected: Domain not found;( from=<[^>]*> to=<[^>]+>)? proto=E?SMTP( helo=<[^[:space:]]+>)?$ -- cgit v1.2.3