Initial commit

This commit is contained in:
phil 2023-03-20 20:01:04 +01:00
commit 11b84aa872
40 changed files with 995 additions and 0 deletions

9
README.md Normal file
View file

@ -0,0 +1,9 @@
Postfix
=======
Use this role to setup a Postfix mail server. It comes with the following additions:
- [Mail-TLS-Helper](https://github.com/systemli/mail-tls-helper)
- [MTA-STS-Resolver](https://github.com/Snawoot/postfix-mta-sts-resolver)
- Fail2ban
- optional: [OnionMX](https://github.com/ehloonion/onionmx)
- optional: Unbound

12
defaults/main.yml Normal file
View file

@ -0,0 +1,12 @@
---
mail_sasl_log: mail-sasl.log
postfix_conf_dir: /etc/postfix/conf.d
postfix_daemon_dir: /usr/lib/postfix/sbin
postfix_default_db_type: cdb
tls_helper_domains_file: tls_domains
tls_helper_postfix_dir: /var/lib/postfix/tls-helper
postfix_dhparam_file: /etc/ssl/private/dhparam.pem
fail2ban_jail_dir: /etc/fail2ban/jail.d
fail2ban_filter_dir: /etc/fail2ban/filter.d

View file

@ -0,0 +1,7 @@
[sasl]
enabled = true
findtime = 3600
bantime = 3600
port = submission
filter = postfix-sasl
logpath = /var/log/mail-sasl.log

View file

@ -0,0 +1,21 @@
# Fail2Ban filter for postfix authentication failures
#
[INCLUDES]
before = common.conf
[Definition]
_daemon = postfix(-\w+)?/(?:submission/|smtps/)?smtp[ds]
failregex = ^%(__prefix_line)swarning: [-._\w]+\[<HOST>\]: SASL ((?i)LOGIN|PLAIN|(?:CRAM|DIGEST)-MD5) authentication failed(: [ A-Za-z0-9+/:]*={0,2})?\s*$
ignoreregex = authentication failed: Connection lost to authentication server$
[Init]
journalmatch = _SYSTEMD_UNIT=postfix.service
# Author: Yaroslav Halchenko

View file

@ -0,0 +1,4 @@
Logrotat runs with hardening features (/lib/systemd/system/logrotate.service)
which prevents write access to /etc.
You will find the tls_domains file at /var/lib.

View file

@ -0,0 +1,9 @@
# Managed by Ansible
check process mta-sts-daemon
matching "/usr/bin/python3 /usr/bin/mta-sts-daemon"
group mailserver
start program = "/usr/sbin/service postfix-mta-sts-resolver start"
stop program = "/usr/sbin/service postfix-mta-sts-resolver stop"
if 2 restarts within 3 cycles then timeout
if failed host 127.0.0.1 port 8461 for 3 cycles then restart

7
files/monit/postfix Normal file
View file

@ -0,0 +1,7 @@
# Managed by Ansible
check process postfix with pidfile /var/spool/postfix/pid/master.pid
group mailserver
start program = "/usr/sbin/service postfix@- start"
stop program = "/usr/sbin/service postfix@- stop"
if failed port 25 protocol smtp with timeout 15 seconds for 3 cycles then restart

View file

@ -0,0 +1,10 @@
# Manages by Ansible
# bogus networks
0.0.0.0/8 550 Mail server in broadcast network
1.0.0.0/8 550 Mail server in IANA reserved network
#10.0.0.0/8 550 No route to your RFC 1918 network
127.0.0.0/8 550 Mail server in loopback network
224.0.0.0/4 550 Mail server in class D multicast network
#172.16.0.0/12 550 No route to your RFC 1918 network
192.168.0.0/16 550 No route to your RFC 1918 network

View file

@ -0,0 +1,10 @@
# Managed by Ansible
/^Content-(Disposition|Type).*name\s*=\s*"?([^;]*(\.|=2E)(
ade|adp|asp|bas|bat|chm|cmd|com|cpl|dll|exe|
hlp|ht[at]|
inf|ins|isp|js|jse?|lnk|md[betw]|ms[cipt]|nws|
\{[[:xdigit:]]{8}(?:-[[:xdigit:]]{4}){3}-[[:xdigit:]]{12}\}|
ops|pcd|pif|prf|reg|sc[frt]|sh[bsm]|swf|
vb[esx]?|vxd|ws[cfh]))(\?=)?"?\s*(;|$)/x
REJECT Attachment name "$2" may not end with ".$4"

View file

@ -0,0 +1,7 @@
# Managed by Ansible
# Remove external mail processing headers
/^X-Spam-.*: .*$/ IGNORE
/^X-Amavis-.*: .*$/ IGNORE
/^X-Virus-.*: .*$/ IGNORE
/^X-Rc-(Spam|Virus)+: .*$/ IGNORE

6
files/smtp_tor Normal file
View file

@ -0,0 +1,6 @@
#!/bin/sh
# This script will be called by Postfix master.cf.
# It runs a service for OnionMX.
exec /usr/bin/torsocks -i /usr/lib/postfix/sbin/smtp "$@"

25
handlers/main.yml Normal file
View file

@ -0,0 +1,25 @@
---
- name: restart rsyslog
ansible.builtin.service:
name: rsyslog
state: restarted
- name: reload fail2ban
ansible.builtin.service:
name: fail2ban
state: reloaded
- name: reload postfix
ansible.builtin.service:
name: postfix
state: reloaded
- name: restart postfix
ansible.builtin.service:
name: postfix
state: restarted
- name: reload monit
ansible.builtin.service:
name: monit
state: reloaded

10
meta/main.yml Normal file
View file

@ -0,0 +1,10 @@
galaxy_info:
author: Sense.Lab e.V. administrators
description: Role to setup Postfix
company: Sense.Lab e.V.
license: GPLv3
min_ansible_version: "2.9"
platforms:
- name: Debian
versions:
- "bullseye"

26
tasks/fail2ban.yml Normal file
View file

@ -0,0 +1,26 @@
---
- name: "Fail2ban | Copy jaiil file"
ansible.builtin.copy:
src: files/fail2ban/postfix-sasl.conf
dest: "{{ fail2ban_jail_dir }}/postfix-sasl.conf"
mode: "0644"
notify: reload fail2ban
- name: "fail2ban | Copy SASL filter"
ansible.builtin.copy:
src: files/fail2ban/postfix-sasl.local
dest: "{{ fail2ban_filter_dir }}/postfix-sasl.local"
mode: "0644"
notify: reload fail2ban
- name: "Fail2ban | Setup SASL logging"
ansible.builtin.lineinfile:
dest: /etc/rsyslog.d/postfix.conf
line: ':msg, contains, \"SASL\" /var/log/{{ mail_sasl_log }}'
notify: restart rsyslog
- name: "Fail2ban | Setup logrotate"
ansible.builtin.template:
src: mail-sasl.j2
dest: /etc/logrotate.d/mail-sasl
mode: "0644"

10
tasks/hostname.yml Normal file
View file

@ -0,0 +1,10 @@
---
- name: "Hostname | Set hostname"
ansible.builtin.hostname:
name: "{{ inventory_hostname }}"
use: systemd
- name: "Hostname | Set hostname in /etc/hosts"
ansible.builtin.lineinfile:
path: /etc/hosts
line: '127.0.0.1 {{ ansible_hostname }}'

29
tasks/main.yml Normal file
View file

@ -0,0 +1,29 @@
---
- name: Packages
ansible.builtin.import_tasks: packages.yml
tags: packages
- name: Postfix
ansible.builtin.import_tasks: postfix.yml
tags: postfix
- name: OnionMX
ansible.builtin.import_tasks: onionmx.yml
tags: onionmx
when: postfix_onionmx is defined and postfix_onionmx
- name: Fail2ban
ansible.builtin.import_tasks: fail2ban.yml
tags: fail2ban
- name: TLS-helper
ansible.builtin.import_tasks: tls-helper.yml
tags: tls-helper
- name: Hostname
ansible.builtin.import_tasks: hostname.yml
tags: hostname
- name: Monitoring
ansible.builtin.import_tasks: monitoring.yml
tags: monitoring

16
tasks/monitoring.yml Normal file
View file

@ -0,0 +1,16 @@
---
- name: "Monitoring | Enable Monit monitoring for Postfix"
ansible.builtin.copy:
src: monit/postix
dest: /etc/monit/conf-enabled/postfix
mode: "0644"
notify: reload monit
when: "'monit' in ansible_facts.packages"
- name: "Monitoring | Enable Monit Monitoring for MTA-STS"
ansible.builtin.copy:
src: monit/mta-sts-daemon
dest: /etc/monit/conf-enabled/mta-sts-daemon
mode: "0644"
notify: reload monit
when: "'monit' in ansible_facts.packages"

22
tasks/onionmx.yml Normal file
View file

@ -0,0 +1,22 @@
---
- name: "OnionMX | Install torsocks"
ansible.builtin.apt:
pkg: torsocks
cache_valid_time: 3600
- name: "OnionMX | Copy script"
ansible.builtin.copy:
src: smtp_tor
dest: "{{ postfix_daemon_dir }}"
mode: "0755"
- name: "OnionMX | Copy transport table"
ansible.builtin.template:
src: postfix/conf.d/transport_tor.j2
dest: "{{ postfix_conf_dir }}/transport_tor"
mode: "0644"
- name: "OnionMX | Run postmap"
ansible.builtin.command:
cmd: "postmap {{ postfix_default_db_type }}:transport_tor"
chdir: "{{ postfix_conf_dir }}"

23
tasks/packages.yml Normal file
View file

@ -0,0 +1,23 @@
---
- name: "Packages | Get installed packages"
ansible.builtin.package_facts:
manager: apt
- name: "Packages | Install packages"
ansible.builtin.apt:
pkg:
- fail2ban
- libsasl2-modules
- pflogsumm
- pfqueue
- postfix
- postfix-cdb
- postfix-pcre
- postfix-mta-sts-resolver
cache_valid_time: 3600
- name: "Packages | Install Unbound"
ansible.builtin.apt:
pkg:
- unbound
when: unbound_install is defined and unbound_install

77
tasks/postfix.yml Normal file
View file

@ -0,0 +1,77 @@
---
- name: "Postfix | Copy main.cf"
ansible.builtin.template:
src: postfix/main.cf.j2
dest: /etc/postfix/main.cf
mode: "0644"
notify: reload postfix
- name: "Postfix | Copy master.cf"
ansible.builtin.template:
src: postfix/master.cf
dest: /etc/postfix/master.cf
mode: "0644"
notify: restart postfix
- name: "Postfix | Create configuration directory"
ansible.builtin.file:
path: "{{ postfix_conf_dir }}"
state: directory
mode: "0755"
- name: "Postfix | Copy lookup tables"
ansible.builtin.copy:
src: "postfix/conf.d/{{ item }}"
dest: "{{ postfix_conf_dir }}/{{ item }}"
mode: "0644"
loop:
- bogus_mx
- header_checks
- header_checks_inbound
- name: "Postfix | Copy lookup tables from templates"
ansible.builtin.template:
src: "postfix/conf.d/{{ item }}.j2"
dest: "{{ postfix_conf_dir }}/{{ item }}"
mode: "0644"
loop:
- bad_smtp_auth_users
- client_checks
- destination_limit
- header_add
- header_treatment
- permit_sasl_login_mismatch
- postscreen_access
- relay_by_sender
- relay_checks
- sender_checks
- transport_global_exceptions
- transport_relay
notify: reload postfix
- name: "Postfix | Run postmap"
ansible.builtin.command: "postmap {{ item.table | default('cdb') }}:{{ item.file }}"
args:
chdir: "{{ postfix_conf_dir }}"
changed_when: false
notify: reload postfix
loop:
- file: bad_smtp_auth_users
- file: client_checks
- file: destination_limit
- file: permit_sasl_login_mismatch
- file: relay_checks
- file: sender_checks
- file: transport_relay
- name: "Postfix | Create dhparam file"
community.crypto.openssl_dhparam:
path: "{{ postfix_dhparam_file }}"
size: 4096
- name: "Postfix | Setup cron job for pflogsum"
ansible.builtin.cron:
name: "Ansible: Daily pflogsum statistics"
job: /usr/sbin/pflogsumm --detail 8 --problems-first --no-no-msg-size --reject-detail 12 /var/log/mail.log.1 | mail -s "{{ postfix_pflogsum_mail_subject }} ({{ inventory_hostname }})" {{ postfix_pflogsum_recipient }}
hour: "06"
minute: "24"

65
tasks/tls-helper.yml Normal file
View file

@ -0,0 +1,65 @@
---
- name: "TLS-helper | Clone repository"
ansible.builtin.git:
repo: "https://github.com/systemli/mail-tls-helper.git"
dest: "/opt/mail-tls-helper"
version: main
- name: "TLS-helper | Copy Readme"
ansible.builtin.copy:
src: mail-tls-helper/readme.txt
dest: /opt/mail-tls-helper/
mode: "0644"
- name: "TLS-help | Copy allowlist"
ansible.builtin.template:
src: postfix/allowlist.txt
dest: /opt/mail-tls-helper/allowlist.txt
mode: "0644"
- name: "TLS-helper | Create directory"
ansible.builtin.file:
path: "{{ tls_helper_postfix_dir }}"
state: directory
owner: postfix
group: postfix
mode: "0755"
- name: "TLS-helper | Create transport map"
ansible.builtin.file:
path: "{{ tls_helper_postfix_dir }}/{{ tls_helper_domains_file }}"
state: touch
owner: postfix
group: postfix
mode: "0644"
- name: "TLS-helper | Run postmap"
ansible.builtin.command:
cmd: "postmap {{ postfix_default_db_type }}:{{ tls_helper_domains_file }}"
chdir: "{{ tls_helper_postfix_dir }}"
- name: "TLS-helper | Link files"
ansible.builtin.file:
path: "{{ postfix_conf_dir }}/{{ item }}"
src: "{{ tls_helper_postfix_dir }}/{{ item }}"
state: link
loop:
- "{{ tls_helper_domains_file }}"
- "{{ tls_helper_domains_file }}.{{ postfix_default_db_type }}"
- name: "TLS-helper | Remove default logrotate configuration for mail logging"
ansible.builtin.lineinfile:
path: /etc/logrotate.d/rsyslog
line: "{{ item }}"
state: absent
loop:
- /var/log/mail.info
- /var/log/mail.warn
- /var/log/mail.err
- /var/log/mail.log
- name: "TLS-helper | Create new logrotate configuration"
ansible.builtin.template:
src: logrotate.conf
dest: /etc/logrotate.d/maillog
mode: "0644"

17
templates/logrotate.conf Normal file
View file

@ -0,0 +1,17 @@
/var/log/mail.log
/var/log/mail.info
/var/log/mail.warn
/var/log/mail.err
{
rotate 1
daily
missingok
notifempty
compress
delaycompress
sharedscripts
postrotate
/usr/lib/rsyslog/rsyslog-rotate
python3 /opt/mail-tls-helper/mail-tls-helper.py -s /opt/mail-tls-helper/domains.sqlite -p /var/lib/postfix/tls-helper/tls_domains -t cdb --allowlist /opt/mail-tls-helper/allowlist.txt -d {{ postfix_tls_helper_domain }} -r {{ postfix_tls_helper_recipient }} -f {{ postfix_tls_helper_sender }}
endscript
}

10
templates/mail-sasl.j2 Normal file
View file

@ -0,0 +1,10 @@
### {{ ansible_managed }}
/var/log/{{ mail_sasl_log }} {
rotate 2
daily
missingok
notifempty
delaycompress
compress
}

View file

@ -0,0 +1,5 @@
# {{ ansible_managed }}
{% for domain in postfix_tls_helper_allowlist %}
{{ domain }}
{% endfor %}

View file

@ -0,0 +1,11 @@
### {{ ansible_managed }}
# Use this file to block SMTP-Auth access for users.
# Example:
# username REJECT
{% if postfix_bad_smtp_auth_users is defined %}
{% for user in postfix_bad_smtp_auth_users %}
{{ "%-30s %s" | format(user, "REJECT") }}
{% endfor %}
{% endif %}

View file

@ -0,0 +1,10 @@
### {{ ansible_managed }}
### With this file you can allow or disallow clients to connect to the SMTP server.
{% if postfix_client_checks is defined %}
{% for client in postfix_client_checks %}
{{ client.comment }}
{{ "%-30s %s" | format(client.name, client.state) }}
{% endfor %}
{% endif %}

View file

@ -0,0 +1,7 @@
### {{ ansible_managed }}
{% if postfix_dlimit_domains is defined %}
{% for domain in postfix_dlimit_domains %}
{{ "%-50s %s" | format(domain, "dlimit:") }}
{% endfor %}
{% endif %}

View file

@ -0,0 +1,7 @@
### {{ ansible_managed }}
{% if postfix_header_add is defined %}
{% for header in postfix_header_add %}
{{ "%-50s %s" | format(header.destination, header.header) }}
{% endfor %}
{% endif %}

View file

@ -0,0 +1,21 @@
### {{ ansible_managed }}
# Remove sensible headers
/^Mail-System-Version:/ IGNORE
/^Mailer:/ IGNORE
/^Originating-Client:/ IGNORE
/^User-Agent:/ IGNORE
/^X-Enigmail-Version:/ IGNORE
/^X-Mailer:/ IGNORE
/^X-MimeOLE:/ IGNORE
/^X-Newsreader:/ IGNORE
/^X-Originating-IP:/ IGNORE
/^X-Sender:/ IGNORE
/^\s*(Received: from)[^\n]*(.*)/ REPLACE $1 [127.0.0.1] (localhost [127.0.0.1])
{% if postfix_header_treatment is defined %}
{% for header in postfix_header_treatment %}
{{ header }}
{% endfor %}
{% endif %}

View file

@ -0,0 +1,13 @@
### {{ ansible_managed }}
{% if postfix_default_helo_checks is defined %}
{% for check in postfix_default_helo_checks %}
{{ "%-30s %s" | format(check.client, check.state) }}
{% endfor %}
{% endif %}
{% if postfix_helo_checks is defined %}
{% for check in postfix_default_helo_checks %}
{{ "%-30s %s" | format(check.client, check.state) }}
{% endfor %}
{% endif %}

View file

@ -0,0 +1,8 @@
### {{ ansible_managed }}
### Enable sender spoofing for selected accounts
{% if postfix_permit_login_mismatch is defined %}
{% for user in postfix_permit_login_mismatch %}
{{ "%-50s %s" | format(user, "permit_login_mismatch") }}
{% endfor %}
{% endif %}

View file

@ -0,0 +1,19 @@
### {{ ansible_managed }}
{% if postfix_default_postscreen_access is defined %}
{% for source in postfix_default_postscreen_access %}
{% if source.comment is defined %}
# {{ source.comment }}
{% endif %}
{{ "%-40s %s" | format(source.source, source.state) }}
{% endfor %}
{% endif %}
{% if postfix_postscreen_access is defined %}
{% for source in postfix_postscreen_access %}
{% if source.comment is defined %}
# {{ source.comment }}
{% endif %}
{{ "%-40s %s" | format(source.source, source.state) }}
{% endfor %}
{% endif %}

View file

@ -0,0 +1,9 @@
# {{ ansible_managed }}
# http://www.postfix.org/postconf.5.html#sender_dependent_relayhost_maps
{% if postfix_relay_by_sender is defined %}
{% for map in postfix_relay_by_sender %}
{{ map }}
{% endfor %}
{% endif %}

View file

@ -0,0 +1 @@
### {{ ansible_managed }}

View file

@ -0,0 +1,20 @@
### {{ ansible_managed }}
{% if postfix_sender_checks is defined %}
{% for sender in postfix_sender_checks %}
{% if sender.comment is defined %}
# {{ sender.comment }}
{% endif %}
{{ "%-50s %s" | format(sender.client, sender.state) }}
{% endfor %}
{% endif %}
# Blocked Domains
{% for domain in postfix_blocked_domains %}
{{ "%-50s %s" | format(domain, "REJECT No spammers") }}
{% endfor %}
# Blocked Sender
{% for sender in postfix_blocked_senders %}
{{ "%-50s %s" | format(sender, "REJECT No spammers") }}
{% endfor %}

View file

@ -0,0 +1,12 @@
### {{ ansible_managed }}
# Use this file for mail addresses that should be treated specially.
{% if postfix_transport_global_exceptions is defined %}
{% for address in postfix_transport_global_exceptions %}
{% if address.comment is defined %}
# {{ address.comment }}
{% endif %}
{{ "%-50s %s" | format(address.adress, address.state) }}
{% endfor %}
{% endif %}

View file

@ -0,0 +1,10 @@
### {{ ansible_managed }}
{% if postfix_transport_relay is defined %}
{% for transport in postfix_transport_relay %}
{% if transport.comment is defined %}
# {{ transport.comment }}
{% endif %}
{{ "%-50s %s" | format(transport.destination, transport.relay) }}
{% endfor %}
{% endif %}

View file

@ -0,0 +1,13 @@
### {{ ansible_managed }}
{% if postfix_default_transport_tor_domains is defined %}
{% for domain in postfix_default_transport_tor_domains %}
{{ "%-50s %s" | format(domain.name, domain.relay) }}
{% endfor %}
{% endif %}
{% if postfix_transport_tor_domains is defined %}
{% for domain in postfix_transport_tor_domains %}
{{ "%-50s %s" | format(domain.name, domain.relay) }}
{% endfor %}
{% endif %}

View file

@ -0,0 +1,307 @@
### {{ ansible_managed }}
smtpd_banner = {{ postfix_smtpd_banner }}
### Debug Logging
#debug_peer_list =
### Protocols and destinations
inet_interfaces = all
inet_protocols = ipv4
myhostname = $myorigin
myorigin = {{ postfix_myorigin }}
mydestination = {{ postfix_mydestination | join(', ') }}
mynetworks = {{ postfix_mynetworks | join(', ') }}
### TLS settings
tls_ssl_options = NO_COMPRESSION, NO_RENEGOTIATION
tls_preempt_cipherlist = no
tls_medium_cipherlist = ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-SHA
tls_high_cipherlist=EDH+CAMELLIA:EDH+aRSA:EECDH+aRSA+AESGCM:EECDH+aRSA+SHA256:EECDH:+CAMELLIA128:+AES128:+SSLv3:!aNULL:!eNULL:!LOW:!3DES:!MD5:!EXP:!PSK:!DSS:!RC4:!SEED:!IDEA:!ECDSA:kEDH:CAMELLIA128-SHA:AES128-SHA
### TLS settings for SMTP server
smtpd_tls_security_level = may
smtpd_tls_auth_only = yes
smtpd_tls_cert_file = {{ postfix_smtpd_tls_cert_file }}
smtpd_tls_key_file = {{ postfix_smtpd_tls_key_file }}
smtpd_tls_ciphers = medium
smtpd_tls_mandatory_ciphers = medium
smtpd_tls_exclude_ciphers = aNULL, eNULL, MD5, DES, 3DES, DES-CBC3-SHA, RC4-SHA, AES256-SHA, AES128-SHA, DHE-RSA-AES256-SHA
#Einige berechtigte Mailserver nutzen nur TLSv1
#smtpd_tls_mandatory_protocols = !TLSv1
#smtpd_tls_protocols = !TLSv1
smtpd_tls_session_cache_database = btree:${data_directory}/smtpd_scache
smtpd_tls_session_cache_timeout = 7200s
smtpd_tls_loglevel = 1
smtpd_tls_CAfile = /etc/ssl/certs/ca-certificates.crt
smtpd_tls_dh1024_param_file = {{ postfix_dhparam_file }}
smtpd_tls_eecdh_grade = strong
### TLS settings for SMTP client
smtp_tls_security_level = dane
smtp_dns_support_level = dnssec
smtp_tls_session_cache_database = btree:${data_directory}/smtp_scache
smtp_tls_session_cache_timeout = 7200s
#Some mailserver use only TLSv1. Hence we can't disable it.
#smtp_tls_protocols = !TLSv1
{% if postfix_smtp_tls_policy_maps is defined %}
smtp_tls_policy_maps =
{% for map in postfix_smtp_tls_policy_maps %}
{{ map.type }}:{{ map.path }}
{% endfor %}
{% endif %}
smtp_tls_ciphers = medium
smtp_tls_fingerprint_digest = sha1
smtp_tls_loglevel = 1
smtp_tls_CAfile = /etc/ssl/certs/ca-certificates.crt
smtp_pix_workarounds = disable_esmtp
### Domains and recipients
{% if postfix_virtual_mailbox_domains is defined %}
virtual_mailbox_domains =
{% for map in postfix_virtual_mailbox_domains %}
{{ map.type }}:{{ map.path }}
{% endfor %}
{% endif %}
{% if postfix_virtual_mailbox_maps is defined %}
# Check for existing recipients
virtual_mailbox_maps =
{% for map in postfix_virtual_mailbox_maps %}
{{ map.type }}:{{ map.path }}
{% endfor %}
{% endif %}
{% if postfix_virtual_alias_maps is defined %}
virtual_alias_maps =
{% for map in postfix_virtual_alias_maps %}
{{ map.type }}:{{ map.path}}
{% endfor %}
{% endif %}
{% if postfix_virtual_transport is defined %}
virtual_transport =
{% for map in postfix_virtual_transport %}
{{ map.type }}:{{ map.address }}
{% endfor %}
{% endif %}
{% if postfix_relay_domains is defined %}
# Relay mails without recipient check
relay_domains =
{% for map in postfix_relay_domains %}
{{ map.type}}:{{ map.path }}
{% endfor %}
{% endif %}
{% if postfix_sender_dependent_relayhost_maps is defined %}
sender_dependent_relayhost_maps =
{% for map in postfix_sender_dependent_relayhost_maps %}
{{ map.type }}:{{ map.path }}
{% endfor %}
{% endif %}
{% if postfix_transport_maps is defined %}
transport_maps =
{% for map in postfix_transport_maps %}
{{ map.type }}:{{ map.path }}
{% endfor %}
{% endif %}
{% if postfix_smtpd_sasl_type is defined %}
### SMTP Auth, server side
broken_sasl_auth_clients = yes
smtpd_sasl_type = {{ postfix_smtpd_sasl_type }}
smtpd_sasl_path = {{ postfix_smtpd_sasl_path }}
smtpd_sasl_auth_enable = no
{% if postfix_smtpd_sasl_exceptions_networks is defined %}
# Some clients demand SASL Auth if the server offers it
smtpd_sasl_exceptions_networks = {{ postfix_smtpd_sasl_exceptions_networks | join(', ') }}
{% endif %}
{% endif %}
{% if postfix_smtp_sasl_auth is defined and postfix_smtp_sasl_auth %}
### SMTP Auth client side
smtp_sasl_auth_enable = yes
smtp_sasl_auth_soft_bounce = no
smtp_sasl_password_maps = hash:/etc/postfix/sasl/sasl_passwd
smtp_sasl_security_options = noanonymous
{% endif %}
#### Postscreen
postscreen_access_list =
permit_mynetworks
cidr:/etc/postfix/conf.d/postscreen_access.cidr
postscreen_blacklist_action = drop
# Pregreeting
postscreen_greet_action = drop
# DNS block lists
postscreen_dnsbl_threshold = 2
postscreen_dnsbl_sites =
bl.spamcop.net*1
ix.dnsbl.manitu.net*2
zen.spamhaus.org*2
postscreen_dnsbl_action = drop
# Postfix runs restrictions with the following order
# - smtpd_client_restriction
# - smtpd_helo_restriction
# - smtpd_sender_restrition
# - smtpd_relay_restrictions
# - smtpd_recipient_restrictions
# - smtpd_data_restriction
# - smtpd_end_of_data_restriction
# - smtpd_etrn_restriction
smtpd_restriction_classes = permit_login_mismatch
smtpd_client_restrictions =
permit_mynetworks,
permit_sasl_authenticated,
check_client_access cdb:/etc/postfix/conf.d/client_checks,
reject_unknown_client_hostname,
permit
# Reject only after RCPT-TO
smtpd_delay_reject = yes
# Enforce helo to apply restrictions
smtpd_helo_required = yes
smtpd_helo_restrictions =
permit_mynetworks,
permit_sasl_authenticated,
check_helo_access pcre:/etc/postfix/conf.d/helo_checks,
reject_non_fqdn_helo_hostname,
reject_invalid_helo_hostname,
permit
smtpd_sender_restrictions =
permit_mynetworks,
check_sender_access cdb:/etc/postfix/conf.d/sender_checks,
reject_non_fqdn_sender,
reject_unknown_sender_domain,
check_sender_mx_access cidr:/etc/postfix/conf.d/bogus_mx,
#Uncomment the next two lines to block mails from other servers with our domain as MAIL FROM
#permit_sasl_authenticated,
#check_sender_access hash:/etc/postfix/conf.d/sender_checks_domain,
permit
# Restrictions for submission port
mua_sender_restrictions =
check_sasl_access cdb:/etc/postfix/conf.d/permit_sasl_login_mismatch,
permit_mynetworks,
check_sender_access cdb:/etc/postfix/conf.d/sender_checks,
reject_non_fqdn_sender,
reject_unknown_sender_domain,
reject_sender_login_mismatch,
permit_sasl_authenticated
permit_login_mismatch =
permit_mynetworks,
reject_non_fqdn_sender,
reject_unknown_sender_domain,
permit_sasl_authenticated
submission_bad_smtp_user_check =
check_sasl_access cdb:/etc/postfix/conf.d/bad_smtp_auth_users
smtpd_relay_restrictions =
permit_mynetworks,
permit_sasl_authenticated,
check_client_access cdb:/etc/postfix/conf.d/relay_checks,
reject_unauth_destination
smtpd_recipient_restrictions =
reject_unauth_pipelining,
reject_non_fqdn_recipient,
reject_unknown_recipient_domain,
permit_mynetworks,
permit_sasl_authenticated,
reject_unverified_recipient
# Configuration for reject_unverified_recipient
unverified_recipient_reject_reason = User unknown / Nutzer unbekannt
unverified_recipient_reject_code = 550
smtpd_data_restrictions =
reject_multi_recipient_bounce,
check_recipient_access pcre:/etc/postfix/conf.d/header_add,
### Connection limits
smtpd_client_connection_rate_limit = 100
smtpd_client_event_limit_exceptions = {{ postfix_smtpd_client_event_limit_exceptions | join(', ') }}
smtpd_client_message_rate_limit = 25
smtpd_client_new_tls_session_rate_limit = 100
smtpd_client_auth_rate_limit = 100
default_destination_rate_delay = 60s
default_destination_recipient_limit = 1
default_destination_concurrency_failed_cohort_limit = 10
header_checks = pcre:/etc/postfix/conf.d/header_checks
### Spam and DKIM
{% if postfix_smtpd_milters is defined %}
smtpd_milters =
{% for map in postfix_smtpd_milters %}
{{ map.type }}:{{ map.address }}
{% endfor %}
{% endif %}
{% if postfix_non_smtpd_milters is defined %}
non_smtpd_milters =
{% for map in postfix_non_smtpd_milters %}
{{ map.type }}:{{ map.address }}
{% endfor %}
{% endif %}
milter_default_action = accept
milter_connect_macros = i j {daemon_name} v {if_name} _
milter_mail_macros = i {auth_type} {auth_authen} {auth_author} {mail_addr} {mail_host} {mail_mailer} {client_addr} {client_name}
milter_rcpt_macros = i j _ {auth_type} {rcpt_addr} {rcpt_host} {rcpt_mailer}
milter_connect_timeout = 20s
# Prevent DKIM signatures (don't allow spam header to change the signature)
disable_mime_output_conversion = yes
### Misc
readme_directory = /usr/share/doc/postfix
html_directory = /usr/share/doc/postfix/html
disable_vrfy_command = yes
recipient_delimiter = +
# Postfix-default: alias_maps = hash:/etc/mail/aliases nis:mail.aliases
# Prevents delays caused by NIS queries
alias_maps =
# Error notifications
# http://www.postfix.org/postconf.5.html#notify_classes
notify_classes = data, delay, resource, software
minimal_backoff_time = 1000s
maximal_backoff_time = 4h
compatibility_level = 2
biff = no
append_dot_mydomain = no
# Uncomment the next line to generate "delayed mail" warnings
#delay_warning_time = 4h
# Add missing headers
always_add_missing_headers = yes
local_header_rewrite_clients = permit_mynetworks
mailbox_size_limit = 0
message_size_limit = {{ postfix_message_size_limit }}
### Destination limits
# Some mail server limit concurrent connections
# Solves: Maximum parallel connections for your IP-Address
dlimit_destination_concurrency_limit = 4
dlimit_destination_recipient_limit = 3
dlimit_destination_rate_delay = 5s
{% if postfix_proxy_read_maps is defined %}
### Proxy maps
proxy_read_maps =
{% for map in postfix_proxy_read_maps %}
{{ map }}
{% endfor %}
{% endif %}

View file

@ -0,0 +1,90 @@
### {{ ansible_managed }}
# ==========================================================================
# service type private unpriv chroot wakeup maxproc command + args
# (yes) (yes) (no) (never) (100)
# ==========================================================================
smtp inet n - y - 1 postscreen
smtpd pass - - y - 100 smtpd
-o cleanup_service_name=smtpd-in
dnsblog unix - - y - 0 dnsblog
tlsproxy unix - - y - 0 tlsproxy
{% if postfix_submission is defined and postfix_submission %}
smtps inet n - y - 100 smtpd
-o syslog_name=postfix/smtps
-o smtpd_tls_wrappermode=yes
-o smtpd_tls_cert_file={{ postfix_submission_smtpd_tls_cert_file }}
-o smtpd_tls_key_file={{ postfix_submission_smtpd_tls_key_file }}
-o smtpd_tls_dh1024_param_file={{ dhparam_file }}
-o smtpd_tls_mandatory_protocols=!TLSv1,!TLSv1.1
-o smtpd_tls_protocols=!TLSv1,!TLSv1.1
-o smtpd_client_restrictions=$submission_bad_smtp_user_check,permit_sasl_authenticated,reject
-o smtpd_sasl_auth_enable=yes
{% if postfix_smtpd_sender_login_maps is defined %}
-o smtpd_sender_login_maps={{ postfix_smtpd_sender_login_maps | join(', ') }}
{% endif %}
-o smtpd_sender_restrictions=$mua_sender_restrictions
-o cleanup_service_name=subclean
submission inet n - y - - smtpd
-o syslog_name=postfix/submission
-o smtpd_tls_security_level=encrypt
-o smtpd_tls_cert_file={{ postfix_submission_smtpd_tls_cert_file }}
-o smtpd_tls_key_file={{ postfix_submission_smtpd_tls_key_file }}
-o smtpd_tls_dh1024_param_file={{ dhparam_file }}
-o smtpd_client_restrictions=$submission_bad_smtp_user_check,permit_sasl_authenticated,reject
-o smtpd_sasl_auth_enable=yes
{% if postfix_smtpd_sender_login_maps is defined %}
-o smtpd_sender_login_maps={{ postfix_smtpd_sender_login_maps | join(', ') }}
{% endif %}
-o smtpd_sender_restrictions=$mua_sender_restrictions
-o cleanup_service_name=subclean
{% if postfix_submission_alternative_port is defined %}
{{ postfix_submission_alternative_port }} inet n - y - - smtpd
-o syslog_name=postfix/submission-local
-o smtpd_tls_security_level=none
-o smtpd_client_restrictions=permit_mynetworks,reject
-o smtpd_sasl_auth_enable=no
-o cleanup_service_name=subclean
{% endif %}
{% endif %}
dlimit unix - - n - - smtp
-o syslog_name=postfix-dlimit
pickup unix n - y 60 1 pickup
cleanup unix n - y - 0 cleanup
qmgr unix n - n 300 1 qmgr
tlsmgr unix - - y 1000? 1 tlsmgr
rewrite unix - - y - - trivial-rewrite
bounce unix - - y - 0 bounce
defer unix - - y - 0 bounce
trace unix - - y - 0 bounce
verify unix - - y - 1 verify
flush unix n - y 1000? 0 flush
proxymap unix - - n - - proxymap
proxywrite unix - - n - 1 proxymap
smtp unix - - y - - smtp
smtptor unix - - n - - smtp_tor
-o smtp_dns_support_level=disabled
-o smtp_tls_security_level=none
-o smtp_tls_policy_maps=
relay unix - - y - - smtp
-o syslog_name=postfix/$service_name
# -o smtp_helo_timeout=5 -o smtp_connect_timeout=5
showq unix n - y - - showq
error unix - - y - - error
retry unix - - y - - error
discard unix - - y - - discard
local unix - n n - - local
virtual unix - n n - - virtual
lmtp unix - - y - - lmtp
anvil unix - - y - 1 anvil
scache unix - - y - 1 scache
postlog unix-dgram n - n - 1 postlogd
# Outbound: Remove sensible headers
subclean unix n - y - 0 cleanup
-o header_checks=regexp:/etc/postfix/conf.d/header_treatment
# Inbound: Remove some headers
smtpd-in unix n - y - 0 cleanup
-o syslog_name=postfix/smtpd-in
-o header_checks=pcre:/etc/postfix/conf.d/header_checks_inbound