從零開始郵件服務器搭建

概念解釋

SPF:Sender Policy Framework,直譯過來就是發件人保證框架.出現的主要原因是SMTP協議的缺陷.XMTP中,發件人的郵箱地址是可以偽造的,因而SPF的出現就是防止偽造發件人.SPF的記錄實際上就是DNS服務器上面的一個記錄.如果郵件服務器收到了一封郵件,來自主機的IP是45.76.210.63并且生成發件人為yusengy@info.郵件服務器會去查詢yusengy@info的SPF記錄.如果SPF記錄的IP為45.76.210.63,那么就認為是合法的,否則通常都會被退信.SPF記錄一般如下.

SPF記錄
SPF記錄

DKIM:DomainKeys Identified Mail.功能目的與SPF相似,主要是讓收件人可以通過加密解密的方式來得知發件人是否是真實的.原理就是在電子郵件的開頭插入一段簽名,然后接收方通過從DNS查詢得到公鑰以后,以進行驗證,與SSH的公鑰和密鑰類似.
記錄一般如下:

DKIM公鑰
DKIM公鑰

PTR:反向域名解析,可以通過發件人的IP地址反向得知域名,也是一種用以判斷發件人是否正常的方式.

MUA:Mail User Agent.用戶郵件代理,用戶通過MUA接收發送郵件.例如Outlook, formail等.

MTA: Mail Transfer Protocol.郵件傳輸代理,是SMTP的一種實現.常用的MTA有sendmail,Postfix.本例中使用Postfix.MTA僅僅負責郵件的傳輸,MDA負責把接收到的郵件保存在硬盤中.

MDA: Mail Deliver Agent,郵件分發代理.負責將接收到的郵件保存在郵件服務器上.sendmail以及Postfix默認使用的MDA是procmail.

MRA: Mail Receive Agent,郵件接收代理,用來實現IMAP,POP3協議,負責與MUA交互,將服務器上的郵件通過IMAP以及POP3傳輸給客戶端.本例中使用的MRA是Dovecot.

LMTP:Local Mail Transfer Protocol.本地郵件傳輸協議,是SMTP協議的擴展.本例中用與同一主機內郵件傳輸.

Postfix:一個開源的MTA服務器,負責通過SMTP協議管理發送到本機的郵件以及由本機向外發送的郵件.與sendMail相似.現今流行的服務器套件例如Zimbra,IRedMail內部都采用Postfix作為MTA.

Dovecot:一個開源的IMAP以及POP3服務器.通常工作是驗證用戶身份以及郵件的處理.

MySQL:存取用戶信息,監聽的域名信息,用戶郵箱地址以及登錄密碼等.

郵件協議簡述

SMTP

SMTP全稱是Simple Mail Transfer Protocol,直譯過來就是簡單郵件傳輸協議, 由RFC5321定義.主要的工作就是把郵件信息從發件人的郵件服務器中傳送到接收人的郵件服務器中,偶爾我們使用MUA來發送郵件的話,也承載傳輸用戶郵件到發件服務器的功能, 因而也稱作協議,順帶提一下,SMTP協議的出現是比HTTP還早的,最早在1982年中發布第一版的RFC.
因而因為提出的年代久遠,所以在當時有許多問題都考慮不全面并且也有這許多的限制,例如SMTP要求信息內容需要是7位的ASCII來承載,因而我們在發送以及接受的時候,都需要將其編碼解碼.
另外,SMTP還存在一個問題就是沒有對發送方進行一個身份驗證,雖然在早期的互聯網環境沒有很大問題,但是在垃圾郵件滿天飛的今天,這卻是一個明顯的短板.因而衍生出了SPF, DKIM, DMARC等一系列用來驗證發件人身份的方法.

POP3

POP3,Post Office Protocol Version 3,直譯就是郵局協議第三版,由RFC1939進行定義.這個協議的主要服務于用戶管理郵件服務器上面的電子郵件.具體過程是:當外來郵件發送到收件人的郵件服務器上時,收件人可以使用郵件客戶端連接郵件服務器,把未閱讀的郵件服務器以及部分信息拉取回本地進行處理.在拉取的過程中,我們可以選擇拉取完刪除以及拉取完不刪除兩種方式,不過現在默認一般都是拉取完不刪除,方便我們在其他的地方也能對郵件進行閱讀以及管理.

