目次
Postfix+dovecot (POP/IMAPサーバ)関連
Postfix+dovecotでSMTP/POP/IMAPサーバを構築する際のメモ。
参考
方針
メールサーバにPostfixを利用し、クライアントへの吸い上げにdovecotを利用する。
- UNIXアカウントが必要ないメールアカウントはバーチャルメールボックスとする
- UNIXユーザはOSのユーザ情報を利用したうえで、同一ドメイン上のバーチャルユーザと共存させる
Postfix/dovecotのインストール
標準的なUSEフラグでよい。ただし、sieveで振り分けを行うためにdovecotにsieve、SMTP-AUTHにdovecotの認証を利用するためにPostfixにdovecot-saslをUSEフラグに設定。
#USEフラグ(/etc/portage/package.use) net-mail/dovecot sieve mail-mta/postfix dovecot-sasl
>emerge -av postfix dovecot
Postfixの設定
とりあえず一般的な設定をしておく。
メールボックスの形式を、maildir形式に変更しておく(必要ない?)
#/etc/postfix/main.cf home_mailbox = .maildir/
ローカルヘッダの隠蔽
メールを送信する際に、接続元MUAのIPアドレスやホスト名がReceivedヘッダに記録される。メールの経路情報として重要ではあるが、内部のネットワーク構成をあまり知られたくないので、(メールシステムの仕様や理念からは少し外れるかもしれないが)ヘッダを削除しておく。
Postfixのheader_checksで該当するヘッダを削除すればよい。ただし、
# /etc/postfix/main.cf header_checks = regexp:/etc/postfix/header_checks # /etc/postfix/header_checks /^Received: from.*192\.168\..*/ IGNORE
/etc/postfix/header_checksファイルには正規表現で条件を書き、対応するアクションを指定する。ここでは、マッチしたヘッダを削除する。
ただし、条件にマッチしたヘッダがすべて削除されるので、場合によっては外からのメールのヘッダも消えるので注意すること。たとえば、上記の場合、「192.168…」がReceivedヘッダに含まれていれば削除されてしまう。外出先から送信する場合などは、送信ホストのアドレスが記録されるので、これを消したいのだが、、、自分が接続した場合だけ削除する方法がわからない。
aliasによる簡易的なバーチャルメールボックス
バーチャルユーザのメールボックスについては、いくつか実現方法がある。今回はaliasでファイルにmaildir形式で配送することで実現する。
バーチャルメールボックスのベースディレクトリを作成(任意の場所)。
mkdir /var/spool/virtual_mailbox
ベースディレクトリ以下に、バーチャルユーザのメールボックスとなるディレクトリを作成。所有者を、Postfixのmain.cfで指定しているdefault_privsに変更する。default_privsは、Postfixがローカル配送する際のユーザ。パーミッションを所有者のみにしておく。
mkdir ${basedir}/pop.account chown nobody:nobody ${basedir}/pop.account chmod 700 ${basedir}/pop.account
バーチャルユーザの作成
特別な設定をするわけではなく、システムのaliasでファイルに配送する。
/etc/aliases
pop.account: /var/spool/virtual_mailbox/pop.account/
pop.account@example.com宛のメールが、/var/spool/virtual_mailbox/pop.account/に配送される。ディレクトリを指定することで、maildir形式で保存される。
Postfixでバーチャルメールボックスを利用する
上記のようにaliasで直接ディレクトリに配送するのではなく、Postfixのバーチャルメールボックスで仮想ユーザを作成する。
バーチャルドメインを利用することで、ローカル配送時に外部コマンドを利用する際などに便利になる。aliasを利用すると、そのままローカル配送されるため、mailbox_commandなどで外部コマンドに渡せない。単にPOPアカウントを作成する場合は、振り分けなどはローカルの役割であるが、imapではサーバサイドで振り分けなどができることが好ましい。バーチャルメールボックスにすれば、dovecotなど外部の配送コマンドを利用できる。
方針
ここでは内部的に仮想メールボックス用の架空のバーチャルドメインを作成し、ローカルユーザがないメールアカウントを作成する際に、ローカルのaliasで架空のバーチャルドメインに転送して、バーチャルドメイン側のメールボックスで受け取ることで、ローカルユーザとバーチャルユーザを共存させる。
virtual_mailbox_domains = virtual.example.jp #架空のドメイン:外部から直接受信はしない virtual_mailbox_base = /var/spool/virtual_mailbox #バーチャルメールボックスの起点となるディレクトリ virtual_mailbox_maps = hash:/etc/postfix/virtual_account #バーチャルメールボックスのマップ virtual_minimum_uid = 100 #これ以上のuidでなければ配送できない:セキュリティ設定 virtual_uid_maps = static:65534 #配送に利用するユーザ:固定でnobodyを利用 virtual_gid_maps = static:65534 #配送に利用するグループ:固定でnobodyを利用 virtual_transport = dovecot #バーチャルドメインで配送に利用するコマンド:dovecotで配送する事でsieveを利用する dovecot_destination_recipient_limit = 1 #おまじない? #virtual_alias_maps = hash:/etc/postfix/virtual #今回はバーチャルドメインのaliasは特に必要ない virtual_mailbox_limit = 0 #バーチャルメールボックスの容量制限:ローカルより小さいと警告が出るので設定:無制限 relay_domains = #virtual_mailbox_domainsを記載すると警告が出るので空にする
「virtual.example.jp」という架空ドメインを作成し、バーチャルメールボックスはここで全て管理する。このドメインには、外部から直接メールを受け取らない。ローカルのaliasからのみ転送することにする。
バーチャルメールボックスの設定
/etc/postfix/virtual_accountに以下の様にアカウントとディレクトリの対応情報を作成する
account1@virtual.example.jp account1/maildir/ account2@virtual.example.jp account2/foo/
起点となるディレクトリ以下のどのディレクトリにメールを格納するかを決める。ディレクトリはあらかじめ作成しておく必要があるかもしれない。
ファイルを作成したら、以下のコマンドでデータベースを更新する。
> postmap /etc/postfix/virtual_account
これで、/etc/postfix/virtual_account.dbが作成される。
dovecotの設定
/etc/dovecot以下のファイルを編集。
/etc/dovecot/dovecot.conf
protocols = pop3
対応するプロトコルを指定する。pop3s等は旧バージョンの場合。新しいバージョンからは、inet_listenerでpop3の接続設定として設定する。
その他の設定はdovecot.confから、conf.dディレクトリ以下の.confファイルを読み込む。
${prefix}/conf.d/10-master.conf
service pop3-login { inet_listener pop3 { port = 0 } inet_listener pop3s { #port = 995 #ssl = yes } }
popの待ち受けポートとして、平文の標準ポートを閉じて、SSLポート(995番)のみにする。port=0を指定するとポートが閉じられる。
${prefix}/conf.d/10-auth.conf
disable_plaintext_auth = yes
デフォルトでプレーンテキストは許可されないが念のため明示的に禁止する。
認証の詳細は、10-auth.confから別の設定ファイルを読み込む(ファイル末尾に記載)。必要に応じてコメントアウトし、読み込みファイルを編集する。
認証関係の設定ファイル
- ${prefix}/conf.d/auth-deny.conf.ext
- ユーザごとにログインを制限する
- argsに指定されているファイルにログインを禁止するユーザを列挙する
- ${prefix}/conf.d/auth-system.conf.ext
- システムのユーザ情報を認証に利用するための設定
- 標準はpam経由で認証するようになっている
- ${prefix}/conf.d/auth-passwdfile.conf.ext
- システムのユーザ情報以外の仮想的なユーザ情報を利用するための設定
- 後述
UNIXアカウントのないヴァーチャルユーザがPOPやIMAPでログインするために、auth-passwdfile.conf.extを編集して、システムとは別のユーザ/パスワードマップを作成する。実現方法は複数あるが、ここでは/etc/passwdファイルに準じたファイルを作成する。
フォーマット
user:password:uid:gid:(gecos):home:(shell):extra_fields
パスワードは以下のコマンドで生成できる。
doveadm pw -s CRAM-MD5 doveadm pw -s SHA512-CRYPT
多くのメーラではCRAM-MD5での暗号化に対応しているので、CRAM-MD5がよいかもしれない。dovecotのCRAM-MD5はパスワードを平文で保持する必要はない。他の暗号化方式だと、メーラが対応していないのでパスワードは平文で送られることになる。SSLで経路を保護すれば問題ないが、CRAM-MD5でさらにSSLを使うことにする。CRAM-MD5は、パスワードをサーバとクライアント間でやり取りする際の暗号化で、SSLはその経路の暗号化。
${prefix}/conf.d/auth-passwdfile.conf.ext
passdb { driver = passwd-file # args = scheme=SHA512-CRYPT username_format=%u /etc/dovecot/virtual_passwd #←SHA512で暗号化する場合 args = username_format=%u /etc/dovecot/vmbox_passwd } userdb { driver = passwd-file args = username_format=%u /etc/dovecot/virtual_passwd }
/etc/dovecot/virtual_passwdに上記フォーマットでユーザ情報を作成する。
pop.account:${PASSOWRD}:nobody:nobody::/var/spool/virtual_mailbox::userdb_mail=pop.account
ホームディレクトリにあたるフィールドはメールボックスのベースディレクトリを指定する。extra_fieldsに追加情報として、メールボックスのディレクトリを指定する。userdb_mailにユーザのメールボックスとなるベースディレクトリ以下のディレクトリを指定する。
SSL関係
SSLで経路を保護する設定。証明書を用意する必要があるが、ここでは簡易的自己書名の証明書を作成して用いる。
${prefix}/conf.d/10-ssl.conf
ssl = required ssl_cert = </etc/ssl/dovecot/server.pem ssl_key = </etc/ssl/dovecot/server.key
ssl=requiredで、SSLを必須にする。ssl=yesにすると、プレーンテキストもトライする。
ssl_certに証明書、ssl_keyに秘密鍵を指定する。
SSL証明書などの生成
Gentooの場合、dovecotをインストールした段階で、/etc/ssl/dovecot以下に自動的に証明書類が生成される。
OpenSSLを利用して手動で生成してもよいが、専用のスクリプトが用意されているのでそれを利用することもできる。
bzcat /usr/share/doc/dovecot-${varsion}/dovecot-openssl.cnf.bz2 > dovecot-openssl.cnf bzcat /usr/share/doc/dovecot-${varsion}/mkcert.sh.bz2 > mkcert.sh
パッケージに含まれている、証明書生成スクリプトmkcert.shと、その設定ファイルdovecot-openssl.cnfを同一ディレクトリに解凍し編集する。
mkcert.shは、標準で/etc/ssl/dovecot以下に、秘密鍵、証明書リクエストファイル、証明書などが生成される。出力先を変更する場合は、スクリプトを修正すること。
dovecot-openssl.cnf
[ req ] default_bits = 1024 encrypt_key = no distinguished_name = req_dn x509_extensions = cert_type prompt = no [ req_dn ] # country (2 letter code) C=JP # State or Province Name (full name) ST=Tokyo # Locality Name (eg. city) L=Tokyo # Organization (eg. company) O=RCPS # Organizational Unit Name (eg. section) OU=RCPS ADMIN # Common Name (*.example.com is also possible) CN=master.rcps.jp # E-mail contact emailAddress=xxxxx@xxxx.jp [ cert_type ] nsCertType = server
encrypt_key = noで、パスフレーズなしの秘密鍵を生成する?
デバッグなど
${prefix}/conf.d/10-logging.confファイルでデバッグを有効にすると、ログファイルにデバッグ情報が出力される。
Postfix+dovecotによるSMTP AUTH
Postfixをdovecot-saslを有効にしてビルド
USE=dovecot-sasl
/etc/postfix/master.cf
submission inet n - n - - smtpd #コメントアウトを外してサブミッションポートでも待ち受けるようにする。
/etc/postfix/main.cf
#SMTP-AUTH設定 smtpd_sasl_auth_enable = yes #saslでの認証を許可 smtpd_sasl_authenticated_header = no #ヘッダにSMTP AUTHの認証情報を書き込むか smtpd_sasl_local_domain = $myhostname #ローカルドメインの指定 broken_sasl_auth_clients = yes #Outlookのようなクライアント向け #mynetwork、saslで認証されたホストを許可し、認証されていないホストは拒否する ## 2.10以降はsmtpd_recipient_restrictionsではなくsmtpd_relay_restrictionsを利用する #smtpd_recipient_restrictions = permit_mynetworks, permit_sasl_authenticated, reject_unauth_destination smtpd_relay_restrictions = permit_mynetworks, permit_sasl_authenticated, reject_unauth_destination smtpd_sasl_type = dovecot #dovecotと連携 smtpd_sasl_path = private/auth #dovecot側で認証を待ち受けるソケットのパス #SSL設定 smtpd_use_tls = yes # SSL/TLSを有効化 smtpd_tls_auth_only = yes #クライアントからの接続にはSSL/TLS必須 #smtpd_tls_loglevel = 2 #ログレベルの変更:デバッグ時 #証明書、秘密鍵の指定 smtpd_tls_cert_file = /etc/ssl/postfix/server.pem smtpd_tls_key_file = /etc/ssl/postfix/server.key
/etc/dovecot/conf.d/10-auth.conf
auth_mechanisms = plain login digest-md5 cram-md5
login、digest-md5、cram-md5など対応する認証メカニズムを追加。ほとんどのメーラはCRAM-MD5しか対応していないようだ。
/etc/dovecot/conf.d/10-master.conf
service auth { unix_listener auth-userdb { mode = 0666 user = postfix group = postfix } # Postfix smtp-auth unix_listener /var/spool/postfix/private/auth { #Postfixからの認証を待ち受けるソケット mode = 0666 } }
Dovecotでローカル配送(配送時にsieveで振り分けるため)
バーチャルドメインのメールボックスへの配送にdovecotを利用する。配送時のユーザマップなどは、dovecot側のデータを利用するため、dovecotの認証サービスを設定しなければならない。
Postfixの設定で、バーチャルメールボックスへの配送にdovecotを利用する様に設定する(再掲)。
postfix/main.cf
virtual_transport = dovecot dovecot_destination_recipient_limit = 1
以下では、上記の「virtual_transport = dovecot」に対応するサービスを作成する
postfix/master.cf
#dovecotのWebサイトに記載される内容 dovecot unix - n n - - pipe flags=DRhu user=nobody:nobody argv=/usr/libexec/dovecot/dovecot-lda -f ${sender} -d ${recipient} #dovecotのユーザデータベースに合わせて「-d ${user}」に変更 dovecot unix - n n - - pipe flags=DRhu user=nobody:nobody null_sender= argv=/usr/libexec/dovecot/dovecot-lda -f ${sender} -d ${user}
dovecotにアクセスしユーザ情報を取得するためのクエリにあたる部分。dovecotのバーチャルユーザマップでユーザ名のみを記載している場合「-d ${user}」でユーザ名のみで検索するようにする。ドメイン名まで含めてユーザを登録している場合は、Webサイトの通りでよい。
エラーメールを受け取った際に、エラーメールは「Return-Path」が空である必要があるが、dovecotでローカル配送すると送信元をReturn-Pathに設定するので、「Return-Path: <MAILER-DAEMON>」となってしまう。それを回避するために、パラメータに「null_sender=」を追加すること。http://wiki.dovecot.org/LDA/Postfixのnull_sender Problemを参照のこと。
dovecotでsieveプラグインを有効にする。
${dovecot}/conf.d/15-lda.conf
protocol lda { # Space separated list of plugins to load (default is global mail_plugins). mail_plugins = sieve }
Dovecotで認証サービスを待ち受ける(標準で設定されている)。
${dovecot}/conf.d/10-master.conf
service auth { unix_listener auth-userdb { mode = 0600 user = vmail # User running dovecot-lda #group = vmail # Or alternatively mode 0660 + dovecot-lda user in this group } }
sieveの設定
各ユーザの振り分けに用いるsieveファイルの所在を設定する。
${dovecot}/conf.d/90-sieve.conf
sieve = ~/dovecot.sieve
バーチャルメールボックスなので、隠しファイルにしないようにする。
所定の場所に、dovecot.sieveファイルを作成して振り分け設定を行う。
# 振り分けの設定例 # 通常のプログラミング言語のようにif文を記述していく。 require ["fileinto","imap4flags"]; #fileinto:振り分け、imap4flags:imapのフラグ変更モジュール
# 既読にする #setflag "\\seen"; # ヘッダX-spam-FlagにYESが含まれている場合に、既読にしてspamフォルダに移動する if header :contains "X-Spam-Flag" "YES" { setflag "\\seen"; fileinto "INBOX.spam"; } # この場合は「is」なので、一致する場合 if header :is "X-Spam-Flag" "YES" { setflag "\\seen"; fileinto "INBOX.spam"; }
振り分け先のフォルダがサブフォルダの時、ファイルシステム上では「.spam」のように隠しフォルダであるが、sieveではINBOX.サブフォルダ名と記述する。
転送時の送信元書き換え
メールが転送される時、メールを実際に送信(転送)するサーバと、メール本体に書かれている送信元情報が異なってしまう。メールシステム上は特に問題ないが、最近のスパム対策に引っ掛かり問題となる可能性がある。例えばspfはメール本体の送信者情報から送信元サーバを検証するため、転送メールでは送信元として転送前のspfレコードを検索してしまう。そうすると、そのspfには実際に送信している転送ホストがリストされていないため、検証に失敗してしまう。そこで、転送時にspfの検証に利用されるenvelope_senderを書き換えて対応する。
Postfixの設定ファイル「main.cf」に以下を設定
# 書き換え対象のヘッダ sender_canonical_classes = envelope_sender # 書き換えルールを記述したファイル。「regexp:」で正規表現を利用 sender_canonical_maps = regexp:/etc/postfix/sender_canonical.regexp
/etc/postfix/sender_canonical.regexp
# 「@」以下をすべて自サイトのドメインに書き換え /@([a-z0-9_+\-\.]+)$/ @rcps.jp
書き換えルールファイルを作成した後にpostmapでデータベース作成
> postmap /etc/postfix/sender_canonical.regexp
これで転送メールのspfの問題は解消されるが、問題もありそう。転送したメールの表面上のヘッダは書き変わらないが、Return-Pathには書き換えた値がセットされてしまう。転送先にトラブルがありエラーメールが帰って来た場合、「@」以下のみ書き換えているため転送ホストにそのようなユーザは存在しないため、エラーがどこにも帰らなくなる。
2.3系へのアップデート対応
2.3系のアップデートでいくつか設定ファイルの修正が必要だった。
SSL関係
以下の設定が必須になったようだ。
以前のバージョンではDiffie Hellman parametersが初回起動時に自動生成され週ごとに再生成されていたが、セキュリティ上のメリットがさほどないため廃止された。バージョン2.3からはssl_dhの指定が強制されるため、以下を必ず設定して、設定した場所にDiffie Hellman parametersファイルを配置しなければならない。
/etc/dovecot/conf.d/10-ssl.conf
ssl_dh = </etc/dovecot/dh.pem
ファイルの内容は、以前のものを再利用する場合以下のコマンドで変換できる
# 旧バージョンで生成されたssl-parameters.datファイルの場所は適宜探して指定する dd if=/var/lib/dovecot/ssl-parameters.dat bs=1 skip=88 |openssl dhparam -inform der > /etc/dovecot/dh.pem
今回は強度の高いものを新しく再生成する
openssl dhparam 4096
生成にはかなり時間がかかるので、しばらく待つ。
SIEVE関係
バージョン2.3にすると、SIEVEの振り分けが動かなくなった。ログに以下のエラーが出力されていた。
Sep 03 11:06:54 [dovecot] lda(****)<5130><XXXXXXXXXXXXXXXXXXXXXXXXX>: Error: sieve: Failed to initialize script execution: Invalid postmaster_address: invalid address `postmaster@' specified for the postmaster_address setting
エラーを返す際のpostmasterのメールアドレスのドメイン部分がうまく取得できていないようだ。これまでは厳密にチェックされていなかったが、バージョン2.3からはチェックされるようになり、SIEVEが起動できなくなったようだ。
以下のpostmaster_addressのパラメータにpostmasterのアドレスを設定してやると解決する。
/etc/dovecot/conf.d/15-lda.conf
postmaster_address = postmaster@xxxx.co.jp