本系列第八篇: 使用 MySQL 管理 User, Domain 和 Alias
早在第二篇我們設定了 Dovecot 的 userdb 和 passdb 的靜態 Database。
但每次新增 Email 用戶都要 SSH 進 Server 修改 /etc/dovecot/passwd
都是太麻煩了。
這次把 Dovecot userdb 和 passdb 都放進 MySQL, 方便其他程式管理 Email 用戶。
Postfix 的 virtual_mailbox_domains
負責那些 domain 的 Email 可以轉交給 Dovecot LMTP
virtual_alias_maps
負責 Email 別名轉寄, 這裡也一併把它放進 MySQL 管理
Dovecot 部分
安裝 Dovecot MySQL 套件
apt install dovecot-mysql
修改 Dovecot 登入認證方法
vim /etc/dovecot/conf.d/10-auth.conf
# Uncomment !include auth-sql.conf.ext # Comment #!include auth-static.conf.ext
因為先前設定了 static uid/gid, 所以這裡 userdb 不用 sql
用 static 就可以了
vim /etc/dovecot/conf.d/auth-sql.conf.ext
passdb { driver = sql # Path for SQL configuration file, see example-config/dovecot-sql.conf.ext args = /etc/dovecot/dovecot-sql.conf.ext } userdb { driver = static args = uid=vmail gid=vmail }
建立 MySQL Database 及 Table
CREATE DATABASE `dovecot`; USE `dovecot`; CREATE TABLE `users` ( `username` varchar(128) NOT NULL, `domain` varchar(128) NOT NULL, `password` varchar(64) NOT NULL, `active` char(1) NOT NULL DEFAULT 'Y' ) ENGINE=InnoDB DEFAULT CHARSET=latin1;
建立 MySQL 用戶
CREATE USER 'dovecot'@'%' IDENTIFIED BY 'somepassword'; GRANT ALL PRIVILEGES ON `dovecot`.* TO 'dovecot'@'%'; FLUSH PRIVILEGES;
建立 Dovecot 用戶
INSERT INTO `users` (`username`, `domain`, `password`, `active`) VALUES ('tiger', 'domain.com', sha1('123456'), 'Y')
設定 MySQL 連線設定
為了方便測試, 先用 Unsalted SHA1 (Unsalted 比較不安全)
vim /etc/dovecot/dovecot-sql.conf.ext
driver = mysql connect = host=127.0.0.1 dbname=dovecot user=dovecot password=somepassword default_pass_scheme = SHA1
重啟 Dovecot 並測試
Reference: https://wiki.dovecot.org/AuthDatabase/SQL
Postfix 部分
安裝 Postfix MySQL 套件
apt install postfix-mysql
把 Virtual Mailbox 設定放進 MySQL
vim /etc/postfix/main.cf
, 修改 virtual_mailbox_domains
virtual_mailbox_domains = mysql:/etc/postfix/mysql-virtual-mailbox-domains.cf
vim /etc/postfix/mysql-virtual-mailbox-domains.cf
, 新增內容
user = dovecot password = somepassword hosts = 127.0.0.1 dbname = dovecot query = SELECT 1 FROM users WHERE domain = '%s'
把 Virtual Alias 設定放進 MySQL
建立 MySQL Table
USE `dovecot`; CREATE TABLE `aliases` ( `source` varchar(255) NOT NULL, `destination` varchar(255) NOT NULL ) ENGINE=InnoDB DEFAULT CHARSET=latin1;
vim /etc/postfix/mysql-virtual-alias-maps.cf
, 新增內容
user = dovecot password = somepassword hosts = 127.0.0.1 dbname = dovecot query = SELECT destination FROM aliases WHERE source = '%s'
重啟 Postfix 並測試
Bonus: Catch-all Address
這裡特別說明一下 Catch-all Address 的設定方法
Catch-all Address 的典型 Use Case 是
當某個 Domain 的 User 不存在的時候
把 Email 轉寄到特定地址 (例如 [email protected] => [email protected])
這功能在我們未轉用 Dovecot LMTP 前
只要設定 virtual_alias_maps 就可以了, 例如:
@domain.com [email protected]
但因為 Postfix 處理 virtual_alias_maps 的優先級高於 virtual_transport
所有這樣設定後會發現 *@domain.com 不管存在不存在都轉寄到 [email protected]
這顯然不是我們想要的結果
由於 virtual_alias_maps 中
[email protected] 的優先級有高於 @domain.com
所以 virtual_alias_maps 只要有
[email protected] [email protected]
就可以達到我們預期的效果, 但我們沒有理由把 users table 全部都加一份到 aliases table 吧
幸好 virtual_alias_maps 可以用多個 Table, 於是我們
vim /etc/postfix/mysql-email2email.cf
user = dovecot password = somepassword hosts = 127.0.0.1 dbname = dovecot query = SELECT CONCAT(username, '@', domain) AS email FROM users WHERE username='%u' AND domain = '%d'
vim /etc/postfix/main.cf
, 再次修改 virtual_mailbox_domains
virtual_alias_maps = mysql:/etc/postfix/mysql-virtual-alias-maps.cf,mysql:/etc/postfix/mysql-email2email.cf
重啟 Postfix 並測試
Reference: https://workaround.org/ispmail/wheezy/connecting-postfix-to-the-database
(因為 Database 結構不同, Query 經過修改)
安全性設定
因為 MySQL 的 Password 在 mysql-*.cf 裡面, 為了安全計, 把它們設定只給 postfix 讀取
chgrp postfix /etc/postfix/mysql-*.cf chmod u=rw,g=r,o= /etc/postfix/mysql-*.cf