IMAP

IMAP, Internet Message Access Protocol, 直譯過來就是網絡信息訪問協議,可能和現在主流的翻譯不太一致,不過能理解其意思就好.相對于pop3協議所有郵件的管理都需要下載下來進而管理,IMAP提供了用戶遠程訪問郵件服務器的途徑,因而通過IMAP,用戶可以直接管理郵件服務器上的郵件.

工作原理

電子郵件架構

郵件原理
郵件原理

這里我們使用的MTA是Postfix, MRA是Dovecot.我們可以繪制出郵件服務器接受郵件,用戶查收郵件以及用戶發送郵件的過程.

郵件服務器接受收件

假設yusen@Foxmail.com發送一封郵件到yusen@yusengy.info中.

郵件服務器接受郵件
郵件服務器接受郵件

  1. foxmail.com服務器會通過DNS查詢到yusengy.info的MX記錄,然后找到Postfix所在的服務器所在.
  2. 郵件通過SMTP協議發送給Postfix.
  3. Postfix通過MySQL查詢,yusengy.info是否是本機需要處理的域名.
  4. MySQL通過查詢返回確認信息給Postfix.
  5. Postfix得到確認信息,把郵件傳送給Dovecot,由Dovecot的LMTP服務來說投遞工作.
  6. Dovecot把郵件的內容保存在對應的路徑中.

用戶查收郵件過程

用戶查收郵件過程
用戶查收郵件過程
  1. MUA向Dovecot請求IMAP連接.
  2. Dovecot發送自己的SSL證書.
  3. MUA發送用戶的賬號密碼.
  4. Dovecot得到賬號密碼向MySQL查詢.
  5. MySQL返回查詢結果.
  6. 如果賬號密碼正確,Dovecot讀取在改用戶路徑下的信息.
  7. 得到最新的郵件以及其他的一些統計信息.
  8. 通過IMAP協議發送給MUA.

用戶發送郵件的過程

用戶發送郵件過程.png-19.1kB
用戶發送郵件過程.png-19.1kB
  1. MUA請求Postfix建立SMTP連接
  2. Postfix發送SSL證書給MUA
  3. MUA發送賬號密碼給Postfix,請求驗證
  4. Postfix請求Dovecot驗證賬號密碼.
  5. Dovecot請求MySQL查詢結果
  6. MySQL返回查詢結果.
  7. Dovecot返回Postfix賬號密碼驗證結果.
  8. Postfix返回MUA賬號密碼驗證結果.
  9. MUA使用SMTP協議發送郵件到Postfix.
  10. Postfix把郵件進行發送.接下來的步驟參考前面服務器查收郵件的過程.

郵件服務器搭建

根據上面的幾個示意圖,我們已經基本了解了郵件發送,接收的一般流程以及每個組件在其中的職責.了解清楚以后,郵件服務器的搭建則會變得簡單了許多,明白其中每一步的作用以及緣由.

前期準備

設置hostname

CentOS7,可以通過hostnamectl set-hostname hostname命令設置hostname,并且修改hosts文件.這里域名是yusengy.info.

hostnamectl set-hostname mail.yusengy.info

為什么要設置hostname呢?因為一般情況下,Postfix在與其他的SMTP服務器進行通信的時候,會使用hostname來表名自己的身份.主機名有兩種形式,單名字FQDN(Fully Qualified Domain Name).如果SMTP服務器不是用FQDN來表明身份,則有可能會被拒收.

修改防火墻開放端口

修改防火墻開發相應的端口,分別是25, 465, 587, 110, 995, 143, 993.

域名解析配置

域名解析配置
域名解析配置

安裝Postfix, Dovecot以及數據庫

由于Centos中默認的源沒有MySQL,因而使用MariaDB代替,實際使用與MySQL一致.
首先更新系統yum update -y.把系統的一些組件更新到最新,然后需要修改一些CentOS的源設置,因為CentOS默認源里面的Postfix默認是不能和MariaDB協同工作的,因而我們需要安裝擴展源里面的Postfix.
修改: /etc/yum.repos.d/CentOS-Base.repo

