Quickly build Maddy email service based on Docker
Docker build
Maddy is an ALL-IN-ONE mail system developed in GO language. Its main function is to send and receive mail through SMTP. Through IMAP, the client can access it. It also supports DKIM, SPF, DMARC, DANE, MTA-STS and other mail related security and anti-spam protocols.
In layman's terms, it is very convenient to deploy, takes up less resources, and is very suitable for personal use of email servers.
Project address: maddy/maddy.conf at master foxcpp/maddy (github.com)
premise:
- Have a server with a public IP and a domain name
- The server opens the following ports: 143,25,465,587,993
Reference: Common mail ports
example.com
The domain name is used as a demonstration below , and it is actually replaced with a real domain name.
1. Apply for an SSL certificate
Apply for a certificate from https://sslforfree.com , download and getmx1.example.com
certificate.crt
private.key
certificate.crt
Rename and to , private.key
respectively (the names specified by default in the configuration file)fullchain.pem
privkey.pem
2. Create a docker persistent directory and import configuration files
Download the official default configuration file from maddy.conf and modify its contents:
(hostname) = mx1.example.com
(primary_domain) = example.com
Create a directory maddydata to store the data mapping in the container, and put the above certificate file and maddy.conf into
At this time, the directory structure of maddydata is as follows:
maddydata
├── certs
│ └── mx1.example.com
│ ├── fullchain.pem
│ └── privkey.pem
└── maddy.conf
3. Docker starts Maddy
docker run \
--name maddy \
-e MADDY_HOSTNAME=mx1.example.com \
-e MADDY_DOMAIN=example.com \
-v /maddydata/certs:/etc/maddy/certs/ \
-v /maddydata:/data \
-p 25:25 \
-p 143:143 \
-p 587:587 \
-p 993:993 \
-d foxcpp/maddy:latest
If the docker service fails to start, docker logs maddy
check the log to find the reason
4. DNS settings of the cloud server
For a more detailed explanation, please refer to the official document Installation & initial configuration - maddy
Note that
example.com
it should be changed to your own domain name
# A 记录
example.com. A 10.2.3.4
# MX 记录
example.com. MX 10 mx1.example.com.
# MX 域解析
mx1.example.org. A 10.2.3.4
# SPF
example.com. TXT "v=spf1 mx ~all"
example.com. TXT "v=spf1 mx ~all"
# _dmarc
_dmarc.example.com. TXT "v=DMARC1; p=quarantine; ruf=mailto:[email protected]"
# _mta-sts. _smtp.tls
_mta-sts.example.com. TXT "v=STSv1; id=1"
_smtp._tls.example.com. TXT "v=TLSRPTv1;rua=mailto:[email protected]"
# 设置的值项目运行后自动生成,cat maddydata/dkim_keys/example.com_default.dns
default._domainkey.example.com. TXT "v=DKIM1; k=ed25519; p=xxxxxxxxxxxx"
If there is an IPV6 address, it can also be configured:
example.com. AAAA 2001:beef::1 # IPV6 有就配置
mx1.example.org. AAAA 2001:beef::1 # IPV6 有就配置
For detailed analysis of each configuration, please refer to the following part.
Maddy Command Line Operations
Enter the maddy container:
docker exec -it maddy sh
Maddy uses virtual users, so it does not need to create system users like postfix and dovecot. It requires a login account and an IMAP local storage account to be created. (The login account is the verification information for SMTP and IMAP login)
# 创建一个 [email protected] 的登录账户
$ maddyctl creds create [email protected]
# 查看登录账户列表
$ maddyctl creds list
# 创建一个 [email protected] 邮件储存账户
$ maddyctl imap-acct create [email protected]
# 查看刚存储账户列表
$ maddyctl imap-acct list
# 可以看到账户下的邮件分类
$ maddyctl imap-mboxes list [email protected]
INBOX [\HasNoChildren]
Sent [\Sent \HasNoChildren]
Trash [\Trash \HasNoChildren]
Junk [\Junk \HasNoChildren]
Drafts [\Drafts \HasNoChildren]
Archive [\Archive \HasNoChildren]
# 可以查看当前账户对应分类接收到的邮件,一般收件在 INBOX 中
$maddyctl imap-msgs list [email protected] INBOX
Test whether the build is successful
Log in to the previous web mailbox (for example, 163), and [email protected]
send
Check to see if you received the email:
$ maddyctl imap-msgs list [email protected] INBOX
UID 1: <[email protected]> - =?utf-8?B?dGVzdEBoYWhhY29kZS5jbg==?=
[\Recent], 2023-03-22 09:54:47 +0000 UTC
Basic knowledge of domain name resolution configuration
No matter what software is used in the email system, domain name resolution related to mail cannot be bypassed. As long as you are engaged in mail, you need to configure the following domain name resolution:
- MX record: Domain Name System base record, pointing to the mail server
- SPF records: Specify which servers can use your domain name to send mail
- DKIM records: prevent content tampering of sent emails
- DMARC record: When SPF and DKIM verification fails, specify the receiver's processing policy and report to the specified mailbox
- PTR record: that is, IP anti-analysis, and reverse domain name search based on IP, which needs to be done by the supplier
MX records
When sending and receiving emails, the MX record specifies its own mail server address, and the priority can be set. Generally, more than 2 mx records are recommended ()
域名 类型 值 优先级
example.com mx mx1.example.com 10
Set up a record corresponding to the MX subdomain name:
mx1.example.com A 10.2.3.4
After setting, use the dig command to verify:
dig mx example.com
PTR record
Mapping domain names to IP addresses is forward resolution, and mapping from IP addresses to domain names is reverse resolution. On the public network, reverse resolution cannot be provided by DNS, because the management authority of IP addresses belongs to the operator, so it is necessary to apply to the operator. Add reverse resolution, the operator points the IP address to the domain name through the PTR (Pointer Record) record. The mail server IP does not make PTR records, and there is a high probability that the mail will be regarded as spam after sending.
After contacting the supplier and adding it, you can use the dig command to verify:
dig -x mx1.example.com
SPF record
The full name of SPF is the sender policy framework , and its main function is to bind the sending mail server and the sending domain name to prevent forged senders. Use the TXT record in the SPF record to specify the server that is allowed to send mail. When the other party receives the mail, the system will verify the sending domain name and read the IP in the SPF record, and take further action after verifying whether it is consistent.
Take the Google SPF record as an example:
# dig txt gmail.com
gmail.com. 300 IN TXT "v=spf1 redirect=_spf.google.com"
# dig txt _spf.google.com
_spf.google.com. 300 IN TXT "v=spf1 include:_netblocks.google.com include:_netblocks2.google.com include:_netblocks3.google.com ~all"
# dig txt _netblocks.google.com
_netblocks.google.com. 300 IN TXT "v=spf1 ip4:35.190.247.0/24 ip4:64.233.160.0/19 ip4:66.102.0.0/20 ip4:66.249.80.0/20 ip4:72.14.192.0/18 ip4:74.125.0.0/16 ip4:108.177.8.0/21 ip4:173.194.0.0/16 ip4:209.85.128.0/17 ip4:216.58.192.0/19 ip4:216.239.32.0/19 ~all"
The SPF record v=spf1
starts all
ends with , and keywords such as ip4/ip6/a/mx/include/redirect can be used in the middle to specify the ip range. The matching mechanism for SPF records combines qualifiers to tell the server what to do when matching records. Common qualifiers are:
+
pass, which is the default if no qualifier is explicitly specified.-
Hard deny, which directly rejects mail from unauthorized hosts.~
With soft reject, the message can be accepted or marked as spam.?
Neutral, regardless of whether the mail is accepted or not.
Personal email settings allow the server in the mx record to send letters, and finally set the SPF record as:
example.com txt "v=spf1 mx -all"
DKIM records
The main function of the DKIM record is to prevent the mail from being maliciously tampered with and ensure the integrity of the mail content. The method used is similar to SSL. The server generates a public-private key pair, and the private key signs each outgoing mail and inserts it in the mail header. DKIM signature (DKIM-Signature header), and the public key is stored in the domain name record. When the mail receiver receives the mail, it obtains the public key through DNS query, and uses the public key to decrypt the mail signature, thereby verifying the validity and integrity of the mail.
Docker will automatically generate the DKIM private key and the dns records to be added after running Maddy, the location is:
dockerdata/dkim_keys/example.com_default.dns
default._domainkey.example.com txt "v=DKIM1; k=rsa; p=MIIBIjANBgkqhkiG9w0......"
DMARC records
DMARC is based on the existing SPF and DKIM protocols, and declares the processing policy for emails that fail verification. When the mail receiver receives the mail, it first obtains the DMARC record through DNS, then performs SPF verification and DKIM verification on the mail source, processes the mail that fails verification according to the DMARC record, and feeds back the processing result to the sender.
_dmarc.nixops.me txt "v=DMARC1; p=quarantine; ruf=mailto:[email protected]"
p
: reject rejects the mail; none means no processing; quarantine marks it as spam.ruf
: Forged email detected, email address reported by recipient
MTA-STS and TLS reports
MTA-STS is the MTA Strict Transport Security Protocol, which is used to ensure that emails sent to us are transmitted securely through TLS to prevent man-in-the-middle attacks. After enabling MTA-STS, the sender's mail server will only send us mail if the following conditions are met:
- Authenticated with a valid certificate
- Encrypted using TLS 1.2 or higher
Of course, if the sender does not support MTA-STS, emails can still be sent (there may be man-in-the-middle attacks), mainly for compatibility.
Requirements to enable MTA-STS:
- Create a policy file and provide HTTPS access
- Set txt records through DNS to tell other mail service providers to support MTA-STS
The content of the policy file mta-sts.txt is:
version: STSv1
mode: enforce
mx: mx1.nixops.me
mx: mx2.nixops.me
max_age: 86400
Create a subdomain name and enable https, the final access path is:
https://mta-sts.nixops.me/.well-known/mta-sts.txt
Configure the TXT record for MTA-STS:
_mta-sts.nixops.me TXT "v=STSv1; id=20211031T010101;"
The general id is a timestamp.
DNSSEC, DNAME, CAA
With MTA-STS enabled, DANE can ensure that the TLS certificate is valid, and in fact plays the role of CA through DNS. DANE declares that a certificate is trustworthy through TLSA records. Since DANE is based on the DNS protocol, it may be hijacked. Therefore, DNSSEC needs to be enabled to ensure that it is not modified during transmission.
- Enabling DNSSEC requires the support of both the domain name registrar and the dns service provider. Choose to enable DNSSEC at the DNS service provider, and then fill in the provided DS records to the domain name registrar.
- Use TLSA certificate generation tool and TLS certificate in PEM format to generate TLSA record
- CAA records generated using CAA Record Helper
To secure TLS certificates:
- DNSSEC secures DNS records in transit
- DANE blocks improperly signed certificates on the client side
- CAA specifies which certificate authority is allowed to issue certificates for a domain name
In this step, in order to enhance security, it is possible to recommend enabling configurations.
reference
Reference article:
- Maddy Creates Personal Email Service - Reading Notes (nixops.me)
- Open Source Mail Server Maddy Deployment Tutorial (lwebapp.com)
Other reference links and useful tools: