Zhen Zhang's Blog

VPS 折腾系列(二)-- mail server

这篇教程我们主要来讨论怎么利用VPS来搭建服务器。

(本文主要是对这篇文章进行了一些解释、翻译和拓展,其中一些地方进行了更正,并且加入了一些digitalocean的特色设置,在此声明)

原因

我们为什么会有这样一个想法呢?当我们拥有了自己的域名以后,很显然的就会去想,如果我有一个以我的域名命名的邮箱该有多么cool啊!比如我拥有的域名中有一个是zhangzhen.me,那么我想拥有一个邮箱形如xxx@zhangzhen.me。

这其实有很多种方式可以去实现:

  1. 使用google Apps for enterprise,这也应该是最好的方案。然而这个需要我们每个月支付5dollars,一年下来也是一笔不小的开支。当然,如果你在2012年12月7日之前就注册了免费版,那么恭喜你,这篇教程可以直接跳过了,因为我们的终极目的也是想用gmail来收发我们的域名邮箱。

  2. 使用腾讯企业邮、网易企业邮等国内的免费版,或者Zoho企业邮的免费版。前者经常收不到邮件(这个经常上v2ex的攻城狮应该都知道他们被吐槽成什么样了),而后者的管理界面一直感觉很别扭。

  3. 自己搭建服务器。这也是本文将要讨论的问题。

所以,我们的目的已经很明确了:使用自己的VPS来搭建一个mail server进行邮件的收发,并且最后达到能够用gmail来管理我们自己创建的域名邮箱的目标。

在这里我们使用的VPS是digital ocean的最便宜套餐,系统是Ubuntu 14 x86。

开始吧。

Step 0: 准备

在搭建mail server之前,我们需要保证一下几点:

  1. 有自己的VPS,且运行Linux系统;

  2. 有自己的域名,如zhangzhen.me;

并且,我们假设:

  1. 我们的域名为example.domain;

  2. 我们的mail server地址是myserver.example.domain;

  3. 我们的gmail目标邮箱是myname@gmail.com;

Step 1: 设置相关DNS记录

  1. MX记录:这里要将MX记录指向myserver.example.domain,这相当于告诉全网络,所有给@example.domain发的邮件都将会被发送到myserver.example.domain服务器上;

  2. A记录:将myserver.example.domain指向我们的VPS的IP;

  3. PTR记录:将IP地址反向解析到我们的mail server上,也就是myserver.example.domain上。这能够帮主Gmail验证我们域名的合法性。这一项不同于前两项,不能在域名供应商那里设置,应该在VPS供应商那里设置。

    这里需要注意的是,如果你和我一样使用的是digital ocean的VPS的话,我们的PTR记录就是我们droplet的名称。换句话说,如果我想让我的mail server的名称是myserver.example.domain的话,我的droplet也必须叫这个名字。我们可以通过host IP来检测我们的PTR记录。

  4. TXT记录:这里创建的TXT记录,值为“v=spf1 mx ~all”,直接指向example.domain。

Step 2: 邮件的接收

Step 2.1: Postfix基本设置

我们这里主要是通过Postfix这一工具完成的。

首先是他的安装:

1
$ sudo DEBIAN_FRONTEND=noninteractive apt-get install postfix

这里我们选择了使用DEBIAN_FRONTEND=noninteractive,是因为如果我们不这么做的话,我们安装的过程将会有图形界面出现,而那些设置最终都可以在配置文件中调整。

下一步就是修改配置文件/etc/postfix/main.cf

1
vi /etc/postfix/main.cf

我们的目标是把它修改成这样:

1
2
3
4
5
6
7
8
9
10
# /etc/postfix/main.cf
# Host and site name.
myhostname = myserver.example.domain
mydomain = example.domain
myorigin = example.domain
# Virtual aliases.
virtual_alias_domains = example.domain
virtual_alias_maps = hash:/etc/postfix/virtual

前面的几行不解释了,最后一行是告诉Postfix,当看到发给xxx@example.domain的时候,将它转发给另一个邮箱,而他的规则在/etc/postfix/virtual文件中指定:

1
2
3
4
5
6
# /etc/postfix/virtual
# Forwarding mapping, one from-to address pair per line. The format is:
# <forward-from-addr> <whitespace> <forward-to-addr>
@example.domain myname@gmail.com

