delete from hateblo.jp where 1=1;

タイトルに意味はありません。

複数ドメイン対応のdovecotを構成する

対象

dovecotをマルチドメイン対応し、それぞれのドメインごとに権限を分離したい場合の内容です。

ソフトウエア構成

このページで紹介する設定

このページで紹介しない情報

  • PostfixAdminに準拠した設定等は紹介しません
  • MySQLの構築方法は紹介しません
  • postfixとの連携はしません(気が向いたら追記するかも)
  • firewallの設定はしません
  • IMAP4sやPOP3sの設定は紹介しません
  • SELinuxの設定は紹介しません(virtualmapsを使用するため、広範囲の許可が必要です、ポリシーのビルド必須)

準備

sudo yum install dovecot-mysql telnet

telnetdovecotの接続確認(IMAP)に使用します。別端末で行う場合は不要です。

MySQL

DBを作成する

DB名はmailserverとする。
ユーザー名はpostfixで、パスワードはpasswordとしておく。(本番環境では必ず違うやつにしてください)

CREATE DATABASE mailserver;
CREATE USER 'postfix'@'%' IDENTIFIED BY 'password';
GRANT USAGE ON * . * TO 'postfix'@'%' IDENTIFIED BY 'password'
 WITH MAX_QUERIES_PER_HOUR 0 MAX_CONNECTIONS_PER_HOUR 0 MAX_UPDATES_PER_HOUR 0 MAX_USER_CONNECTIONS 0 ;
GRANT ALL PRIVILEGES ON `mailserver` . * TO 'postfix'@'%';
テーブル等を作成

必要に応じて項目を増減させてください。
ER図とか外部キーやINDEXは今回、割愛させていただきたく。

--DROP TABLE domain;
--DROP TABLE email;

create table domain (
	id INTEGER AUTO_INCREMENT PRIMARY KEY
	,server_id INTEGER
	,domain VARCHAR(128)
	,dir VARCHAR(128)
	,uid INTEGER
	,uid_name VARCHAR(64)
	,gid INTEGER
);

create table email (
	id BIGINT AUTO_INCREMENT PRIMARY KEY
	,server_id INTEGER
	,domain_id INTEGER
	,name VARCHAR(128)
	,dir VARCHAR(128)
	,password VARCHAR(256)
);
テストデータの挿入

メールサーバーにユーザーとグループを作成する。

sudo groupadd vmail -g 5000
sudo adduser vuser1 -u 5001 -g 5000 -m -s /sbin/nologin

作成するSQLに必ずuid,gidが一致するように作成してください。

INSERT INTO `mailserver`.`domain` (`id`, `server_id`, `domain`, `dir`, `uid`, `uid_name`, `gid`)
 VALUES (NULL, '1', 'mailtest.home.lan', 'mailtest.home.lan', '5001', 'vuser1', '5000');
INSERT INTO `mailserver`.`email` (`id`, `server_id`, `domain_id`, `name`, `dir`) VALUES (NULL, '1', '1', 'root', 'root');
ビューの作成

ここをpostfixが見に行く

CREATE OR REPLACE VIEW mailbox AS
SELECT e.id
, e.server_id
, e.domain_id
, e.name
, d.domain
, concat(e.name,'@',d.domain) AS email
FROM email AS e
INNER JOIN domain AS d
ON e.domain_id = d.id
AND e.server_id = d.server_id
;


ここをdovecotが見に行く

CREATE OR REPLACE VIEW mailusers AS
SELECT e.id
, e.server_id
, e.domain_id
, e.name
, d.domain
, d.uid
, d.uid_name
, d.gid
, concat('{PLAIN-MD5}',MD5(e.password)) AS password
, concat(d.dir,'/',e.dir) AS home
, concat(e.name,'@',d.domain) AS email
FROM email AS e
INNER JOIN domain AS d
ON e.domain_id = d.id
AND e.server_id = d.server_id
;
注意点

password列については、本来MD5でハッシュ化されたデータを格納すべきです。
パスワードスキーマ を参照して「{スキーマ名}ハッシュ化されたパスワード文字列」とすることで、dovecotがどの処理を使ってパスワードの一致確認を行えばいいのか判断してくれます。上記例では、「{PLAIN-MD5}1a1dc91c907325c69271ddf0c944bc72」のようなデータになります。
[id:indication:20100211:1265892873]にもあるように他バックエンドの対応スキーマ等を配慮した上でスキーマを決定することを推奨します。
なお、平文(PLAIN)でパスワードをDBへ保存する愚かな行為は、来世に渡って負債を残すので、強く拒否いたします。

