Setup
The MTA handles the transmission of email to and from the system, while the MDA handles delivery of email on that system.
In this configuration, postfix is the MTA and dovecot is the MDA.
See Email Docker and Documentation.
Ports
Email Ports
Note
POP3 and non TLS/SSL connections should be considered compromised by default. If enabling remote MUA connections, Use TLS/SSL IMAP.
Port 465
is a defacto standard for client email submissions before the
creation of RFC 2476. It is safe to disable this unless you are forcing
connections to this port. Read more about ports here.
Port
Protocol
Type
Purpose
25
TCP
PUBLIC
MTA SMTP Mail Relay (Receive mailnfrom other mail servers)
110
TCP
DISABLE
POP3 plaintext client
143
TCP
DISABLE
StartTLS IMAP client
465
TCP
DISABLE
SSL MUA email submission (defacto standard)
587
TCP
EXPOSED
TLS MUA email submission (RFC 2476)
993
TCP
EXPOSED
TLS/SSL IMAP client
995
TCP
DISABLE
TLS/SSL POP3 client
Updated: None
Files
Email Files
Location
Purpose
/var/mail
Email storage location
/var/mail-state
Mail server state
/var/log/mail
Mail logs
/tmp/docker-mailserver
Mail configuration files
/etc/letsencrypt
Let’s Encrypt certificates to use for SSL
Updated: None
Note
Documentation assumes the following DNS preferences:
mail.{DOMAIN}
resolves to the mail server IP, MX records (e.g. mail.example.com).Mail accounts are
{USER}@{DOMAIN}
.
Docker Creation
Warning
Create the compose file but do not start the docker container. Pre-existing configurations can be started normally.
Initial configuration must be done before launching the conatiner so that all auto-generated setup for domains, accounts, aliases and SPF/DKIM/SSL are generated and configured correctly.
See Configuration.
Delete configuration files to reset if started without configuration.
Mail containers should be placed on a separate isolated network as the is exposed to the world.
See Docker options for detailed docker environment setup. Explicit options set even if default to remain consistent if any changes do occur.
Dovecot manages SASL authentication, so
SASLAUTHD
is disabled.
mail:
image: tvial/docker-mailserver:latest
hostname: mail
domainname: {DOMAIN}
stop_grace_period: 1m
restart: unless-stopped
ports:
- "25:25"
- "587:587"
- "993:993"
environment:
- DEFAULT_RELAY_HOST=''
- DMS_DEBUG=0
- DOVECOT_MAILBOX_FORMAT=maildir
- ENABLE_CLAMAV=1
- ENABLE_ELK_FORWARDER=0
- ENABLE_FAIL2BAN=0
- ENABLE_FETCHMAIL=0
- ENABLE_LDAP=''
- ENABLE_MANAGESIEVE=1
- ENABLE_POP3=0
- ENABLE_POSTFIX_VIRTUAL_TRANSPORT=''
- ENABLE_POSTGREY=1
- ENABLE_SASLAUTHD=0
- ENABLE_SPAMASSASSIN=1
- ENABLE_SRS=1
- LOGROTATE_INTERVAL=weekly
- LOGWATCH_INTERVAL=weekly
- ONE_DIR=1
- PERMIT_DOCKER=host
- PFLOGSUMM_TRIGGER=logrotate
- POSTFIX_DAGENT=''
- POSTFIX_MAILBOX_SIZE_LIMIT=0
- POSTFIX_MESSAGE_SIZE_LIMIT=10480000
- POSTGREY_AUTO_WHITELIST_CLIENTS=0
- POSTGREY_DELAY=300
- POSTGREY_MAX_AGE=35
- POSTGREY_TEXT=Delayed by postgrey
- POSTMASTER_ADDRESS=postmaster@{DOMAIN}
- POSTSCREEN_ACTION=enforce
- RELAY_HOST=''
- SA_KILL=6.31
- SA_SPAM_SUBJECT=***SPAM***
- SA_TAG2=6.31
- SA_TAG=3.0
- SASL_PASSWD=''
- SASLAUTHD_MECH_OPTIONS=''
- SASLAUTHD_MECHANISMS=''
- SMTP_ONLY=''
- SPOOF_PROTECTION=1
- SRS_EXCLUDE_DOMAINS=''
- SRS_SENDER_CLASSES=envelope_sender,header_sender
- SSL_TYPE=letsencrypt
- TLS_LEVEL=modern
- TZ=America/Los_Angeles
- VIRUSMAILS_DELETE_DELAY=7
volumes:
- /data/mail:/var/mail
- /data/mail/server/state:/var/mail-state
- /var/log/mail:/var/log/mail
- /data/mail/server/config:/tmp/docker-mailserver
- /data/letsencrypt:/etc/letsencrypt:ro
- /etc/localtime:/etc/localtime:ro
Note
NET_ADMIN
capability is required if fail2ban
is run within the
container. Alternatively, the mail logs can be mounted externally and
fail2ban
run in an isolated container.
See fail2ban for System.
SYS_PTRACE
capability is required for debugging as well as detecting
a hung procress; disabling might allow container processes to die and not
restart.
The security vulnerability with SYS_PTRACE is patched for all 4.8+ Linux kernels.
fail2ban Setup
Enable fail2ban for MTA and MDA services.
Use fail2ban for System for the base fail2ban service setup.
f2b-system:
volumes:
- /var/log/mail:/var/log/mail:ro
Custom filters generated by extracting them from the mail docker image and adding as additional rules for the separate fail2ban container.
[INCLUDES]
before = common.conf
[Definition]
_daemon = (auth|dovecot(-auth)?|auth-worker)
failregex = ^%(__prefix_line)s(pam_unix(\(dovecot:auth\))?:)?\s+authentication failure; logname=\S* uid=\S* euid=\S* tty=dovecot ruser=\S* rhost=<HOST>(\s+user=\S*)?\s*$
^%(__prefix_line)s(pop3|imap)-login: (Info: )?(Aborted login|Disconnected)(: Inactivity)? \(((no auth attempts|auth failed, \d+ attempts)( in \d+ secs)?|tried to use (disabled|disallowed) \S+ auth)\):( user=<\S*>,)?( method=\S+,)? rip=<HOST>, lip=(\d{1,3}\.){3}\d{1,3}(, session=<\w+>)?(, TLS( handshaking)?(: Disconnected)?)?\s*$
^%(__prefix_line)s(Info|dovecot: auth\(default\)): pam\(\S+,<HOST>\): pam_authenticate\(\) failed: (User not known to the underlying authentication module: \d+ Time\(s\)|Authentication failure \(password mismatch\?\))\s*$
^\s.*passwd-file\(\S*,<HOST>\): unknown user.*$
(?: pop3-login|imap-login): .*(?:Authentication failure|Aborted login \(auth failed|Aborted login \(tried to use disabled|Disconnected \(auth failed).*rip=(<HOST>),.*
## ^%(__prefix_line)spasswd-file\(\S*,<HOST>\): unknown user.*$
ignoreregex =
Note
Dovecot filter needs to be adjusted to use the <HOST>
as the default
filter will fail by default.
Patched, pending release: https://github.com/tomav/docker-mailserver/pull/1388
# Fail2Ban filter for selected Postfix SMTP rejections
#
#
[INCLUDES]
# Read common prefixes. If any customizations available -- read them from
# common.local
before = common.conf
[Definition]
_daemon = postfix(-\w+)?/(?:submission/|smtps/)?smtp[ds]
failregex = ^%(__prefix_line)sNOQUEUE: reject: RCPT from \S+\[<HOST>\]: 554 5\.7\.1 .*$
^%(__prefix_line)sNOQUEUE: reject: RCPT from \S+\[<HOST>\]: 450 4\.7\.1 Client host rejected: cannot find your hostname, (\[\S*\]); from=<\S*> to=<\S+> proto=ESMTP helo=<\S*>$
^%(__prefix_line)sNOQUEUE: reject: RCPT from \S+\[<HOST>\]: 450 4\.7\.1 : Helo command rejected: Host not found; from=<> to=<> proto=ESMTP helo= *$
^%(__prefix_line)sNOQUEUE: reject: EHLO from \S+\[<HOST>\]: 504 5\.5\.2 <\S+>: Helo command rejected: need fully-qualified hostname;
^%(__prefix_line)sNOQUEUE: reject: VRFY from \S+\[<HOST>\]: 550 5\.1\.1 .*$
^%(__prefix_line)sNOQUEUE: reject: RCPT from \S+\[<HOST>\]: 450 4\.1\.8 <\S*>: Sender address rejected: Domain not found; from=<\S*> to=<\S+> proto=ESMTP helo=<\S*>$
^%(__prefix_line)simproper command pipelining after \S+ from [^[]*\[<HOST>\]:?$
ignoreregex =
[Init]
journalmatch = _SYSTEMD_UNIT=postfix.service
# Author: Cyril Jaquier
# Fail2Ban filter for Postfix's RBL based Blocked hosts
#
#
[INCLUDES]
# Read common prefixes. If any customizations available -- read them from
# common.local
before = common.conf
[Definition]
_daemon = postfix(-\w+)?/smtpd
failregex = ^%(__prefix_line)sNOQUEUE: reject: RCPT from \S+\[<HOST>\]: 454 4\.7\.1 Service unavailable; Client host \[\S+\] blocked using .* from=<\S*> to=<\S+> proto=ESMTP helo=<\S*>$
ignoreregex =
# Author: Lee Clemens
# 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
ignoreregex =
[dovecot]
enabled = true
port = pop3,pop3s,imap,imaps,imap2,imap3,smtp,ssmtp
filter = dovecot
logpath = /var/log/mail/mail.log
bantime = -1
findtime = 86400
maxretry = 3
[mail-dovecot]
enabled = true
port = pop3,pop3s,imap,imaps,imap2,imap3,smtp,ssmtp
filter = mail-dovecot
logpath = /var/log/mail/mail.log
bantime = -1
findtime = 86400
maxretry = 3
[postfix]
enabled = true
port = pop3,pop3s,imap,imaps,imap2,imap3,smtp,ssmtp
filter = postfix
logpath = /var/log/mail/mail.log
bantime = -1
findtime = 86400
maxretry = 3
[mail-postfix]
enabled = true
port = pop3,pop3s,imap,imaps,imap2,imap3,smtp,ssmtp
filter = mail-postfix
logpath = /var/log/mail/mail.log
bantime = -1
findtime = 86400
maxretry = 3
[mail-postfix-rbl]
enabled = true
port = pop3,pop3s,imap,imaps,imap2,imap3,smtp,ssmtp
filter = mail-postfix-rbl
logpath = /var/log/mail/mail.log
bantime = -1
findtime = 86400
maxretry = 3
[mail-postfix-sasl]
enabled = true
port = pop3,pop3s,imap,imaps,imap2,imap3,smtp,ssmtp
filter = mail-postfix-sasl
logpath = /var/log/mail/mail.log
bantime = -1
findtime = 86400
maxretry = 3
Restart
f2b-system
.