今天来聊聊Linux邮件服务器的搭建,本以为电子邮件这种高度成熟的技术应该很容易部署,上手后才发现原来坑还真不少。本方案以主流的postfix + dovacot为基础,其中postfix用作smtp,dovecot用作pop3(或imap)。
-
工作模式
用postfix构建的邮件系统至少有两种工作模式,第一种是利用本地Linux账号进行邮件收发,比如本地系统有用户root或someone,那么就有root@example.com和someone@example.com两个email地址。 第二种相对复杂一些,为了管理的方便和系统安全,postfix的用户管理采用了虚拟用户方式,即postfix单独设立了许多用户,他们各自在系统中映射有独立的硬盘空间。但同时这些用户又跟本地Linux系统内固有的真实账号没有关联。本文所有讨论就是建立在这种模式下的,值得注意的是,这两种工作模式的部署方法差异极大,在参考网上教程的时候,首先要确认它是建立在哪个模式下的,否则容易张冠李戴,出现很多令人头疼的问题。 -
运行流程
对于电子邮件,我们有可能存在的一个误区是,将smtp和pop3按照字面的意思去理解,即smtp只管发件,pop3则只负责收件。其实并不完全是这样。下面是一封电子邮件在互联网上的投递流程:
- 发件人:me@qq.com 收件人:you@gmail.com
me@qq.com 用邮件客户端(比如outlook)写了一封邮件给you@gmail.com,点下发送按钮后,邮件首先会发送到smtp.qq.com - smtp.qq.com 检索到这封邮件的收件人域名是gmail.com,于是通过互联网(WAN)将邮件发送到smtp.gmail.com
- smtp.gmail.com确认收下邮件后,将它转存到邮件服务器的硬盘中待收。
通过观察以上流程,你会发现smtp服务器其实身兼了 “收、发” 两个功能。 对于smtp.qq.com而言,是发送。 而从smtp.gmail.com的角度来看,则是接收。那么,咱们平时经常说起的 “收件服务器pop3” 又是怎么回事呢,整个流程似乎看不到它的身影?
pop3(或imap服务器,与之性质相同)更多的是起一个中转作用,它将存储在邮件服务器硬盘中的邮件转移回邮件客户端(user agent),它只负责从邮件服务器到邮件客户端这段路径,而邮件在广域网上的收发则是smtp要做的事,与pop3没有关系。
pop3与imap的区别是,pop3将邮件拉回本地后,即与服务器脱钩了。imap则更先进一些,它能做到实时将你在邮件客户端的操作反馈回邮件服务器,比如:删除邮件,标记已读等,服务器上的邮件也会做相应的动作。所以无论从浏览器登录邮箱或者客户端软件登录邮箱,看到的邮件以及状态都是一致的。
pop3-smtp-imap-difference-00.jpg
基础原理就这么点,下面开始进入实战环节。
一、 准备工作
前面说过,本文以虚拟邮件用户为基础,创建虚拟用户有很多方法,其中最容易也最易于扩展的方式莫过于采用数据库来管理邮件客户。比如说以后如果需要扩展Web Mail功能,就比较容易与现有系统无缝衔接。
本文选用Centos下最常见的MariaDB作为数据库,它与MySQL是完全兼容的,关于MariaDB的部署不在本文讨论之内,网上有很多教程,也非常简单。
首先将我的运行环境做一个说明:
OS : Centos 8.2
DB : MariaDB 10.3.17
Postfix 3.3.1
Dovecot 2.3.8
编辑器:nano
注意:
- 文中所有出现example.com的地方,需要换成你自己的域名。
- 文中凡出现nano开头的地方表达的意思就是编辑这个文件。
准备工作部分我们要做三件事:
- 建立数据库
- 修改DNS设置
- 获取域名证书
一步一步来,我们首先来创建数据库(默认你已经装好了MySQL或MariaDB):
准备步骤1:创建数据库
- 建库
mysql -u root -p 密码
进入mysql,然后执行:
create database servermail;
GRANT SELECT ON servermail.* TO 'usermail'@'127.0.0.1' IDENTIFIED BY 'mailpassword';
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;
- 生成一些初始数据
创建域名:
INSERT INTO `servermail`.`virtual_domains`
(`id` ,`name`)
VALUES
('1', 'example.com'),
('2', 'mail.example.com');
生成两个初始email账号:
其中,dmarck-reports@example.com是将来设置DKIM需要用到的,这是后话先别管它,创建了再说:
INSERT INTO `servermail`.`virtual_users`
(`id`, `domain_id`, `password` , `email`)
VALUES
('1', '1', ENCRYPT('密码', CONCAT('$6$', SUBSTRING(SHA(RAND()), -16))), 'webmaster@example.com'),
('2', '1', ENCRYPT('密码', CONCAT('$6$', SUBSTRING(SHA(RAND()), -16))), 'dmarck-reports@example.com');
生成一个别名:
INSERT INTO `servermail`.`virtual_aliases`
(`id`, `domain_id`, `source`, `destination`)
VALUES
('1', '1', 'boss@example.com', 'webmaster@example.com');
据库的基本操作完毕。
准备步骤2:修改DNS服务器
这需要登录你的域名管理界面,做几个简单的操作:
-
添加一个A记录,如图:
image.png -
添加一个MX记录,如图:
image.png
每个域名提供商的操作界面有可能不太一样,但都大同小异的。
准备步骤3:申请证书
接下来我们需要为邮件服务器获取域名证书,抛开安全性不谈,纯粹从装X的角度而言,这玩意就如同https一样,这年头你的网站还穿着http出来见人就真的有点丢人了,因此证书几乎是必备的。
域名证书有很多获取方式,有收费的也有免费的,国内有一家通过网页申请的,可参见我写的另一篇博文:https://www.jianshu.com/p/b4b5ca1d88d6
今天我们采用另一个方法,利用Letsencrypt在线生成,这个方案的好处是不用等待,证书立等可取,而且流程相对也比较简单。因为证书必须要对应一个真实存在的网站,所以我们还必须先装装样子,安装一个nginx,还好Letsencrypt对网站的实际内容没什么要求,nginx默认的初始页面也是可以的。
-
首先安装nginx
dnf -y install nginx
装好之后到浏览器输入你的域名,如果出现nginx欢迎页面,说明安装成功。 -
然后安装certbot
dnf -y install certbot python3-certbot-nginx
-
生成证书
certbot certonly -a nginx --agree-tos --staple-ocsp --email webmaster@example.com -d mail.example.com
如果没有问题,系统将回显如下:
- Congratulations! Your certificate and chain have been saved at:
/etc/letsencrypt/live/mail.example.com/fullchain.pem
Your key file has been saved at:
/etc/letsencrypt/live/mail.example.com/privkey.pem
Your cert will expire on 2021-02-27.
这里面包括了公私钥的存放地址以及有效期之类的信息。
至此,准备工作全部完成了,下面进入我们的核心部署环节!
二、核心内容:Postfix篇
首先我们需要安装postfix,在centos下这很简单,只需要一条命令:
dnf -y install postfix postfix-mysql
设置自启动:
systemctl start postfix
systemctl enable postfix
安装完毕后,开始对postfix进行设置,其中关键的配置文件有两个:main.cf和master.cf。
1. nano /etc/postfix/main.cf
这是一个超复杂的配置文件,不过大多数都是注释。限于篇幅我就不把整个文件贴出来了,你可以将源文件完全清空,然后将以下内容原封不动地复制进去,保存即可。注意所有出现example.com的地方,需要换成你自己的域名(后面的所有配置文件都是如此,接下来我就不再强调了)
mydomain = example.com
myorigin = mail.example.com
myhostname = mail.example.com
mydestination = \$mydomain
inet_interfaces = all
message_size_limit=52428800
mailbox_size_limit=0
smtpd_tls_cert_file=/etc/letsencrypt/live/mail.example.com/fullchain.pem
smtpd_tls_key_file=/etc/letsencrypt/live/mail.example.com/privkey.pem
smtpd_use_tls=yes
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
smtpd_banner = $myhostname ESMTP \$mail_name (Ubuntu)
biff = no
append_dot_mydomain = no
readme_directory = no
alias_maps = hash:/etc/aliases
alias_database = hash:/etc/aliases
relayhost =
mynetworks = 127.0.0.0/8 [::ffff:127.0.0.0]/104 [::1]/128
mailbox_size_limit = 0
recipient_delimiter = +
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
话说整个main.cf有相当多的设置项目,真正钻进去研究透彻需要花费大量时间,对于上述设置我只谈几个我已经看明白的:
mydomain = example.com
设置域名是example.com
myorigin = example.com
myorigin参数指定默认域名,该默认域名将附加到没有@domain部分的发件人和收件人地址。 需要将其值更改为example.com,因此邮件服务器上的发件人将具有@example.com地址。
myhostname = mail.example.com
与其他SMTP服务器通信时,Postfix使用此主机名来标识自己。 但是,操作系统主机名可能会更改,因此,最好直接在配置文件中设置。
mydestination = \$mydomain
mydestination参数指定服务器将其视为自身最终目的地的域列表。这个听起来有点拗口,说白了就是别人给您发信,哪些信你是接受的。比如12345@qq.com给您发一封信,收件人是webmaster@example.com,当你的smtp服务器接收到这封信的时候表示接受,对应的规则就是$mydomain。注意:此处如果设错了,有可能出现一个问题:你可以给别人发信,但是别人给你发的信你会收不到。
smtpd_tls_cert_file=/etc/letsencrypt/live/mail.example.com/fullchain.pem
smtpd_tls_key_file=/etc/letsencrypt/live/mail.example.com/privkey.pem
这两个是刚才我们生成的证书。
message_size_limit=52428800
mailbox_size_limit=0
这两个设置比较实用,是指附件最大允许容量和邮箱的总容量,这里我们把最大附件设为50MB,邮箱总容量则不设限制(0)
virtual_transport = lmtp:unix:private/dovecot-lmtp
这是一条核心设置,表示通过lmtp (Local Mail Transfer Protocol)协议,将本地邮件传递到dovecot中,相当于告诉Postfix,将从广域网收到的邮件,最终传递到dovecot能控制的地方,以便我们用pop3或imap下载到邮件客户端。
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
这三行与数据库有关,表示邮箱的虚拟域,用户映射关系和别名映射关系,分别由哪三个SQL脚本做查询动作。
- 接下来我们就要创建这3个SQL脚本了,稍懂一点SQL语句的朋友一定也可以看出其中的关联,这里也不再展开讨论了:
nano /etc/postfix/mysql-virtual-mailbox-domains.cf
user = usermail
password = mailpassword
hosts = 127.0.0.1
dbname = servermail
query = SELECT 1 FROM virtual_domains WHERE name='%s'
nano /etc/postfix/mysql-virtual-mailbox-maps.cf
user = usermail
password = mailpassword
hosts = 127.0.0.1
dbname = servermail
query = SELECT 1 FROM virtual_users WHERE email='%s'
nano /etc/postfix/mysql-virtual-alias-maps.cf
user = usermail
password = mailpassword
hosts = 127.0.0.1
dbname = servermail
query = SELECT destination FROM virtual_aliases WHERE source='%s'
创建好之后,用systemctl restart postfix
重启一次postfix,然后测试一下刚才建立的三个脚本。
postmap -q example.com mysql:/etc/postfix/mysql-virtual-mailbox-domains.cf
正确的话,应该返回:1
postmap -q webmaster@example.com mysql:/etc/postfix/mysql-virtual-mailbox-maps.cf
正确的话,应该返回:1
postmap -q boss@example.com mysql:/etc/postfix/mysql-virtual-alias-maps.cf
正确的话,应该返回:webmaster@example.com
2. nano /etc/postfix/master.cf
这也是一个巨复杂的配置文件,不过你依然可以先把它彻底清空,然后原封不动把以下内容粘贴进去:
smtp inet n - n - - smtpd
submission inet n - - - - smtpd
-o syslog_name=postfix/submission
-o smtpd_tls_security_level=encrypt
-o smtpd_sasl_auth_enable=yes
-o smtpd_client_restrictions=permit_sasl_authenticated,reject
smtps inet n - y - - smtpd
-o syslog_name=postfix/smtps
-o smtpd_tls_wrappermode=yes
-o smtpd_sasl_auth_enable=yes
-o smtpd_relay_restrictions=permit_sasl_authenticated,reject
-o smtpd_recipient_restrictions=permit_mynetworks,permit_sasl_authenticated,reject
-o smtpd_sasl_type=dovecot
-o smtpd_sasl_path=private/auth
pickup unix n - n 60 1 pickup
cleanup unix n - n - 0 cleanup
qmgr unix n - n 300 1 qmgr
tlsmgr unix - - n 1000? 1 tlsmgr
rewrite unix - - n - - trivial-rewrite
bounce unix - - n - 0 bounce
defer unix - - n - 0 bounce
trace unix - - n - 0 bounce
verify unix - - n - 1 verify
flush unix n - n 1000? 0 flush
proxymap unix - - n - - proxymap
proxywrite unix - - n - 1 proxymap
smtp unix - - n - - smtp
relay unix - - n - - smtp
-o syslog_name=postfix/$service_name
showq unix n - n - - showq
error unix - - n - - error
retry unix - - n - - error
discard unix - - n - - discard
local unix - n n - - local
virtual unix - n n - - virtual
lmtp unix - - n - - lmtp
anvil unix - - n - 1 anvil
scache unix - - n - 1 scache
master.cf这个文件主要掌管着postfix的各种服务,
这个文件的与一般的配置文件不同,它是缩进敏感的。
每一个顶格的行,代表一种服务,比如:
submission inet n - - - - smtpd
smtps inet n - y - - smtpd
同时他们下面又有一些
-o syslog_name=postfix/submission
-o smtpd_tls_security_level=encrypt
以-o开头的行,前面多了两空格,表示该服务下的具体设置。这两个空格不能删除,否则会报错,这就是所谓的缩进敏感。
可以看到我们开启了smtp,smtps和submission这三个服务,分别对应端口25,465和587,功能分别是:传统smtp服务,加密的smtps服务,还有一个submission。这是一个与smtps类似的加密协议。smtps 和 submission从功能上而言极其雷同,关于这两个端口,历史上还有一些彼此争夺话语权的野史,感兴趣的可以自行搜索。题外话我们暂且不表,反正两个都开通就是了。
至此,Postfix的设置工作就完成了,你可以通过以下命令用它发一封最简单的邮件,看看能否收到?
echo "Hello world!" | sendmail 你的qq@qq.com
三、核心内容:Dovecot篇
1. 安装dovecot
dnf -y install dovecot dovecot-mysql
设置自启动:
systemctl start dovecot
systemctl enable dovecot
2. nano dovecot.conf
protocols = imap lmtp
listen = *, ::
mail_max_userip_connections = 50
!include conf.d/*.conf
!include_try local.conf
这其实也是一个很复杂的配置文件,但是注释去掉之后也没什么内容。
protocols = imap lmtp
表示支持的协议,这里我们只开通了imap和lmtp,如果你需要pop3的话,加上去即可。
注意:此处的lmtp必须打开,这是dovecot和postfix交流的通道。
listen = *, ::
表示监听所有地址,*是ipv4的表达方法,::则是ipv6的,如果你没有启用ipv6,直接listen = *也行
mail_max_userip_connections = 50
设置一个合理的数值,否则会报mail_max_userip_connections 错误。
!include conf.d/*.conf
!include_try local.conf
没有太大的作用,表示此处将包含conf.d文件夹下的所有配置文件。
3. nano /etc/dovecot/conf.d/10-mail.conf
mail_location = maildir:/var/mail/vhosts/%d/%n
mail_privileged_group = mail
这个文件的原始体积也很大,但删掉注释之后只有2行,它设置的是邮箱对应硬盘的具体位置,%d表示域名,%n表示用户名,比如在本文中,webmaster@example.com这个用户在硬盘中的物理位置在:
/var/mail/vhost/example.com/webmaster
4. 创建用户组和用户:
groupadd -g 5000 vmail
useradd -g vmail -u 5000 vmail -d /var/mail
创建一个用户组vmail并添加一个用户vmail,id为5000,
用户vmail隶属于用户组vmail。起始目录为 /var/mail
5. 创建域名目录:
mkdir -p /var/mail/vhosts/example.com
6. 修改/var/mail和/etc/dovecot的拥有者:
chown -R vmail:vmail /var/mail
chown -R vmail:dovecot /etc/dovecot
chmod -R o-rwx /etc/dovecot
7. 查看权限
ls -ld /var/mail
如果显示:
lrwxrwxrwx. 1 vmail vmail 10 May 11 2019 /var/mail -> spool/mail
说明权限设置成功,请注意:这一步非常重要,如果该目录持有者不是vmail的话,dovecot在收到邮件后无法保存,将会报错。
8. nano /etc/dovecot/conf.d/10-auth.conf
disable_plaintext_auth = yes
auth_mechanisms = plain login
!include auth-sql.conf.ext
disable_plaintext_auth = yes
表示登录密码必须加密,否则不通过,我们这个方案是全盘TLS加密的,因此此处把他打开,不允许明文密码。
auth_mechanisms = plain login
授权机制,表示允许明文密码授权和login密码授权,为啥此处我们选择明文密码呢?此明文非彼明文,此处的明文是指在SSL/TLS加密通道中的明文,因为本身就已经加密过了,所以我们不需要担心密码泄露问题,而此处的login方式,是专门为outlook准备的。此处可以选择cram-md5,专门用于加密密码,但本身我们已经是加密通道了,因此没有必要画蛇添足。
!include auth-sql.conf.ext
此行表示启用MySQL授权
9. nano /etc/dovecot/conf.d/auth-sql.conf.ext
passdb {
driver = sql
args = /etc/dovecot/dovecot-sql.conf.ext
}
userdb {
driver = static
args = uid=vmail gid=vmail home=/var/mail/vhosts/%d/%n
}
当我们通过邮件客户端登录咱们的pop3(或imap)服务器准备取回邮件时,需要进行密码核对和用户名核对,那么dovecot是如何实现的呢?这个文件指定dovecot是如何获取用户密码和用户资料的,密码部分采用sql脚本方式。用户数据采用static (静态) 方式,通常,SQL数据库也可以做这件事,也可以通过它得到用户的UID,GID和主目录。但此处如果我们仅使用静态UID和GID,并且可以使用模板指定主目录,则可以改用静态方式,它会比SQL方式略快一些。
10. nano /etc/dovecot/dovecot-sql.conf.ext
driver = mysql
connect = host=127.0.0.1 dbname=servermail user=usermail password=mailpassword
default_pass_scheme = SHA512-CRYPT
password_query = SELECT email as user, password FROM virtual_users WHERE email='%u';
这个文件就是刚才我们说的SQL方式获取用户密码的脚本,很简单只有一句,相信大家都能看得懂。
说句题外话,dovecot只能识别user和password字段,如果你的初始数据库用的并不是这两个字段的话,必须是用as修饰符强制将它们转换成user和password。
11. nano /etc/dovecot/conf.d/10-master.conf
service lmtp {
unix_listener /var/spool/postfix/private/dovecot-lmtp {
mode = 0600
user = postfix
group = postfix
}
}
service auth {
unix_listener /var/spool/postfix/private/auth {
mode = 0666
user = postfix
group = postfix
}
unix_listener auth-userdb {
mode = 0600
user = vmail
}
user = dovecot
}
service auth-worker {
user = vmail
}
这个文件主要作用是为了打通dovecot和postfix的关联,授权postfix通过lmtp协议访问属于dovecot的地盘,访问权限是0600,表示有读写权限,但无执行权限。这个文件的源文件也比较庞杂,里面对多个协议都有设定,但是如果你全部把它们删了也没关系,等于采用默认设置,比如你把imap这一段删了,那么dovacot会将imap设为默认端口993。
11. nano /etc/dovecot/conf.d/10-ssl.conf
ssl = required
ssl_cert = </etc/letsencrypt/live/mail.example.com/fullchain.pem
ssl_key = </etc/letsencrypt/live/mail.example.com/privkey.pem
ssl_cipher_list = PROFILE=SYSTEM
这个配置文件主要是设置SSL,
ssl = required
表示强制使用SSL加密通道,从密码到邮件内容全部加密,这就是前面咱们在“授权机制”那个步骤允许使用的plain(明文密码)的原因了,因为整个通道都已经被加密了,明文密码走在加密通道里面也可以认为是安全的,后面两行指定了我们在准备步骤生成的证书存放位置。请注意,这两个文件与Postfix里的设置是完全一致的,也就是说Postfix和Dovecot采用的是同一个证书,不仅如此,实际上这本证书还可以用于nginx用于加密你的Web网站,开通https等。
12. nano /etc/dovecot/conf.d/15-mailboxes.conf
namespace inbox {
inbox = yes
mailbox Drafts {
auto = create
special_use = \Drafts
}
mailbox Junk {
auto = create
special_use = \Junk
}
mailbox Trash {
auto = create
special_use = \Trash
}
mailbox Sent {
auto = create
special_use = \Sent
}
mailbox "Sent Messages" {
auto = create
special_use = \Sent
}
}
这个文件是用来指定收件箱的命名空间的,auto = create
表示当这些邮箱都没有的时候,就自动创建它,这里指定的都是常规的,比如收件箱,已发送,垃圾箱,已删除等等,如果需要别的种类,请自行研究。
四、验证篇
终于快大功告成了!
现在我们需要验证一下服务器到底设置成功没有,首先重启一下postfix和dovecot:
stystemctl restart postfix dovecot
查看日志的方法是:
tail -f /var/log/maillog
请注意:postfix和dovecot的日志是合并在一起的,两者的变化都会记录在这个文件里。
1. 初级判断:
本文中,我们开通了smtp, smtps, imaps, lmtp, submission 这四个服务,分别对应端口:
25/tcp smtp :负责广域网邮件传递,非加密
465/tcp smtps :同上,加密
143/tcp imap :负责将服务器的邮件传回邮件服务端,非加密
993/tcp imaps :同上,加密
587/tcp submission :同上,加密
lmtp :为内部传输服务,不对外,无端口号
最简单的,我们可以用:
netstat -tunlp
看看这些端口起来了没有,
如果显示这样:
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp 0 0 0.0.0.0:25 0.0.0.0:* LISTEN 6717/master
tcp 0 0 0.0.0.0:465 0.0.0.0:* LISTEN 6717/master
tcp 0 0 0.0.0.0:143 0.0.0.0:* LISTEN 6729/dovecot
tcp 0 0 0.0.0.0:993 0.0.0.0:* LISTEN 6729/dovecot
tcp 0 0 0.0.0.0:587 0.0.0.0:* LISTEN 6717/master
说明OK,如果指定的端口号不存在,那么说明服务有问题,需要排查。
另外一个更高端的端口扫描器叫做nmap,也可以实现同样的功能,首先安装它:
dng -y install nmap
使用很简单:
nmap mail.example.com
2. 测试连通性:
如果端口都存在,说明大毛病没有了,我们可以用telnet测一下,
命令很简单,比如我们想测一下993端口:
telnet mail.example.com 993
如果返回:
Trying 123.123.123.123...
Connected to mail.example.com.
Escape character is '^]'.
说明没有大问题,输入quit或ctrl+c,退出。
如果返回:
Trying 123.123.123.123...
telnet: connect to address 123.123.123.123: Connection refused
则说明这个端口有毛病,需要排查。
3. 高端测试
利用openssl命令,我们可以对这些服务进行更深层次的检测。
例如我们想查一下服务器的993端口(imap)加密通道到底正不正常:
openssl s_client -connect mail.example.com:993
如果返回一大堆类似密文的东西,说明基本OK,往上翻,如果出现类似这样的信息:
depth=1 C = US, O = Let's Encrypt, CN = Let's Encrypt Authority X3
verify return:1
depth=0 CN = mail.example.com
说明证书是OK的,由Let's Encrypt公司颁发,域名也跟你的实际域名对得上,说明SSL这一块大问题没有。
如果输入了这条命令毫无反应,或报错,或者域名不是你的域名,你就要仔细排查你的域名证书是不是有问题了,因为dovecot装好之后本身有一本默认证书,但那不是你的域名的,尽管看上去好像没毛病,但实际那本证书是无法使用的。
4. 常见错误
- 问题: Error: namespace configuration error: inbox=yes namespace missing
nano /etc/dovecot/conf.d/15-mailboxes.conf
namespace inbox {
inbox = yes #添加这一行,注意位置一定别搞错,只能加在这里
mailbox Drafts {
auto = create
special_use = \Drafts
}
- 问题:Recipient address rejected: User unknown in local recipient table
nano /etc/postfix/main.cf :
mydestination = \$mydomain
- 问题: Error: Diffie-Hellman key exchange requested, but no DH parameters provided. Set ssh_dh=</path/to/dh.pem
nano /etc/dovecot/dovecot.conf
去掉pop3:
protocols = imap lmtp
pop3需要强制使用迪菲-赫爾曼密鑰(简称DH),因此你需要自己去建一个,相当耗时且麻烦,所以本文中干脆就不用pop3了,imap现在已经是主流协议了,而且功能更强大。
- 其他认证类问题:
基本上问题出在SSL,各种乱七八糟的报错都有,这里就不赘述了,实在不行就从源头开始查,从生成证书那一步就开始认真核对,比如输入域名的时候有没有敲错之类。
- 更诡异的问题:
大家不一定都能碰到,在此我只做一个记录:
所有服务都运行正常,openssl测试也通过了,但是当我用客户端进行设置的时候foxmail就是报ssl错误,百思不得其解,更诡异的是,日志丝毫没有反应,连报错都没有,排查工作根本无从谈起。折腾了一晚上,第二天故障居然自行消失了!找不到问题这更让人窝火,后来通过慢慢回忆,我找出了问题所在:我在用foxmail客户端测试的时候忘记关FQ开关。因为采用的是tun2socks方式全局FQ,我猜测某些数据经过多层跳板是不是无法最终发送到服务器导致?
- 目前的问题:
Mozilla Thunderbird客户端无法使用,Foxmail却很完美,目前我也没有招,搜遍整个google,貌似不止我一个,初步判断是Thunderbird对加密证书有别的要求,反正平时我也是用Foxmail,这个问题先搁一边,以后有时间再慢慢研究。
- 关于防火墙:
firewalld和iptables本人不会用,只贴一个nft的简单版,放行了本文中所有涉及到的端口,关于端口放行的问题,不麻烦,请自行百度谷歌。
我的简单防火墙脚本:
flush ruleset
table inet filter {
chain input {
type filter hook input priority 0; policy drop;
ct state established,related accept
ct state invalid drop
iif lo accept
ip protocol icmp icmp type { destination-unreachable, router-solicitation, router-advertisement, time-exceeded, parameter-problem } accept
ip protocol igmp accept
tcp dport { ssh, http, https,smtp, smtps, imap, imaps} accept
}
chain forward {
type filter hook forward priority 0; policy drop;
}
chain output {
type filter hook output priority 0; policy accept;
}
}
使用方法,先把上面的粘贴复制成一个文件,然后nft -f 文件名,即可。
- 关于客户端设置:
以Foxmail为例,如图:
- 结束了吗?
其实才刚开始,后面的事情还多着呢,还需要给我们的邮件服务器设置WEB Mail,设置SPF、DKIM、DMARC等等等等,SPF和DKIM可以参考我的前一篇博文:
https://www.jianshu.com/p/736867371d28
如何提高邮件服务器的“受尊重度”是一门大学问,而且还不怎么和技术直接挂钩,非常不省心,我的邮件服务器至今也没进得了gmail的法眼,尽管可以通过Postmark等第三方smtp代发机构解决这个难题,但如果大家有什么好方法让我们理直气壮被gmail认可的话,欢迎留言告知,交流,感谢!!
网友评论