[base]
name=CentOS-$releasever - Base
exclude=postfix

#released updates
[updates]
name=CentOS-$releasever - Updates
exclude=postfix

修改完畢以后,我們讓擴展源生效,并且安裝我們所需要的應用以及服務.

yum --enablerepo=centosplus install postfix
yum install dovecot mariadb-server dovecot-mysql

接下來,我們配置MariaDB數據庫來處理虛擬域名以及用戶信息.

數據庫配置

MariaDB的安裝配置與MySQL有些許不同,MySQL是在安裝的時候設置root的密碼,而MariaDB則是在安裝完畢后設置密碼.
首先我們啟動MariaDB.

systemctl enable mariadb.service
systemctl start mariadb.service

然后,我們進行一些初始化的配置.

mysql_secure_installation

輸入mysql_secure_installation后,我們可以修改root用戶的密碼,禁止外部使用root登錄,刪除匿名賬戶以及刪除test表等等.

數據庫概覽

創建mail數據庫用以處理郵件相關的業務.并且創建郵件管理員.

GRANT SELECT, INSERT, UPDATE, DELETE ON mail.* TO 'mail_admin'@'localhost' IDENTIFIED BY 'mys123123';
GRANT SELECT, INSERT, UPDATE, DELETE ON mail.* TO 'mail_admin'@'localhost.localdomain' IDENTIFIED BY 'mys123123';
FLUSH PRIVILEGES;

這里的mys123123替換成自己的密碼.我這里只是做示范使用,實際中應該使用強度更大的字符串作為密碼.

數據庫
數據庫

mail數據庫中一共有4個表,分別是虛擬域名, 郵件轉發, 用戶信息以及傳輸路徑四個表..
表格
表格

虛擬域名表

該表存儲的是本地服務器用來接收郵件的域名.


虛擬域名表表結構
虛擬域名表表結構

創建語句

CREATE TABLE domains (domain varchar(50) NOT NULL, PRIMARY KEY (domain) );

郵件轉發

可以用來轉發郵件.


郵件發送表表結構
郵件發送表表結構
CREATE TABLE forwardings (source varchar(80) NOT NULL, destination TEXT NOT NULL, PRIMARY KEY (source) );

用戶表

用來存儲用戶的賬號密碼.這里密碼使用加密的方式進行存儲.


用戶信息表結構
用戶信息表結構
CREATE TABLE users (email varchar(80) NOT NULL, password varchar(20) NOT NULL, PRIMARY KEY (email) );

傳輸路徑表

傳輸表可以用來指定郵件的傳輸路徑.


傳輸表結構
傳輸表結構
CREATE TABLE transport ( domain varchar(128) NOT NULL default '', transport varchar(128) NOT NULL default '', UNIQUE KEY domain (domain) );

在配置完數據庫以后,我們最好修改數據庫的配置文件,只允許本地訪問數據庫,提高安全性.
修改: /etc/my.cnf

bind-address=127.0.0.1

如果數據庫存儲在其他的服務器上面,我們這里的bind-address地址在后面配置Postfix的時候需要相應的修改.不過為了安全起見,最好還是不要讓數據庫能夠直接在外部可以訪問.

配置完成了以后,我們則可以重啟數據,使配置生效.

systemctl restart  mariadb.service

配置Postfix

配置完成了數據庫以后,我們就需要配置Postfix,讓其可以與MariaDB協同工作.因為Postfix尋找域名,用戶賬號等需要通過數據庫來完成,但是其本身是不知道如何查詢的,因而需要我們定制化.
下面的配置中,把mys123123替換成前面數據庫管理員設置的密碼

創建虛擬域名配置

創建:/etc/postfix/mysql-virtual_domains.cf

user = mail_admin
password = mys123123
dbname = mail
query = SELECT domain AS virtual FROM domains WHERE domain='%s'
hosts = 127.0.0.1

創建郵件轉發配置

創建:/etc/postfix/mysql-virtual_forwardings.cf

user = mail_admin
password = mys123123
dbname = mail
query = SELECT destination FROM forwardings WHERE source='%s'
hosts = 127.0.0.1

