Ubuntu Postfix Mail Server 設定筆記 (八) 使用 MySQL 管理 User, Domain 和 Alias

本系列第八篇: 使用 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 轉寄到特定地址 (例如 whatever@domain.com => tiger@domain.com)

這功能在我們未轉用 Dovecot LMTP 前
只要設定 virtual_alias_maps 就可以了, 例如:

@domain.com tiger@domain.com

但因為 Postfix 處理 virtual_alias_maps 的優先級高於 virtual_transport
所有這樣設定後會發現 *@domain.com 不管存在不存在都轉寄到 tiger@domain.com
這顯然不是我們想要的結果

由於 virtual_alias_maps 中
tiger@domain.com 的優先級有高於 @domain.com
所以 virtual_alias_maps 只要有
tiger@domain.com tiger@domain.com
就可以達到我們預期的效果, 但我們沒有理由把 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

Leave a Reply

Your email address will not be published.

This site uses Akismet to reduce spam. Learn how your comment data is processed.