Canary Workshop

Whatever is worth doing at all is worth doing well

Debian下完整邮件服务器的安装、配置

几个月时间断断续续折腾出来了一台完整的邮件服务器,在这里记录一下安装流程以备参考。

真的很麻烦!真的很麻烦!真的很麻烦!
左转第三方邮件,右转iRedMail

套件组成主体:

  • Postfix - SMTP服务器
  • Dovecot - IMAP/POP3服务器
  • MariaDB - 数据库
  • SpamAssassin - 反垃圾邮件
  • ClamAV - 杀毒工具
  • RoundCube - Web端程序
  • nginx和PHP - Web环境
  • OpenDKIM - DKIM工具

本文使用全新安装的Debian 9 x64操作。

本文参考了中、英、日文互联网上的大量教程、博文、问答、讨论,其中主体部分参考DigitalOcean文档中的教程。本文最终希望打造一台拥有基础收发功能、抗垃圾、抗病毒、易用的邮件服务器。本文部署的服务均使用TLS,认为SSL证书和私钥分别位于/etc/ssl/mail/mail.crt/etc/ssl/mail/mail.key。安装时为方便操作,直接使用root用户执行命令。

下面开始安装吧

0 准备数据库

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
apt install mysql-server
mysql_secure_installation
mysql -uroot -p
#以下进入MariaDB的提示符内操作
#创建数据库
CREATE DATABASE servermail;
#分配权限,这里使用的数据库账户为“mail”,密码为“Password”
GRANT SELECT ON servermail.* TO 'mail'@'127.0.0.1' IDENTIFIED BY 'Password';
FLUSH PRIVILEGES;
#切换进数据库,准备创建表
USE servermail;
#创建域名表
CREATE TABLE `virtual_domains` ( `id` INT NOT NULL AUTO_INCREMENT, `name` VARCHAR(50) NOT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
#创建用户表
CREATE TABLE `virtual_users` ( `id` INT NOT NULL AUTO_INCREMENT, `domain_id` INT NOT NULL, `password` VARCHAR(106) NOT NULL, `email` VARCHAR(120) NOT NULL, PRIMARY KEY (`id`), UNIQUE KEY `email` (`email`), FOREIGN KEY (domain_id) REFERENCES virtual_domains(id) ON DELETE CASCADE ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
#创建别名表
CREATE TABLE `virtual_aliases` ( `id` INT NOT NULL AUTO_INCREMENT, `domain_id` INT NOT NULL, `source` varchar(100) NOT NULL, `destination` varchar(100) NOT NULL, PRIMARY KEY (`id`), FOREIGN KEY (domain_id) REFERENCES virtual_domains(id) ON DELETE CASCADE ) ENGINE=InnoDB DEFAULT CHARSET=utf8;

接下来,准备输入数据。本例中:

  • 域名使用dynos01.com
  • 账户使用admin@dynos01.com,密码为123456
  • 创建一个别名,令test@dynos01.com成为admin@dynos01.com的别名
1
2
3
4
5
6
7
8
#加入域名
INSERT INTO `servermail`.`virtual_domains` (`id` ,`name`) VALUES ('1', 'dynos01.com');
#加入用户
INSERT INTO `servermail`.`virtual_users` (`id`, `domain_id`, `password` , `email`) VALUES ('1', '1', ENCRYPT('123456', CONCAT('$6$', SUBSTRING(SHA(RAND()), -16))), 'admin@dynos01.com');
#加入别名
INSERT INTO `servermail`.`virtual_aliases` (`id`, `domain_id`, `source`, `destination`) VALUES ('1', '1', 'test@dynos01.com', 'admin@dynos01.com');
#退出
exit

若以后需要增删改数据,可直接书写SQL查询来进行,也可自行编写一个工具来操作。

至此,数据库配置完毕。至于网页端RoundCube的数据库,因其为可选配件,故安装时再行配置。

1 安装、配置Postfix

Postfix是一个很常用的SMTP软件。这里就使用Postfix来提供SMTP支持。

1
apt install postfix postfix-mysql

这里安装程序会询问Postfix的安装配置及域名。选择Internet Site即可,如图:

image
image
image

接下来配置Postfix,请根据实际替换以下内容:
/etc/postfix/main.cf

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
smtpd_tls_cert_file=/etc/ssl/mail/mail.crt
smtpd_tls_key_file=/etc/ssl/mail/mail.key
smtpd_tls_auth_only = yes
smtpd_sasl_type = dovecot
smtpd_sasl_path = private/auth
smtpd_sasl_auth_enable = yes
smtpd_recipient_restrictions = permit_sasl_authenticated, permit_mynetworks, reject_unauth_destination
mydestination = localhost
myhostname = mail.dynos01.com
mydomain = dynos01.com
virtual_transport = lmtp:unix:private/dovecot-lmtp
virtual_mailbox_domains = mysql:/etc/postfix/mysql-virtual-mailbox-domains.cf
virtual_mailbox_maps = mysql:/etc/postfix/mysql-virtual-mailbox-maps.cf
virtual_alias_maps = mysql:/etc/postfix/mysql-virtual-alias-maps.cf
smtp_header_checks = regexp:/etc/postfix/smtp_header_checks

创建文件/etc/postfix/smtp_header_checks并填入以下内容:

1
2
/^Received: .*/ IGNORE
/^User-Agent: .*/ IGNORE

接下来,创建三个新的配置文件来设置数据库:
/etc/postfix/mysql-virtual-mailbox-domains.cf

1
2
3
4
5
user = mail
password = 123456
hosts = 127.0.0.1
dbname = servermail
query = SELECT 1 FROM virtual_domains WHERE name='%s'

etc/postfix/mysql-virtual-mailbox-maps.cf

1
2
3
4
5
user = mail
password = 123456
hosts = 127.0.0.1
dbname = servermail
query = SELECT 1 FROM virtual_users WHERE email='%s'

/etc/postfix/mysql-virtual-alias-maps.cf

1
2
3
4
5
user = mail
password = 123456
hosts = 127.0.0.1
dbname = servermail
query = SELECT destination FROM virtual_aliases WHERE source='%s'

保存后,执行systemctl reload postfix来加载配置。现在测试一下能否正确连接数据库:

1
2
3
4
5
6
postmap -q dynos01.com mysql:/etc/postfix/mysql-virtual-mailbox-domains.cf
#返回“1”为正确
postmap -q admin@dynos01.com mysql:/etc/postfix/mysql-virtual-mailbox-maps.cf
#返回“1”为正确
postmap -q test@dynos01.com mysql:/etc/postfix/mysql-virtual-alias-maps.cf
#返回“admin@dynos01.com”为正确

接下来启用SMTPSStartTLS
/etc/postfix/master.cf
取消submissionsmtps以及其各自下方所有参数(“-o”)的注释,然后修改为以下内容:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
submission inet n - y - - smtpd
-o syslog_name=postfix/submission
-o smtpd_tls_security_level=encrypt
-o smtpd_sasl_type=dovecot
-o smtpd_sasl_auth_enable=yes
-o smtpd_client_restrictions=permit_sasl_authenticated,reject
-o smtpd_sender_login_maps=pcre:/etc/postfix/sender
-o smtpd_sender_restrictions=reject_sender_login_mismatch
smtps inet n - y - - smtpd
-o syslog_name=postfix/smtps
-o smtpd_tls_wrappermode=yes
-o smtpd_sasl_auth_enable=yes
-o smtpd_reject_unlisted_recipient=no
-o smtpd_sender_login_maps=pcre:/etc/postfix/sender
-o smtpd_sender_restrictions=reject_sender_login_mismatch
-o smtpd_recipient_restrictions=
-o milter_macro_daemon_name=ORIGINATING

保存后再次systemctl reload postfix以加载配置。

2 安装、配置Dovecot

这里使用Dovecot来提供IMAP/POP3支持。

1
apt install dovecot-core dovecot-imapd dovecot-lmtpd dovecot-pop3d dovecot-mysql

编辑/etc/dovecot/dovecot.conf并加入如下行来启用协议支持:

1
protocols = imap lmtp pop3

接着编辑nano /etc/dovecot/conf.d/10-mail.conf并做如下修改:

1
2
3
4
5
6
7
8
9
#找到该行:
mail_location = mbox:~/mail:INBOX=/var/mail/%u
#改为:
mail_location = maildir:/var/mail/vhosts/%d/%n
#找到该行:
#mail_privileged_group =
#改为:
mail_privileged_group = mail

接着编辑/etc/dovecot/conf.d/10-auth.conf并做如下修改:

1
2
3
4
5
6
7
8
9
10
11
12
13
#反注释该行:
#disable_plaintext_auth = yes
#找到该行:
auth_mechanisms = plain
改为:
auth_mechanisms = plain login
#注释该行:
!include auth-system.conf.ext
#反注释该行:
#!include auth-sql.conf.ext

接着编辑/etc/dovecot/conf.d/auth-sql.conf.ext,删除所有内容,再加入如下内容:

1
2
3
4
5
6
7
8
passdb {
driver = sql
args = /etc/dovecot/dovecot-sql.conf.ext
}
userdb {
driver = static
args = uid=vmail gid=vmail home=/var/mail/vhosts/%d/%n
}

接着编辑/etc/dovecot/dovecot-sql.conf.ext并作如下修改:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#找到该行:
#driver =
#改为:
driver = mysql
#找到该行:
#connect =
#改为:
connect = host=127.0.0.1 dbname=servermail user=mail password=123456
#找到该行:
#default_pass_scheme = MD5
#改为:
default_pass_scheme = SHA512-CRYPT
#找到该行:
#password_query = \
#改为:
password_query = SELECT email as user, password FROM virtual_users WHERE email='%u';
#添加该行:
user_query = SELECT ('5000') as 'uid',('5000') as 'gid'

接着编辑/etc/dovecot/conf.d/10-master.conf并作如下修改:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
#反注释整个inet_listener imap {}和inet_listener imaps {}部分
#将service lmtp {}部分改为以下内容:
service lmtp {
unix_listener /var/spool/postfix/private/dovecot-lmtp {
mode = 0600
user = postfix
group = postfix
}
}
#将service auth {}部分改为以下内容:
service auth {
unix_listener /var/spool/postfix/private/auth {
mode = 0666
user = postfix
group = postfix
}
unix_listener auth-userdb {
mode = 0600
user = vmail
#group =
}
#unix_listener /var/spool/postfix/private/auth {
# mode = 0666
#}
user = dovecot
}
#在service auth-worker {}花括号中加入以下内容:
user = vmail

接着编辑/etc/dovecot/conf.d/10-ssl.conf并作如下设置:

1
2
3
ssl = required
ssl_cert = </etc/ssl/mail/mail.crt
ssl_key = </etc/ssl/mail.key

创建一个新用户(组)来存取邮件:

1
2
3
groupadd -g 5000 vmail
useradd -g vmail -u 5000 vmail -d /var/mail
chown -R vmail:vmail /var/mail

修改Dovecot目录权限:

1
2
chown -R vmail:dovecot /etc/dovecot
chmod -R o-rwx /etc/dovecot

执行systemctl reload dovecot来加载新配置。

3 安装、配置SpamAssassin

SpamAssassin是由阿帕奇基金会开发的开源垃圾邮件识别引擎。这里我们使用SpamAssassin来识别垃圾邮件,Dovecotsieve组件来分类。

1
apt install spamassassin spamc dovecot-sieve

编辑/etc/default/spamassassin

1
2
3
ENABLED=1
CRON=1
#并在OPTIONS=""中添加user=debian-spamd

编辑/etc/spamassassin/local.cf

1
2
3
4
5
6
7
8
9
10
#rewrite_header Subject ***** SPAM _SCORE_ *****
report_safe 0
required_score 5.0
use_bayes 1
use_bayes_rules 1
bayes_auto_learn 1
skip_rbl_checks 0
use_razor2 0
use_dcc 0
use_pyzor 0

编辑/etc/postfix/master.cf并作如下修改:

1
2
3
4
5
6
7
8
#找到该行:
smtp inet n - - - - smtpd
#在起下方添加:
-o content_filter=spamassassin
#在文件末尾添加:
spamassassin unix - n n - - pipe
user=debian-spamd argv=/usr/bin/spamc -f -e
/usr/sbin/sendmail -oi -f ${sender} ${recipient}

重启postfixspamassassin服务。

编辑/etc/dovecot/conf.d/90-plugin.conf并作如下修改:

1
2
#在plugin {}内加入如下内容:
sieve = /etc/dovecot/sieve/spam.sieve

之后

1
2
3
mkdir /etc/dovecot/sieve
cd /etc/dovecot/sieve
nano spam.sieve

输入如下内容:

1
2
3
4
require ["fileinto","mailbox"];
if header :contains "X-Spam-Flag" "YES" {
fileinto :create "Junk";
}

之后

1
2
sievec /etc/dovecot/sieve/spam.sieve
systemctl reload dovecot

4 配置DKIM

DKIM是一种反垃圾邮件的策略。在本地设置好DKIM可以提高邮件到达率。

1
apt install opendkim opendkim-tools

然后编辑/etc/opendkim.conf并在末尾追加以下内容:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
AutoRestart Yes
AutoRestartRate 10/1h
UMask 002
Syslog yes
SyslogSuccess Yes
LogWhy Yes
Canonicalization relaxed/simple
ExternalIgnoreList refile:/etc/opendkim/TrustedHosts
InternalHosts refile:/etc/opendkim/TrustedHosts
KeyTable refile:/etc/opendkim/KeyTable
SigningTable refile:/etc/opendkim/SigningTable
Mode sv
PidFile /var/run/opendkim/opendkim.pid
SignatureAlgorithm rsa-sha256
UserID opendkim:opendkim
Socket inet:12301@localhost

编辑/etc/default/opendkim并在末尾追加以下内容:

1
SOCKET="inet:12301@localhost"

编辑/etc/postfix/main.cf并在末尾追加以下内容:

1
2
3
4
milter_protocol = 6
milter_default_action = accept
smtpd_milters = inet:localhost:12301
non_smtpd_milters = inet:localhost:12301

接着设置OpenDKIM

1
2
mkdir -p /etc/opendkim/keys
nano /etc/opendkim/TrustedHosts

输入以下内容:

1
2
localhost
*.dynos01.com

编辑/etc/opendkim/KeyTable并输入以下内容:

1
mail._domainkey.dynos01 dynos01.com:mail:/etc/opendkim/keys/dynos01.com/mail.private

编辑/etc/opendkim/SigningTable并输入以下内容:

1
*@dynos01.com mail._domainkey.dynos01.com

之后:

1
2
3
4
5
6
cd /etc/opendkim/keys
mkdir dynos01.com
cd dynos01.com
opendkim-genkey -s mail -d dynos01.com
chown opendkim:opendkim mail.private
cat mail.txt

输出的内容即是DNS数据。至于如何添加,本文最下方有完整示例。

现在重启OpenDKIMPostfix服务。

5 安装、配置ClamAV

!!!ClamAV需要大量内存,2GB内存以下慎入!!!
ClamAV是开源杀毒软件,是目前事实上的邮件杀毒标准。下面安装ClamAV来提供防病毒功能:

1
2
3
apt install clamav-daemon clamav clamsmtp
chown -R clamav:clamav /var/spool/clamsmtp
chown -R clamav:clamav /var/run/clamsmtp

编辑/etc/clamsmtpd.conf

1
User: clamav

编辑/etc/postfix/main.cf并追加以下内容:

1
2
content_filter = scan:127.0.0.1:10026
receive_override_options = no_address_mappings

编辑/etc/postfix/master.cf并追加以下内容:

1
2
3
4
5
6
7
8
9
10
11
12
scan unix - - n - 16 smtp
-o smtp_send_xforward_command=yes
127.0.0.1:10025 inet n - n - 16 smtpd
-o content_filter=
-o receive_override_options=no_unknown_recipient_checks,no_header_body_checks
-o smtpd_helo_restrictions=
-o smtpd_client_restrictions=
-o smtpd_sender_restrictions=
-o smtpd_recipient_restrictions=permit_mynetworks,reject
-o mynetworks_style=host
-o smtpd_authorized_xforward_hosts=127.0.0.0/8

之后重启clamsmtpclamav-daemonpostfix三个服务。

6 安装、配置RoundCube

如果只打算使用邮件客户端,可以跳过本部分。

这一部分是常规的PHP应用安装,自行在MariaDB中创建数据库,然后下载安装源码即可。注意参考这里补全需要的PHP扩展。另外,RoundCube有大量优秀的皮肤和插件,按需安装即可。

7 一些杂记

全套下来,如果不安装ClamAV的话,最少大约需要256MB内存。若安装,至少需要1GB(且会大量使用交换空间),故推荐使用2GB及以上内存。

如果比较讨厌爆破扫描爆破,可以使用Fail2ban来封锁有关IP地址。使用Fail2ban自带的规则即可实现,不再赘述。不过注意修改/etc/dovecot/conf.d/10-logging.confDovecot的日志写入文件。

至于常见的mx2等备份MX,可以参考如下的Postfix配置:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
smtpd_banner = $myhostname ESMTP $mail_name (Debian/GNU)
biff = no
append_dot_mydomain = no
readme_directory = no
compatibility_level = 2
smtpd_tls_cert_file=/etc/ssl/mail/mail.crt
smtpd_tls_key_file=/etc/ssl/mail/mail.key
smtpd_use_tls=yes
smtpd_relay_restrictions = permit_mynetworks permit_sasl_authenticated defer_unauth_destination
myhostname = mx-b.dynos01.com
alias_maps = hash:/etc/aliases
alias_database = hash:/etc/aliases
myorigin = /etc/mailname
relayhost =
mynetworks = 127.0.0.0/8 [::ffff:127.0.0.0]/104 [::1]/128
mailbox_size_limit = 0
recipient_delimiter = +
inet_interfaces = all
inet_protocols = all
smtpd_recipient_restrictions = permit_sasl_authenticated, permit_mynetworks, reject_unauth_destination
relay_domains = dynos01.com, dyn.im
relay_recipient_maps =

另附上与邮件有关的完整的DNS记录表(截至2018年8月):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
dynos01.com. 300 IN MX 10 mx-a.dynos01.com.
dynos01.com. 300 IN MX 20 mx-b.dynos01.com.
dynos01.com. 300 IN MX 30 mx-c.dynos01.com.
dynos01.com. 300 IN TXT "v=spf1 mx mx:dynos01.com -all"
mx-a.dynos01.com. 300 IN A 130.255.76.196
mx-a.dynos01.com. 300 IN AAAA 2a02:e00:ffec:26d::1
mx-b.dynos01.com. 300 IN A 162.220.14.253
mx-b.dynos01.com. 300 IN AAAA 2607:fcd0:107:3ab::1
mx-c.dynos01.com. 300 IN A 108.61.181.39
mx-c.dynos01.com. 300 IN AAAA 2001:19f0:7001:a77::1
_dmarc.dynos01.com. 300 IN TXT "v=DMARC1; p=none"
mail.dynos01.com. 300 IN A 130.255.76.196
mail.dynos01.com. 300 IN AAAA 2a02:e00:ffec:26d::1
imap.dynos01.com. 300 IN A 130.255.76.196
imap.dynos01.com. 300 IN AAAA 2a02:e00:ffec:26d::1
pop.dynos01.com. 300 IN A 130.255.76.196
pop.dynos01.com. 300 IN AAAA 2a02:e00:ffec:26d::1
smtp.dynos01.com. 300 IN A 130.255.76.196
smtp.dynos01.com. 300 IN AAAA 2a02:e00:ffec:26d::1
mail._domainkey.dynos01.com. 300 IN TXT ( "v=DKIM1; h=sha256; k=rsa; " p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA3qvjdCBGppP7/OvRdPgkcSV2banFtwfuSoMj4TU9GZaLBm8/qZVDicfGR8kYmJxxZ/qS/9G/BLa6K6Kyc44Zm+f4D7lH1xYfJCilC63lwvzFvtA/qAkf74/VzVqMHv812rbwuFNaxudux0Y9EmwPTRhce/yCpx08wuvK+rh3wNZZ9pUpHXvNAXh4KT0TEdzl8VylO+N7NsApn6
TS3vvFFyRFrOc0EwE3OB1EA6vyc6GdEV7SD2u5Dy3McMEVI/kuuBCjvS0/Yf8V9tPmm5azCilsr6fl+h8BIsryM0Ved2kf+6+/LJAk3eOqLfIasuzRHTVL92bpGM/+R7ugMjgctQIDAQAB )