这里将@example.domain前面留白的原因是,所有发给他的邮件,都转发给对应的gmail。当然这里我们也可以设置多条规则,指定邮箱之间的对应关系。

现在我们需要让Postfix来认识一下这个规则:

1
$ sudo postmap /etc/postfix/virtual

需要注意的是,每次更改了规则,都要相应的去执行这条指令。

重启Postfix:

1
2
$ sudo postfix restart
$ sudo postfix reload

和上面相同,每次更改postfix时候,都要执行这个指令。

Step 2.2: 测试

这里我们可以测试一下我们能否对外发邮件了:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
$> telnet localhost 25
Trying ::1...
Connected to localhost.
Escape character is '^]'.
220 myserver.example.domain ESMTP Postfix
> HELO myserver.example.domain
250 myserver.example.domain
> mail from: me@myserver.example.domain
250 2.1.0 Ok
> rcpt to: myname@gmail.com
250 2.1.5 Ok
> data
354 End data with <CR><LF>.<CR><LF>
> subject: Test
>
> This is a test mail
> .
>
250 2.0.0 Ok: queued as B9AD4204C7
> quit
221 2.0.0 Bye

发送完成后,我们的gmail中很可能就会看到这封邮件了。之所以说很可能,是因为他有可能在垃圾箱中。后续我们会解决这一问题。

Step 3: 发送邮件

Step 3.1: Cyrus SASL 加密

我们在这里的思路是,Gmail需要一个relay server,这样Gmail和我们的mail server之间可以通过TLS进行加密保护,从而让Gmail发邮件到myserver.example.domain,最后发送到指定地点。

首先安装Cyrus SASL:

1
$ sudo apt-get install sasl2-bin libsasl2-modules

然而我们的目标是仅仅让Gmail可以和我们的mail server进行通讯,其他的垃圾邮件等都不应该能够连接上我们的mail server。这就需要我们进行加密。当然加密有很多手段,比如mySQL,但是我们这里只需要建立一个最简单的文件就可以了。他的默认位置是在/etc/sasldb2:

1
$ sudo saslpasswd2 -c -u example.domain smtp

这里的smtp是我们的用户名,当然也可以换成其他的。此时我们需要输入密码,并确认密码。

这之后我们可以这样验证:

1
$ sudo sasldblistusers2

console中应该输出这样的结果:

1
smtp@example.domain: userPassword

现在我们需要修改文件的权限,这样使得只有Postfix可以读取它:

1
2
$ sudo chmod 400 /etc/sasldb2
$ sudo chown postfix /etc/sasldb2

最后,我们告诉Cyrus SASL去使用这个文件进行什么验证。在/etc/postfix/sasl/smtpd.conf建立文件:

1
2
3
4
pwcheck_method: auxprop
auxprop_plugin: sasldb
mech_list: PLAIN LOGIN CRAM-MD5 DIGEST-MD5 NTLM
log_level: 7

Step 3.2 SSL加密

我们需要通过SSL加密来使用TLS。这里使用自签名的证书就已经足够了。这里使用的是RSA加密方式。

  1. 生成公钥和私钥。这里需要输入密码。

    1
    $ openssl genrsa -des3 -out example.key 1024
  2. 生成CSR文件:

    1
    $ openssl req -new -key example.key -out example.csr

    在这里我们需要输入一串信息,除了common name必须输入为myserver.example.domain以外,其余都可以不输入。

  3. 移除RSA公钥私钥密码:

    1
    2
    $ mv example.key example.key.orig
    $ openssl rsa -in example.key.orig -out example.key
  4. 生成自签名证书。我们设定时间为10年。

    1
    $ openssl x509 -req -days 3650 -in example.csr -signkey example.key -out example.crt
  5. 生成PEM文件:

    1
    $ cat example.crt example.key > example.pem
  6. 移动并保护PEM文件:

    1
    2
    3
    $ sudo mv example.pem /etc/postfix/example.pem
    $ sudo chmod 400 /etc/postfix/example.pem
    $ sudo chown postfix /etc/postfix/example.pem

Step 3.3 Relay Server配置

这里我们需要配置/etc/postfix/master.cf:

1
2
3
4
5
6
7
8
submission inet n - n - - smtpd
-o syslog_name=postfix/submission
-o smtpd_tls_security_level=may
-o smtpd_tls_cert_file=/etc/postfix/example.pem
-o smtpd_sasl_auth_enable=yes
-o smtpd_reject_unlisted_recipient=no
-o smtpd_relay_restrictions=permit_sasl_authenticated,reject
-o milter_macro_daemon_name=ORIGINATING

