在 Nginx 上配置 SSL 加密的 SMTPS, IMAPS 和 POP3S 反向代理

准备工作与说明

本文是针对使用第三方企业邮箱(域名邮箱)的,如果您有独立的邮件服务器,不适用本文。

您需要一个具有 root 权限的 VPS 或云服务器。

我们假定您已经做好 DNS 的 MX 记录解析,第三方企业邮箱已经运行正常,且将 smtp/imap/pop3.<yourdomain>.<yourtld> 解析到您正在操作的服务器上。

本文使用的是 Ubuntu 操作系统,其他系统的操作可能有所不同。

使用 acme.sh 申请 SSL 证书

首先下载 acme.sh :

1
curl  https://get.acme.sh | sh

随后申请证书。笔者使用的是 DNSPod 作为 DNS 服务器,为了进行 DNS 验证,需要获取 DNSPod 的 API 访问密钥。

获取密钥后,执行如下 shell 脚本来申请证书:

1
2
3
4
5
6
export DP_Id="******"
export DP_Key="******"
~/.acme.sh/acme.sh --issue --dns dns_dp \
-d pop3.josephcz.xyz \
-d imap.josephcz.xyz \
-d smtp.josephcz.xyz

可以直接输入 acme.sh 来获取帮助。因为只配置与收发电子邮件相关的域名,因此只申请了有关的三个域名的证书。

也可将该 shell 脚本保存为 .sh 文件并加入 crontab 来自动续期。具体操作在此不表。

安装 Nginx

一句话就够了:

1
apt-get install nginx-full

Nginx 配置

确认或移动 SLL 证书位置

首先移动 SSL 证书的位置。SSL 证书一般保存在 ~/.acme.sh/ 下名字为申请的首个域名的文件夹(在本文中,即 pop3.josephcz.xyz)内。最好将证书移动到一个比较方便的位置,如 /etc/nginx/ssl/ 下。

在本文中,我将文件夹命名为 mail-svcs-josephcz.xyz,并将文件夹内的 pop3.josephcz.xyz.* 文件重命名为了 server.*。以下是进行重命名操作的命令:

1
2
3
4
cd ~/.acme.sh/pop3.josephcz.xyz/
rename -v "s/pop3.josephcz.xyz.*/server.\1/" *
mkdir /etc/nginx/ssl
mv ~/.acme.sh/pop3.josephcz.xyz /etc/nginx/ssl/mail-svcs-josephcz.xyz

重命名不是必须的,但是为了使文件结构和配置文件更加清晰,最好还是进行重命名操作。

配置 TCP 转发

/etc/nginx/nginx.conf 内,找到 stream 节。如果已经存在,可以在原有的节下添加。如果没有该节,则可以新建一个:

1
2
3
stream {
# 在这里开始下面的配置
}

您也可以通过 include 指令来更加方便的管理(并将配置代码放在 mail-proxy 文件中):

1
2
3
stream{
include /etc/nginx/mail-proxy;
}

定义上游

首先要定义 SMTP, IMAP 和 POP3 的上游(即被反向代理)的服务器。以本站使用的阿里云邮为例:

1
2
3
4
5
6
7
8
9
10
11
upstream pop3{
server pop3.mxhichina.com:995;
}

upstream smtp{
server smtp.mxhichina.com:465;
}

upstream imap{
server imap.mxhichina.com:993;
}

配置监听端口和 SSL 证书

新建一个 server 块,并配置证书。

  • listen:监听端口号。为了启用 SSL,必须在后面跟上 ssl
  • ssl_certificatessl_certificate_key:证书和私钥。注意证书应当选择 fullchain 防止因为证书链不全导致服务器不被信任。
  • ssl_protocolsssl_ciphers:安全性配置。在这里禁用了一些不安全的 SSL 协议版本和密钥。可以根据自己的需要配置。

以下以 SMTPS 服务为例:

1
2
3
4
5
6
7
server{
listen 465 ssl;
ssl_certificate /etc/nginx/ssl/mail-svcs-josephcz.xyz/fullchain.cer;
ssl_certificate_key /etc/nginx/ssl/mail-svcs-josephcz.xyz/server.key;
ssl_protocols TLSv1.2 TLSv1.1 SSLv3;
ssl_ciphers HIGH:!aNULL:!MD5;
}

配置代理并指定使用 SSL

在 server 块下增加两行:

1
2
proxy_pass smtp;
proxy_ssl on;

完整配置

用同样的方法配置 IMAPS 和 POP3S。

以下是完整的配置文件:

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
36
37
38
39
40
41
42
43
44
45
46
stream{
upstream pop3{
server pop3.mxhichina.com:995;
}

upstream smtp{
server smtp.mxhichina.com:465;
}

upstream imap{
server imap.mxhichina.com:993;
}

server{
listen 995 ssl;
ssl_certificate /etc/nginx/ssl/mail-svcs-josephcz.xyz/fullchain.cer;
ssl_certificate_key /etc/nginx/ssl/mail-svcs-josephcz.xyz/server.key;
ssl_protocols TLSv1.2 TLSv1.1 SSLv3;
ssl_ciphers HIGH:!aNULL:!MD5;

proxy_pass pop3;
proxy_ssl on;
}

server{
listen 465 ssl;
ssl_certificate /etc/nginx/ssl/mail-svcs-josephcz.xyz/fullchain.cer;
ssl_certificate_key /etc/nginx/ssl/mail-svcs-josephcz.xyz/server.key;
ssl_protocols TLSv1.2 TLSv1.1 SSLv3;
ssl_ciphers HIGH:!aNULL:!MD5;

proxy_pass smtp;
proxy_ssl on;
}

server{
listen 993 ssl;
ssl_certificate /etc/nginx/ssl/mail-svcs-josephcz.xyz/fullchain.cer;
ssl_certificate_key /etc/nginx/ssl/mail-svcs-josephcz.xyz/server.key;
ssl_protocols TLSv1.2 TLSv1.1 SSLv3;
ssl_ciphers HIGH:!aNULL:!MD5;

proxy_pass imap;
proxy_ssl on;
}
}

启用服务和检查

重启 Nginx:

1
service nginx restart

随后,查看端口使用情况确认服务已经启动:

1
netstat -altp

可以看到以下三行,说明服务已经成功启动:

1
2
3
tcp  0  0 *:imaps  *:*  LISTEN      5822/nginx -g daemo
tcp 0 0 *:pop3s *:* LISTEN 5822/nginx -g daemo
tcp 0 0 *:urd *:* LISTEN 5822/nginx -g daemo
  • 注:URD 是和 SMTPS 同一端口的另一协议。

如果有防火墙,还应当允许防火墙通过相应的端口。

最后使用邮件客户端测试,应当可以正常使用 SSL 的邮件协议,并不会有证书错误的信息提示了。