創建虛擬郵箱配置

創建: /etc/postfix/mysql-virtual_mailboxes.cf

user = mail_admin
password = mys123123
dbname = mail
query = SELECT CONCAT(SUBSTRING_INDEX(email,'@',-1),'/',SUBSTRING_INDEX(email,'@',1),'/') FROM users WHERE email='%s'
hosts = 127.0.0.1

創建電子郵件與文件映射

創建:/etc/postfix/mysql-virtual_email2email.cf

user = mail_admin
password = mys123123
dbname = mail
query = SELECT email FROM users WHERE email='%s'
hosts = 127.0.0.1

創建完畢以后修改權限以及分配用戶組.

chmod o= /etc/postfix/mysql-virtual_*.cf
chgrp postfix /etc/postfix/mysql-virtual_*.cf

同時,我們創建一個新的用戶組以及用戶,用來處理郵件.所有的虛擬郵箱,都會存在這個用戶的home目錄下.

groupadd -g 5000 vmail
useradd -g vmail -u 5000 vmail -d /home/vmail -m

接下來,我們對Postfix總體進行配置.把下面的mail.yusengy.info替換成你的hostname.如果你希望使用自己的SSL證書,則把/etc/pki/dovecot/private/dovecot.pem替換成你的證書路徑.

postconf -e 'myhostname = mail.yusengy.info'
postconf -e 'mydestination = localhost, localhost.localdomain'
postconf -e 'mynetworks = 127.0.0.0/8'
postconf -e 'inet_interfaces = all'
postconf -e 'message_size_limit = 30720000'
postconf -e 'virtual_alias_domains ='
postconf -e 'virtual_alias_maps = proxy:mysql:/etc/postfix/mysql-virtual_forwardings.cf, mysql:/etc/postfix/mysql-virtual_email2email.cf'
postconf -e 'virtual_mailbox_domains = proxy:mysql:/etc/postfix/mysql-virtual_domains.cf'
postconf -e 'virtual_mailbox_maps = proxy:mysql:/etc/postfix/mysql-virtual_mailboxes.cf'
postconf -e 'virtual_mailbox_base = /home/vmail'
postconf -e 'virtual_uid_maps = static:5000'
postconf -e 'virtual_gid_maps = static:5000'
postconf -e 'smtpd_sasl_type = dovecot'
postconf -e 'smtpd_sasl_path = private/auth'
postconf -e 'smtpd_sasl_auth_enable = yes'
postconf -e 'broken_sasl_auth_clients = yes'
postconf -e 'smtpd_sasl_authenticated_header = yes'
postconf -e 'smtpd_recipient_restrictions = permit_mynetworks, permit_sasl_authenticated, reject_unauth_destination'
postconf -e 'smtpd_use_tls = yes'
postconf -e 'smtpd_tls_cert_file = /etc/pki/dovecot/certs/dovecot.pem'
postconf -e 'smtpd_tls_key_file = /etc/pki/dovecot/private/dovecot.pem'
postconf -e 'virtual_create_maildirsize = yes'
postconf -e 'virtual_maildir_extended = yes'
postconf -e 'proxy_read_maps = $local_recipient_maps $mydestination $virtual_alias_maps $virtual_alias_domains $virtual_mailbox_maps $virtual_mailbox_domains $relay_recipient_maps $relay_domains $canonical_maps $sender_canonical_maps $recipient_canonical_maps $relocated_maps $transport_maps $mynetworks $virtual_mailbox_limit_maps'
postconf -e 'virtual_transport = dovecot'
postconf -e 'dovecot_destination_recipient_limit = 1'

修改Postfix配置,添加Dovecot服務.
修改:/etc/postfix/master.cf

dovecot   unix  -       n       n       -       -       pipe
    flags=DRhu user=vmail:vmail argv=/usr/libexec/dovecot/deliver -f ${sender} -d ${recipient}

submission以及smtps部分給反注釋了,讓這部分代碼生效.

配置截圖
配置截圖

重啟Postfix,至此,Postfix就基本配置好了.

systemctl enable postfix.service
systemctl start  postfix.service

Dovecot配置

修改:/etc/dovecot/dovecot.conf
這里把域名yusengy.info替換成自己配置的域名.