dovecot

CentOS5基準で設定します。

メインの設定

基本的な設定を行います。対応するプロトコル、待ち受けるIPアドレス等を設定します。

diff /etc/dovecot/dovecot.conf.org /etc/dovecot/dovecot.conf 
20c20
< #protocols = imap pop3 lmtp
---
> protocols = imap pop3 lmtp
26c26
< #listen = *, ::
---
> listen = *, ::
認証設定

認証キャッシュ(auth_cache_size)をとりあえず、10M程度確保し、
デフォルト設定のシステムでの認証ではなく、sqlへの認証へ変更します。

diff /etc/dovecot/conf.d/10-auth.conf.org /etc/dovecot/conf.d/10-auth.conf
13c13
< #auth_cache_size = 0
---
> auth_cache_size = 10M
19c19
< #auth_cache_ttl = 1 hour
---
> auth_cache_ttl = 1 hour
97c97
< auth_mechanisms = plain
---
> auth_mechanisms = plain cram-md5
119,120c119,120
< !include auth-system.conf.ext
< #!include auth-sql.conf.ext
---
> #!include auth-system.conf.ext
> !include auth-sql.conf.ext

認証結果のキャッシュ (ただしv1.x系)より引用

認証キャッシュに関する設定は、以下のようになります:

 * 'auth_cache_size': 認証キャッシュサイズをキロバイトで指定し、0 は無効と
   なります(デフォルト)。通常、passdb のキャッシュ情報は 50 バイトほどで、
   userdb キャッシュ情報は、ユーザやパスワード検索の応答からの情報量に応じ
   て、100〜200 バイトほどになります。
 * 'auth_cache_ttl': キャッシュ情報の保存時間を秒で指定します。ここで指定
   した秒より前に作られた場合、(内部での失敗の場合以外では)、キャッシュ情
   報は使われなくなります。情報はキャッシュがいっぱいになったか、新しい情
   報が追加されたときのみ、削除されます。
 * 'auth_cache_negative_ttl': (v1.1 以上のみ) もし passdb もしくは userdb
   検索が何も返さなかった場合(例えば、ユーザが存在しないなどで)、それを同
   様に否定的情報としてキャッシュに保存します。この設定は、否定的情報用の
   別の TTL を与えることを可能にします。0 は完全に否定的キャッシュを無効に
   します。
メールの取り扱いについて設定

Maildir形式にする設定、および、ユーザーIDの下限値を設定しておく。

diff /etc/dovecot/conf.d/10-mail.conf.org /etc/dovecot/conf.d/10-mail.conf
24c24
< #   mail_location = maildir:~/Maildir
---
> mail_location = maildir:~/Maildir
167c167
< #first_valid_uid = 500
---
> first_valid_uid = 500
SQLの設定

/etc/dovecot/dovecot-sql.conf.ext
※設定の場所に注意(新規作成)

# NOTE: '\' line splitting works only with v1.1+# The mysqld.sock socket may be in different locations in different systems
driver = mysql
# Use "host= ... pass=foo#bar" if your password has '#' character
#connect = host=/var/run/mysqld/mysqld.sock dbname=mails user=admin password=pass
connect = host=192.168.1.1 dbname=mailserver user=postfix password=password

password_query = SELECT email AS user, password FROM mailusers WHERE name = '%n' AND domain = '%d'
# returning mail overrides mail_location setting for SQL users.
user_query = SELECT concat('maildir:/home/',uid_name,'/Maildir/',home) AS mail, uid, gid FROM mailusers WHERE name = '%n' AND domain = '%d'

user_queryのmail列についてはファイル等を作成する場所を指定する。
基本的にビューを参照させて、メインテーブルの構成変更を吸収できるようにしておくのがポイント。
サーバーの構成に関わるところについては、上記設定で吸収できるようにしておく。

テスト

準備完了

サービスを再起動する

sudo service dovecot restart
動作確認

telnetで接続して、動作を確認する

telnet localhost 110
USER root@mailtest.home.lan
PASS password
STAT
LIST
QUIT

参考:実行結果

Trying ::1...
Connected to localhost.
Escape character is '^]'.
+OK Dovecot ready.
USER root@mailtest.home.lan
+OK
PASS password
+OK Logged in.
STAT
+OK 0 0
QUIT
+OK Logging out.
Connection closed by foreign host.

参考文献