在linode的vps上架设了个邮件服务器,网上的东西都太乱,有的太旧,所以记录下安装的步骤。系统用的是archlinux,可能一些文件的位置和设置和别的系统会不一样。DNS是linode提供的DNS,也可能和别的DNS不同。采用的是虚拟邮箱。使用的软件是 postfix,dovecot,postfix-policyd-spf-perl,opendkim 。没有使用数据库,因为用户不多没必要,会加重服务器负担,备份也麻烦。
解析
首先需要设置FQDN,格式是「名字.域名」,比如我的就是 www.xjpvictor.info 。修改 /etc/hosts 中的FQDN,然后重启,FQDN就生效了。以后FQDN就是邮件服务器的地址了。去DNS添加一条MX记录,比如我的邮箱是 @xjpvictor.info ,那么就添加 xjpvictor.info 指向这个FQDN www.xjpvictor.info ,再添加一条 www.xjpvictor.info 的单独的A记录。还有个重要的是去vps提供的面板中把reverse DNS指定到FQDN。
postfix
postfix的作用是传递邮件,就是把客户端发过来的邮件按照地址传给收件方,然后把别人发过来的邮件交给dovecot,再由dovecot放到相应的目录里。在 /etc/postfix 目录下有 main.cf 和 master.cf 两个文件。因为是虚拟邮箱,所以还需要建立 /etc/postfix/virtual_alias /etc/postfix/virtual_domains /etc/postfix/virtual_mailboxes 三个文件来指定虚拟邮箱账户。同时需要建立一个系统用户 vmail 作为收发邮件的账户,也就是说所有的邮件都是这个vmail用户的,然后vmail再通过邮件地址判断是给哪个虚拟用户的,然后放到相应的邮箱里。
groupadd -g 5000 vmail
useradd -g vmail -u 5000 -d /var/spool/vmail -s /bin/false vmail
mkdir /var/spool/vmail
修改 /etc/postfix/main.cf
myhostname = www.xjpvictor.info #FQDN
mydomain = xjpvictor.info #和FQDN中的域名一样
myorigin = xjpvictor.info #发信时候from显示@xjpvictor.info
inet_interfaces = all
inet_protocols = ipv4
mydestination = localhost #使用虚拟邮箱,所以localhost就行了
mynetworks = 127.0.0.0/8
virtual_mailbox_limit = 1000000000 #邮箱大小限制为1G
virtual_alias_maps = hash:/etc/postfix/virtual_alias #邮箱转发设置
virtual_mailbox_domains = hash:/etc/postfix/virtual_domains #收件的域名设置
virtual_mailbox_maps = hash:/etc/postfix/virtual_mailboxes #收信用户
virtual_mailbox_base = /var/spool/vmail #所有邮箱所在目录
virtual_minimum_uid = 5000
virtual_uid_maps = static:5000 #vmail用户
virtual_gid_maps = static:5000 #vmail用户组
virtual_transport = virtual
virtual_mailboxes 中记录着所有可以收信的用户的邮箱目录,注意最后面那个"/"。如果有用户不需要收信的话可以不用写,但是要进行转发,不然邮件就收不到了。
a@xjpvictor.info a@xjpvictor.info/
c@xjpvictor.info c@xjpvictor.info/
virtual_alias 中记录要进行转发的邮箱,比如b的邮件都给a,其余人的邮件都给c
b@xjpvictor.info a@xjpvictor.info
@xjpvictor.info c@xjpvictor.info
virtual_domains 中记录收信的地址
xjpvictor.info none
然后需要生成相应的数据文件,这个文本文件本身postfix是不认的,所以每次改动后都需要再生成数据文件。
postmap ./virtual_mailboxes ./virtual_alias ./virtual_domains
dovecot
dovecot有三个作用,一个是把postfix收到的邮件按照用户名放到相应的目录中,另一个是提供imap服务器,让客户端可以下载邮件,第三个作用是为postfix提供验证,只有通过了验证的才能发送邮件。
修改 /etc/dovecot/dovecot.conf
protocols = imap #只是用imap协议而已,pop实在功能上太弱了
first_valid_uid = 5000 #vmail用户
first_valid_gid = 5000 #vmail组
auth_username_chars = abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890.-_@
disable_plaintext_auth = no
auth_mechanisms = plain login
auth_cache_size = 32M
auth_cache_ttl = 1 days
mail_location = maildir:/var/spool/vmail/%u #邮件的储存目录
mail_fsync = optimized
maildir_very_dirty_syncs = yes
maildir_copy_with_hardlinks = yes
maildir_stat_dirs = no
namespace {
inbox = yes
location =
prefix =
separator = /
type = private
}
service imap-login {
service_count = 1 #每个process只能允许一个连接
process_min_avail = 8 #最少8个process,这样在连接时就能减少folk进程的时间
process_limit = 16 #最多16个process,避免产生过多的process
vsz_limit = 64M
}
service imap {
service_count = 1
process_min_avail = 8
process_limit = 16
vsz_limit = 64M
}
service auth {
unix_listener /var/spool/postfix/private/auth {
group = postfix
mode = 0666
user = postfix
}
unix_listener auth-userdb {
group = vmail
mode = 0600
user = vmail
}
}
userdb {
args = uid=5000 gid=5000 home=/var/spool/vmail/%u #所有邮件的用户都是vmail
driver = static
}
passdb {
driver = passwd-file
args = scheme=SHA256-CRYPT username_format=%u /etc/dovecot/dovecot-user #验证密码,并且密码使用了sha256-crypt加密
}
新建 /etc/dovecot/dovecot-user 文件记录用户名密码,所有需要收信发信的用户都需要记录。
a@xjpvictor.info:{SHA256-CRYPT}$5$123456...7890
b@xjpvictor.info:{SHA256-CRYPT}$5$123456...7890
c@xjpvictor.info:{SHA256-CRYPT}$5$123456...7890
密码的生成用
doveadm pw -s sha256-crypt
会提示输入密码两次,然后就会生成一串加密过的密码。注意不能用 echo xxx | doveadm pw -s sha256-crypt ,因为需要输入两次密码,如果用管道最后生成的加密字符串是不对的。
还需要设置postfix让它使用dovecot来进行密码验证。所以再修改 /etc/postfix/main.cf ,在最后加入
smtpd_sasl_auth_enable = yes
smtpd_sasl_type = dovecot
smtpd_sasl_path = private/auth
smtpd_sasl_local_domain = localhost
broken_sasl_auth_clients = yes
smtpd_recipient_restrictions = permit_sasl_authenticated, permit_mynetworks, reject_unauth_destination
smtpd_sasl_security_options = noanonymous
smtpd_sasl_tls_security_options = $smtpd_sasl_security_options
这样一来,我有了 a@xjpvictor.info b@xjpvictor.info c@xjpvictor.info 三个用户,其中 b@xjpvictor.info 的邮件会被转发给 a@xjpvictor ,而其他用户比如 d@xjpvictor.info 的邮件会转发给 c@xjpvictor.info 。b和d是不能直接收邮件的,而d连发送也是不行的。
加密
加密主要是dovecot的imap的ssl加密,以及postfix的tls加密。先说dovecot的ssl加密。修改 /etc/dovecot/dovecot.conf ,加入
ssl = required #使用ssl的连接
ssl_cert = </etc/postfix/certs/www.crt
ssl_ca = </etc/postfix/certs/ca.crt
ssl_key = </etc/postfix/certs/www.key
并把
disable_plaintext_auth = no
改为
disable_plaintext_auth = yes
证书的话,我用了startssl的免费证书,所以把申请来的证书放在 /etc/postfix/certs 里,需要指定证书 .crt .key 文件以及startssl的根证书 ca.crt。因为这个证书和postfix的证书我用的是同一个,而startssl免费证书不支持wildcard,所有我的imap服务器也就和smtp服务器相同地址了,也就是FQDN了。其实多申请一个专门用于imap也是可以的。ssl加密的imap使用的是993端口。
再做postfix的tls加密。修改 /etc/postfix/main.cf ,加入
smtp_use_tls = yes
smtp_tls_note_starttls_offer = yes
smtpd_use_tls = yes
smtpd_tls_auth_only = yes
smtpd_tls_received_header = yes
smtpd_starttls_timeout = 60s
smtpd_tls_cert_file = /etc/postfix/certs/www.crt
smtpd_tls_CAfile = /etc/postfix/certs/ca.crt
smtpd_tls_key_file = /etc/postfix/certs/www.key
smtpd_tls_loglevel = 1
tls加密的smtp使用的仍然是25端口,如果客户端想使用587端口,把 /etc/postfix/master.cf 中
submission inet n - n - - smtpd
给uncomment掉。但是记得防火墙仍然需要打开25端口。
因为我需要在vps上直接用msmtp通过tls发送邮件,所以需要把ca根证书单独放着,不然的话可以把根证书合并到 .crt 中。题外话,如果要用msmtp发送邮件并且使用tls,那么必须指定ca,所以postfix就不能把ca合并到证书里,而是需要单独指定CAfile,但是这样的话msmtp又不能再指定ca文件,所以需要设置tls_fingerprint,把ca的fingerprint放进去就好了。
邮箱验证
这个验证是告诉对方我这台邮件服务器证明这个邮箱发出的信是我这里发送的,而不是被其他服务器盗用我的名义发送的,这样对方就能稍微放心点认为这不是垃圾邮件。这就是SPF验证。很简单,在DNS中添加一条TXT记录。注意在设置中name那边什么都别写,不然对方会认为这条TXT记录不是这个域名的SPF。
v=spf1 a:www.xjpvictor.info mx:xjpvictor.info -all
这就是说邮件的发送服务器的ip必须是www.xjpvictor.info的A记录中的ip,域名是xjpvictor.info的mx记录中的域名,否则就应该被拒绝。这也是为什么在DNS中需要一条www.xjpvictor.info的单独的A记录。
当然,在收邮件的时候也能验证对方的SPF。安装 postfix-policyd-spf-perl ,在 /etc/postfix/main.cf 中修改
smtpd_recipient_restrictions = permit_sasl_authenticated, permit_mynetworks, reject_unauth_destination
为
smtpd_recipient_restrictions = permit_sasl_authenticated, permit_mynetworks, reject_unauth_destination, check_policy_service unix:private/policy-spf
并添加
header_checks = pcre:/etc/postfix/header_checks
再在 /etc/postfix/master.cf 中最后添加
policy-spf unix - n n - - spawn
user=nobody argv=/usr/lib/postfix/postfix-policyd-spf-perl
在 /etc/postfix/header_checks 中添加
/Received-SPF: softfail/ REJECT
Update 2012-08-15
我把header_checks这里给删掉了,因为我发现有些公司并不是很注重SPF,所以如果他们的SPF通不过验证的话就会导致邮件寄不进来了
除了SPF,DKIM也很重要。主要是用来给发送的邮件签名,然后对方收到邮件后就会用我这台服务器提供的公钥验证,最后发现确实是我发的邮件,这样对方就能更加确定这不是垃圾邮件了。先安装opendkim,然后
opendkim-genkey
会生成 default.private default.txt 两个文件,把 default.private 放到 /etc/opendkim/ 中作为私钥,然后在DNS中添加一条TXT记录,把 default.txt 中的
v=DKIM1; k=rsa; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDgsYAx/iu+e/6f8ICyBcFXYh6b8n1Y5uqIwo+hc7hHIEw0ILzItc30F2HLvWGtigiij5q20nBp+32Nos3VkU5Ey0dsh8rvAMLyk1vbFBd7jV3lAH071HLnCxuzAWbXkz9lOIY6S+b9ZpGg1spqavr//Cy9KjIymc56nbqiRO/KLQIDAQAB
写在TXT记录中,记录的名字是
dkim._domainkey
其中dkim是 selector ,然后新建 /etc/opendkim/opendkim.conf 文件
Domain xjpvictor.info
KeyFile /etc/opendkim/default.private
Selector dkim
Socket inet:8891@localhost
UserID opendkim
再添加一条DNS的TXT记录
dkim=all
名字是
_adsp._domainkey
这是告诉对方这个服务器发出的邮件都需要有dkim签名。再到 /etc/postfix/main.cf 中添加
non_smtpd_milters=inet:127.0.0.1:8891
smtpd_milters=inet:127.0.0.1:8891
这样发送邮件的时候会附加DKIM签名,而收邮件时候也会验证DKIM签名了。
测试
测试一下是不是能用了。给gmail发封邮件,如果收到的话,show original查看原信件,如果看到
Authentication-Results: mx.google.com; spf=pass (google.com: domain of a@xjpvictor.info designates 1.2.3.4 as permitted sender) smtp.mail=a@xjpvictor.info; dkim=pass header.i=@xjpvictor.info
就说明SPF和DKIM验证通过。
然后用gmail回复一封邮件,然后收到后查看原信件,opera中是view all headers and message,kmail中是view source。如果看到
Authentication-Results: www.xjpvictor.info; dkim=pass reason="2048-bit key" header.d=gmail.com header.i=@gmail.com header.b=R6ZrCqGu; dkim-adsp=pass
就是说收到信以后验证了SPF和DKIM并且通过了。
再执行
telnet localhost 25
登录后执行
starttls
如果看到
Ready to start TLS
说明收信的时候如果发信方也支持的话,那么就是使用的TLS加密连接的。比如gmail发过来的邮件就是通过TLS加密的,但是像QQ之流就还是普通连接。
然后访问 http://checktls.com/perl/TestSender.pl 根据说明向他们发送一封邮件,等他们回复的邮件,如果里面写了
Your email was successfully sent securely using TLS.
就说明发送邮件的时候如果对方支持,那就会使用TLS加密连接。