背景
在上一篇講到了安裝完postfix之后,我們再服務器上有有了收發(fā)郵件的能力。 然而因為我們只是做了一點微小的工作,功能并不夠強大。只能使用root@example.com這個郵箱來進行收發(fā)。因為這時候郵件地址還是和linux服務器上的用戶一一對應的。并不能滿足筆者的需求。筆者需要的是能夠隨意使用在本域下的任意郵箱的呀,所以本文就來探究如何在前篇的基礎上擴充郵件服務,使之具有承載虛擬用戶的能力。
原理分析
postfix只是個MTA服務軟件,并不是一個真正的MDA軟件。postfix只是簡單將收到的郵件發(fā)給對應用戶組下的郵件目錄中,以文件形式存儲下來。如果郵箱地址對應的不是一個linux存在的用戶,那么郵件就會被退回。如果需要很多虛擬用戶的話,就需要另尋他路了,這里我們用dovecot來充當MDA的角色,來進行對虛擬用戶的操縱,并投遞到相應虛擬用戶的目錄中。而虛擬用戶的賬號、別稱數據需要mysql來進行存儲。既然用mysql來進行存儲,就要有賬號管理的應用(注意dovecot只是從數據庫中讀取虛擬用戶的數據傳遞給postfix使用,并不能很方便的創(chuàng)建和管理虛擬用戶的數據),這時候我們就可以使用postfixadmin來進行管理了。
因此本文所涉及到的是4個應用
postfix(MTA) 負責郵件的傳輸
dovecot(MDA) 負責從mysql中讀取數據,轉發(fā)給postfix提供虛擬用戶的數據用以路由與驗證。
mysql(database) 負責存儲用戶數據。
postfixadmin 負責賬號的創(chuàng)建與管理,只是存儲數據庫的數據,并不參與到郵件的轉發(fā)工作中。
操作步驟
- step1 配置服務器用戶
為了安全起見,我們要新配置一個用戶來管理這個郵件的收發(fā),我們叫vmail好了。
$ groupadd -g 5000 vmail #組號為5000,組名為vamil
$ useradd -u 5000 -g vmail -s /usr/bin/nologin -d /home/vmail -m vmail #用戶號為5000,屬于用戶組vmail,沒有登錄shell的權限,主目錄為/home/vmail并自動創(chuàng)建,最后這個用戶就叫vamil了。
- step2 使用postfixadmin配置虛擬域名以及虛擬用戶
$ apt-get install postfixadmin
安裝完以后,phpadmin就會彈出一個配置向導來給我們進行配置。跟著操作來就好了,一般用默認配置就好了。postfixadmin會在數據庫中創(chuàng)建一個名字為postfixadmin的用戶,同時創(chuàng)建一個相應的名字為postfixadmin的數據庫。接著其就會自己進行配置和初始化了。
可以在安裝記錄的提示中看到數據庫創(chuàng)建的提示和配置文件所在目錄
granting access to database postfixadmin for postfixadmin@localhost: success.
Creating config file /etc/dbconfig-common/postfixadmin.conf with new version
Creating config file /etc/postfixadmin/dbconfig.inc.php with new version
這樣我們就基本安裝好了postfixadmin,接著我們就可以從web的方式在網頁上進行配置了。postfixadmin的目web配置文件在/usr/share/postfixadmin/目錄下,我們要把其映射web服務器的可訪問目錄下。如果是用apache那么就自動配置好了,只要訪問yourdomain/postfixadmin/index.php就好了,然而筆者用的nginx,所以要自己額外映射一發(fā)。我們新開一個端口映射到域名下,那么我們訪問https://yourdomain:1234/index.php就可以了
在/etc/nginx/sites-available目錄下新建一個yourdomain_1234_postfixadmin
server {
listen 1234;
listen [::]:1234;
server_name yourdomain;
root /usr/share/postfixadmin;
index index.html;
location ~ \.php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/run/php/php7.0-fpm.sock;
}
location / {
try_files $uri $uri/ =404;
}
}
然后配置一下重啟nginx就好了
$ cd /etc/nginx/sites-enabled
$ ln -s ../sites-available/st0rm23.com_3789_postfixadmin
$ nginx -t
$ /etc/init.d/nginx restart
完了以后,訪問一下先訪問一下https://yourdomain:1234/setup.php,看是否都配置成功。
筆者就悲傷的發(fā)現mysql這一塊失敗了
Error: Can't connect to database
Please edit the $CONF['database_*'] parameters in config.inc.php.
看了一下原因,原來是我使用的是mysqli而不是mysql,然后我在dbconfig.inc.php里面改了一下type類型就就可以正常使用了。
修好以后,又發(fā)現初始化數據庫的時候執(zhí)行失敗了,找了一下原因,是因為postfixadmin的bug,日期的地方默認值填的是0,然而數據庫版本使用的strict模式,就執(zhí)行失敗了(后來postfixadmin修了這個bug,然而筆者做的時候,這個bug修好了只在issue里面,還沒有release出來)。于是筆者就手工修改了mysql去掉了嚴格模式。
在/etc/mysql/conf.d/目錄下新建一個disable_strict_mode.cnf文件,輸入
[mysqld]
sql_mode=IGNORE_SPACE,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION
保存后,使用/etc/init.d/mysql restart重啟加載配置就好了。這樣重新刷新setup.php文件就可以發(fā)現數據庫都加載好了。配置好密碼后,就愉快地訪問你的鏈接吧https://yourdomain:1234/index.php。
-
setup3 使用postadmin的web界面進行配置虛擬用戶
在經過上一步之后,我們就可以從web界面進行配置了,那么登錄到https://yourdomain:1234/index.php就可以看到下述界面。
QQ截圖20161126115438.png
進去之后可以添加域和虛擬用戶。先創(chuàng)建一個hello@example.com的賬號進行后續(xù)使用 setup4 配置dovecot以及相應的sasl
我們如果要接受來自外域的郵件,我們還要配置一個dovecot來管理外部郵件到虛擬用戶的映射。注意在前幾步中,我們只是添加postfixadmin來管理虛擬用戶,然而郵件是外域接受并傳遞到虛擬用戶這個過程并沒有被實現。所以我們就需要用dovecot來實現這個過程。
先安裝一下dovecot相關的包
$ apt-get install dovecot-common
$ apt-get install dovecot-pop3d
$ apt-get install dovecot-imapd
$ apt-get install dovecot-mysql
然后配置dovecot的配置文件/etc/dovecot/dovecot.conf,注意如果有舊的的dovecot.conf,那么把舊的文件刪掉,并不需要舊的那個了
protocols = imap pop3
auth_mechanisms = plain
passdb {
driver = sql
args = /etc/dovecot/dovecot-sql.conf
}
userdb {
driver = sql
args = /etc/dovecot/dovecot-sql.conf
}
service auth {
unix_listener /var/spool/postfix/private/auth {
group = postfix
mode = 0666
user = postfix
}
user = root
}
mail_home = /home/vmail/%d/%n
mail_location = maildir:~
ssl_cert = </etc/ssl/private/yourca.crt
ssl_key = </etc/ssl/private/yourca.key
接著配置一下/etc/dovecot/dovecot-sql.conf,讓dovecot能夠訪問數據庫
driver = mysql
connect = host=localhost dbname=postfixadmin user=postfixadmin password=password
# It is highly recommended to not use deprecated MD5-CRYPT. Read more at http://wiki2.dovecot.org/Authentication/PasswordSchemes
default_pass_scheme = SHA512-CRYPT
# Get the mailbox
user_query = SELECT '/home/vmail/%d/%n' as home, 'maildir:/home/vmail/%d/%n' as mail, 5000 AS uid, 5000 AS gid, concat('dirsize:storage=', quota) AS quota FROM mailbox WHERE username = '%u' AND active = '1'
# Get the password
password_query = SELECT username as user, password, '/home/vmail/%d/%n' as userdb_home, 'maildir:/home/vmail/%d/%n' as userdb_mail, 5000 as userdb_uid, 5000 as userdb_gid FROM mailbox WHERE username = '%u' AND active = '1'
# If using client certificates for authentication, comment the above and uncomment the following
#password_query = SELECT null AS password, %u AS user
注意,這里我用的是private/auth這一套,有些文檔使用的是auth-client那一套,然而我并沒有成功,總是提示找不到對應的文件。
- step5 配置postfix,使得postfix通過dovecot來代理郵件到虛擬用戶的分發(fā)
配置/etc/postfix/main.cf,在末尾加上
relay_domains = $mydestination
virtual_alias_maps = proxy:mysql:/etc/postfix/virtual_alias_maps.cf #數據庫的連接文件,后面要創(chuàng)建的
virtual_mailbox_domains = proxy:mysql:/etc/postfix/virtual_mailbox_domains.cf #數據庫的連接文件,后面要創(chuàng)建的
virtual_mailbox_maps = proxy:mysql:/etc/postfix/virtual_mailbox_maps.cf #數據庫的連接文件,后面要創(chuàng)建的
virtual_mailbox_base = /home/vmail
virtual_mailbox_limit = 512000000
virtual_minimum_uid = 5000
virtual_transport = virtual
virtual_uid_maps = static:5000 #這里就是之前創(chuàng)建的vmail的uid 5000
virtual_gid_maps = static:5000
local_transport = virtual
local_recipient_maps = $virtual_mailbox_maps
transport_maps = hash:/etc/postfix/transport
smtpd_sasl_auth_enable = yes
smtpd_sasl_type = dovecot
smtpd_sasl_path = private/auth #這里要注意,是和上面dovecot配置的時候緊密相關的,通過這個路徑才能進行sasl的認證。
smtpd_recipient_restrictions = permit_mynetworks, permit_sasl_authenticated, reject_unauth_destination
smtpd_relay_restrictions = permit_mynetworks, permit_sasl_authenticated, reject_unauth_destination
smtpd_sasl_security_options = noanonymous
smtpd_sasl_tls_security_options = $smtpd_sasl_security_options
smtpd_tls_security_level = may
smtpd_tls_auth_only = yes
smtpd_tls_received_header = yes
smtpd_tls_cert_file = /etc/ssl/private/www.st0rm23.com.crt
smtpd_tls_key_file = /etc/ssl/private/www.st0rm23.com.key
smtpd_sasl_local_domain = $mydomain
broken_sasl_auth_clients = yes
smtpd_tls_loglevel = 1
同時完成/etc/postfix/virtual_alias_maps.cf、/etc/postfix/virtual_mailbox_domains.cf、/etc/postfix/virtual_mailbox_maps.cf三個文件的數據庫配置。
/etc/postfix/virtual_alias_maps.cf
user = postfixadmin
password = password #你的密碼
hosts = localhost
dbname = postfixadmin
table = alias
select_field = goto
where_field = address
/etc/postfix/virtual_mailbox_domains.cf
user = postfixadmin
password = password #你的密碼
hosts = localhost
dbname = postfixadmin
table = domain
select_field = domain
where_field = domain
/etc/postfix/virtual_mailbox_maps.cf
user = postfixadmin
password = password #你的密碼
hosts = localhost
dbname = postfixadmin
table = mailbox
select_field = maildir
where_field = username
這樣用/etc/init.d/postfix restart 重啟完postfix后就可正式生效了。我們可以用公共的郵箱向在step3中建立的虛擬郵箱hello@example.com用戶發(fā)一封郵件。就會發(fā)現郵件可以成功發(fā)送了。
碰到的問題
一路上還是碰到不少問題的,特別是搭建dovecot的時候,由于很陌生,各個文檔的說法都不一致碰到過很多問題。這里有一個很有效的調試方法,發(fā)一封郵件,然后看/var/log/mail.log下的日志
$ tail /var/log/mail.log -n 20
很明顯能夠看到失敗的原因,這里分享幾個錯誤和解決的方法。
- postfix/smtpd[19476]: warning: SASL: Connect to /var/run/dovecot/auth-client failed: No such file or directory
這個我也不知道為什么postfix和dovecot在auth-client的文件上找不到。后來我就改成了private/auth的接入方式(理論上兩種方式都可以的,只是兩個程序內部的管道數據流罷了)。就是在/etc/dovecot中unix_listener的地方改成/var/spool/postfix/private/auth,同時在/etc/postfix/main.cf的smtpd_sasl_path改成private/auth。重啟兩個服務就可以了 - dovecot: auth: Fatal: Unknown database driver 'mysql'
這個是由于沒有安裝dovecot-mysql組件的原因,用aptget-install安裝一下就好了 - Temporary lookup failure
這個導致的原因多種多樣,我的原因是因為我在/etc/postfix/main.cf中同時開了virtual_transport和transport_maps。前者是虛擬轉發(fā),轉發(fā)到虛擬用戶,而后者是真實地路由到其他的服務器。所以把后者注釋掉了,就可正常接收郵件了。否則由于我沒有transport.db文件,就會報錯收不到郵件。