需要注意的是,submission的那一行第三项要设置为n。

重启Postfix:

1
2
sudo service postfix restart
sudo postfix reload

这里我们就可以监听到587端口了:

1
$ sudo netstat -antu --program | grep 587

Step 4: 配置Gmail

这里好像不需要解释,如果你按照之前的步骤来做的话,这里直接套用就可以了。

首先找到Gmail–settings–Accounts and Import– Add another email address you own。

Gmail1

Gmail2

如果一切正常,你就会到输入验证码的界面了。这时候进入我们在/etc/postfix/virtual指定的收件箱,就可以看见验证码了。

Step 5: 配置DKIM

到这里,我们的邮箱已经可以在Gmail上正常使用了。然而这还不够,因为我们要保证我们的邮件不能被收件系统扔到垃圾箱里面。所以我们需要配置DKIM。

DKIM (DomainKeys Identified Mail),是一种验证机制。它表示发邮件的一方对邮件进行签名,而接受方通过公钥对其进行验证。

Step 5.1: DKIM的安装和基本配置

首先是安装:

1
$ sudo apt-get 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
22
23
24
25
26
# OpenDKIM config.
# Log to syslog
Syslog yes
SyslogSuccess yes
LogWhy yes
# Required to use local socket with MTAs that access the socket as a non-
# privileged user (e.g. Postfix)
UMask 002
Mode sv
PidFile /var/run/opendkim/opendkim.pid
UserID opendkim:opendkim
Socket inet:12301@localhost
Canonicalization relaxed/simple
SignatureAlgorithm rsa-sha256
# Sign for example.domain with key in /etc/opendkim.d/mail.private using
# selector 'mail' (e.g. mail._domainkey.example.domain)
Domain example.domain
KeyFile /etc/opendkim.d/mail.private
Selector mail
ExternalIgnoreList refile:/etc/opendkim.d/TrustedHosts
InternalHosts refile:/etc/opendkim.d/TrustedHosts

之后我们需要建立/etc/opendkim.d/TrustedHosts这个文件:

1
2
mkdir /etc/opendkim.d
vi /etc/opendkim.d/TrustedHosts

并把它配置成如下形式:

1
2
3
4
5
127.0.0.1
localhost
192.168.0.1/24
*.example.domain

这个配置文件告诉DKIM,由这些server发出的邮件,都需要进行签名。

Step 5.2: 密钥对生成

下面让我们生成密钥对:

1
2
$ cd /etc/opendkim.d
$ sudo opendkim-genkey -s mail -d example.domain

这两条指令能够生成一对密钥存放在/etc/opendkim.d中: mail.private (我们的私钥),mail.text (我们的公钥)

下面我们需要修改私钥的权限,保证只有DKIM能够读取:

1
2
$ chmod 600 mail.private
$ chown opendkim:opendkim mail.private

Step 5.3 DNS TEXT record 的配置

我们打开mail.text,就会看到如下形式的文字:

1
mail._domainkey IN TXT ( "v=DKIM1; k=rsa; p=<alphabetical soup>" ) ;----- DKIM key mail for example.domain

我们需要在domain提供商那里更新如下的DNS Text record:

Hostname: mail._domainkey.example.domain

Value: v=DKIM1; k=rsa; p=

这里需要注意的是,如果你和我一样,如果使用的是NameCheap的话,Hostname应该输入 mail._domainkey 就可以了。

Step 5.4 最后的配置

此时,我们修改/etc/postfix/main.bash,使他对于发出的邮件进行签名:

1
2
3
4
5
6
# Milter settings.
milter_protocol = 2
milter_default_action = accept
# OpenDKIM runs on port 12301.
smtpd_milters = inet:localhost:12301
non_smtpd_milters = inet:localhost:12301

如果你曾经配置了SpamAssassin,那么你需要将最后两行追加到相应纪录的后面,以分号隔开。

最后重启相应服务:

1
2
$ sudo /etc/init.d/opendkim start
$ sudo postfix reload

至此,我们的服务器就基本配置完毕了。

Step 6: 垃圾邮件测试

我们这里通过一个叫做mailtester的网站来检测我们的邮件是否会被识别为垃圾邮件,如果可以得到满分10分的话,说明我们的mail server已经足够好啦!