protocols = imap pop3
log_timestamp = "%Y-%m-%d %H:%M:%S "
mail_location = maildir:/home/vmail/%d/%n/Maildir

ssl_cert = </etc/pki/dovecot/certs/dovecot.pem
ssl_key = </etc/pki/dovecot/private/dovecot.pem

namespace {
    type = private
    separator = .
    prefix = INBOX.
    inbox = yes
}

service auth {
    unix_listener auth-master {
        mode = 0600
        user = vmail
    }

    unix_listener /var/spool/postfix/private/auth {
        mode = 0666
        user = postfix
        group = postfix
    }

user = root
}

service auth-worker {
    user = root
}

protocol lda {
    log_path = /home/vmail/dovecot-deliver.log
    auth_socket_path = /var/run/dovecot/auth-master
    postmaster_address = postmaster@yusengy.info
}

因為數據庫存儲有用戶的賬號密碼信息,Dovecot的職責之一就是驗證用戶的賬號密碼,因而我們還需要創建一個配置文件以讓Dovecot與數據庫進行交互.
老慣例,這里也是把密碼進行替換一下.
創建:/etc/dovecot/dovecot-sql.conf.ext

driver = mysql
connect = host=127.0.0.1 dbname=mail user=mail_admin password=mys123123
default_pass_scheme = CRYPT
password_query = SELECT email as user, password FROM users WHERE email='%u';

修改文件所屬的用戶組以及訪問權限

chgrp dovecot /etc/dovecot/dovecot-sql.conf.ext
chmod o= /etc/dovecot/dovecot-sql.conf.ext

設置Dovecot在開啟啟動并且啟動其服務

systemctl enable dovecot.service
systemctl start  dovecot.service

然后我們觀察一下var/log/maillog,確定現在Dovecot沒有錯誤

Dovecot日志
Dovecot日志

然后我們使用Telnet檢測一下pop3服務是否正常.

yum install telnet
telnet localhost pop3

如果你看到的和我看到的差不多,那么說明是pop3服務是正常的.


pop3服務
pop3服務

檢測Postfix

接下來則是檢測Postfix是否運行正常.

telnet localhost 25
ehlo localhost

如果連接成功,同時輸入EHLO命令有如下返回值,則Postfix是正常的.

Postfix測試
Postfix測試

創建用戶

接下來,我們在MariaDB中的郵箱中加入新的用戶,用作日常郵件的發送.
這里的用戶密碼不要使用明文存儲.

USE mail;
INSERT INTO domains (domain) VALUES ('yusengy.info');
INSERT INTO users (email, password) VALUES ('yusen@yusengy.info', ENCRYPT('123123'));
quit

到這個時候,我們的郵件服務器基本就已經搭建完成了,接下來只要使用MUA進行連接,就能像正常的郵件服務器一樣使用了.

MUA配置
MUA配置

嘗試給自己的QQ郵箱發件看看.是不是收到了?


郵件截圖
郵件截圖

如果被拒收或者在垃圾箱中,說明我們的郵件發送服務器信譽不夠,這個時候我們需要給我們的郵件服務器做一些條件,例如添加SPF, DKIM以及DMARC等,以提高郵件發送的成功率,當這些完成以后,基本能夠直接發送到收件箱了.具體可以參考這一篇文章
郵件服務器添加SPF,DKIM,DMARC,PTR

至此,一個郵件服務器的搭建就完成了,通過這一系列的操作,是否對于電子郵件協議又有了進一步的理解呢?
如果沒有在收件箱收到發送的郵件,可以在垃圾箱看看,或者看看是否退件了.這篇文章中我們沒有談到SPF, DKIM以及DMARC驗證的配置,因而有可能會被QQ郵箱退件的,畢竟現實中的郵件服務器還需要一系列的配置,以提高送達率.這些我在后面會開一篇文章專門講解.
如果MUA提示發件失敗,那么我們可以查看一下日志,分別在/var/log/maillog以及/home/vmail/dovecot-deliver.log,找到對應的錯誤,然后回到文章相應的地方看看是否配置錯了.如果還無法解決,可留言私信,我看到了會進行相應的解答.

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容