CyrusIMAPdとの連携運用

前提条件

mail-server.svg

設定目標

なお、200x年代からこの運用をしてきたが、だましだまし運用してたのを、サーバーリプレースする際に、徹底的に見直した。 見直した成果はフィードバック済み。

インストール

/etc/make.conf

以下の内容を追記する。

# for sendmail
mail_sendmail_SET=                      LA NIS SEM TLS DANE SASL SHMEM MILTER SMTPUTF8
mail_sendmail_SET+=                     SOCKETMAP BLACKLISTD CYRUSLOOKUP PICKY_HELO_CHECK
mail_sendmail_UNSET=                    BDB LDAP SASLAUTHD
# for cyrus-imapd32
mail_cyrus-imapd32_SET=                 SRS IDLED SQUAT SQLITE XAPIAN AUTOCREATE READLINE_PERL
mail_cyrus-imapd32_UNSET=               HTTP LDAP NNTP SNMP MYSQL PGSQL BACKUP
mail_cyrus-imapd32_UNSET+=              CLAMAV MURDER REPLICATION READLINE_GNU
# for cyrus-sasl2
security_cyrus-sasl2_SET=               OTP CRAM LMDB NTLM DIGEST LOGIN PLAIN SCRAM
security_cyrus-sasl2_UNSET=             BDB BDB1 ANONYMOUS ALWAYSTRUE AUTHDAEMOND
security_cyrus-sasl2_UNSET+=            KEEP_DB_OPEN OBSOLETE_CRAM_ATTR OBSOLETE_DIGEST_ATTR

/usr/ports/mail/sendmail/Makefile.local

以下の内容でファイルを作成する(「先頭の空白」は全てタブで置き換えること)。

post-configure:
        ${ECHO_CMD} 'APPENDDEF(`conf_sendmail_ENVDEF'\'', `-D_FFR_TLS_USE_CERTIFICATE_CHAIN_FILE'\'')' >> ${WCONF}/site.config.m4
        ${ECHO_CMD} 'APPENDDEF(`conf_sendmail_ENVDEF'\'', `-D_FFR_MTA_STS'\'')'               >> ${WCONF}/site.config.m4
        ${ECHO_CMD} 'APPENDDEF(`conf_sendmail_ENVDEF'\'', `-D_FFR_TLS_ALTNAMES'\'')'          >> ${WCONF}/site.config.m4
        ${ECHO_CMD} 'APPENDDEF(`conf_sendmail_ENVDEF'\'', `-D_FFR_VRFY_TRUSTED_FIRST'\'')'    >> ${WCONF}/site.config.m4
        ${ECHO_CMD} 'APPENDDEF(`conf_sendmail_ENVDEF'\'', `-D_FFR_QUEUE_GROUP_SORTORDER'\'')' >> ${WCONF}/site.config.m4
        ${ECHO_CMD} 'APPENDDEF(`conf_sendmail_ENVDEF'\'', `-UTLS_EC -DTLS_EC=2'\'')'          >> ${WCONF}/site.config.m4

なお _FFR_TLS_USE_CERTIFICATE_CHAIN_FILE の指定が無い場合は、証明書・中間証明書・秘密鍵の3つが別れて指定される、という意味では無く、もっとおぞましい振る舞いをする。 話を聞くとサーバーサイドとクライアントサイドの振る舞い(特に中間証明書の取り扱い)が分離されていないなど、極めて初期の実装が残っているとのこと。

インストール

cd /usr/ports/security/cyrus-sasl2 && make install
cd /usr/ports/mail/sendmail        && make install
cd /usr/ports/mail/cyrus-imapd32   && make install

セットアップ

/usr/local/lib/sasl2/Sendmail.conf

以下の内容のファイルを作成する。

pwcheck_method: auxprop
auxprop_plugin: sasldb

本条件において適用可能なオプションとしては、下記の物があるが、CyrusIMAPd側の設定との調整を考えるとデフォルトのままとする。

設定名

デフォルト値

意味

sasldb_path

/usr/local/etc/sasldb2

SASLDBファイル(本件ではLMDB)のパス

sasldb_mapsize

1048576 バイト

(LMDB固有)全ユーザーをオンメモリにマッピングするためのサイズ

sasldb_maxreaders

126

(LMDB固有)SASLDBファイルを同時アクセス可能な最大セッション(プロセス)数

SASLクライアントが参照すべき設定ファイル名は sasl_server_init() 関数に引き渡される appname 引数により決定される。 SASLフレームワーク的にはマニュアルに明記されていることではあるが、 フレームワークを使用する側(Sendmailなど)ではマニュアルに記載(※)されておらず、 その振る舞いの調査が必要な場合は参考までに。

https://www.cyrusimap.org/sasl/sasl/reference/manpages/library/sasl_server_init.html

※厳密には、フレームワーク使用側の、外のドキュメント(フレームワーク側)で明記されているが、その根拠が明記されていない。

/etc/mail/Makefile.local

以下のファイルを作成する。

SENDMAIL_CF_DIR=/usr/local/share/sendmail/cf

/etc/mail/ホスト名.mc

いわゆるsendmail.cf作成準備

ln -s freebsd.submit.mc /etc/mail/$(hostname).submit.mc
cd /etc/mail && make

切り替え

cd /usr/ports/mail/sendmail && make mailer.conf

なお切り戻しは下記のように実行する。

rm -f /etc/mail/Makefile.local
cd /etc/mail && rm -f ホスト名*.cf && make
cd /usr/ports/mail/sendmail && make mailer.base

/etc/mail/ホスト名.mc のカスタムポイント

TLS関連設定

変更箇所

conf*_CERT にて中間書証明書を含むSSL証明書(いわゆるフルチェイン証明書)のファイル名を、conf*_KEY にて秘密鍵の ファイル名を指定する。

複数の証明書(ECC証明書とRSA証明書といった組み合わせ)を指定したい場合は、順番に「,」でつなげる。下記のように1個目、2個目の証明書がそれぞれ対応するように指定する。また3個以上の証明書は指定できない(指定できる証明書の数は1個か2個)。

define(`confSERVER_CERT', `ECCフルチェイン証明書,RSAフルチェイン証明書')dnl
define(`confSERVER_KEY',  `ECC秘密鍵,RSA秘密鍵')dnl

confCACERT は特に指定しなくてもよいが、confCACERT_PATH には /etc/ssl/certs を指定する。これは特にFreeBSD12.2以降では必須とも言える対応になる。 それ以前のバージョンでは、この設定に指定するディレクトリの工夫が必要であった(もう必要無いので説明しない)。

追加設定

define(`confSERVER_SSL_OPTIONS', `SSL_OP_NO_SSLv2,SSL_OP_NO_SSLv3,SSL_OP_NO_RENEGOTIATION,SSL_OP_PRIORITIZE_CHACHA,SSL_OP_CIPHER_SERVER_PREFERENCE')dnl
define(`confCIPHER_LIST', `TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_128_GCM_SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA:AES256-SHA:AES128-SHA')dnl
define(`confTLS_FALLBACK_TO_CLEAR', `True')dnl

認証関連の設定

define(`confAUTH_MECHANISMS', 'SCRAM-SHA-256 SCRAM-SHA-1 CRAM-MD5 PLAIN')

CyrusIMAPd関連設定

FEATURE(mrs)
FEATURE(mrs_cyrus)
MAILER(cyrusv2)

MAILER 行は他の MAILER 行の周辺に置くこと。FEATURE 行は MAILER 行の前にあればどこでもよい。

バーチャルホスト関連設定

define(`ALIAS_FILE', `/etc/mail/virtaliases,/etc/mail/aliases')dnl
VIRTUSER_DOMAIN_FILE(`-o /etc/mail/virtdomains')

バーチャルホスト連携

/etc/mail/virtdomains

example.jp

/etc/mail/mailertable

example.jp   mrs_cyrus_mailertable:

※ドメインの後の「空白」は「タブ」に置き換えること。: の後ろに指定は無いが、: の存在は必須である。

/etc/mail/virtaliases

とりあえず空で。

よくある質問とその答え

Q.下記のように confLOCAL_MAILER で設定すればいいぢゃん、なんでしないの?

define(`confLOCAL_MAILER', `cyrusv2')dnl

A.sendmailが取り扱う全てのメールをローカルメーラーとして、CyrusIMAPdに送るということはできますが、以下のデメリットが嫌でそうしていません。

※なおsendmailで受信して、CyrusIMAPdのメールボックスに送るだけなら、SASLアカウントの設定は不要。

Q.この手の設定を他で見ると下記のように /etc/mail/access ファイルで設定してるぢゃん、何か違いは?

example.jp: RELAY

A.sendmailのバーチャルドメイン機構を最大限生かすための設定です。 上記設定だけで、/etc/mail/mailertableconfLOCAL_MAILER の設定を忘れると、容易にサードパーティリレイできてしまいます。 VIRTUSER_DOMAIN_FILE を設定すれば、メールボックスの存在が必須になるため、存在しない場合にエラーになります。

Q.ports/pkgで入れないと駄目なんですか?

A.ベースシステムにSASLライブラリが無いのでいかんともしがたいです。 ベースシステムに、ports/pkgでインストールされたSASLライブラリ付でビルドすることもできないでもないですが、 OSのバージョンアップ時のメンテナンスがめんどくさくなるのでオススメしません。

Q.pkgで入れられないのですか?

A.CyrusIMAPd関連の設定(アカウント情報をリアルタイムに参照する設定と転送するための設定)がpkgには無いので、portsでないとダメです。

Q.以下のエラーが出てメールの送信ができません

AUTH failure (XXXXXXXX): generic failure (-1) SASL(-1): generic failure: Unable to open MDB transaction, user=...

A.極シンプルにCyrusIMAPdサーバーの再起動で一時しのぎします。

service imapd restart

A.以下のコマンドを実行して、LMDBファイルに接続しているセッション数およびプロセスIDを確認する。

# mdb_stat -ne /usr/local/etc/sasldb2
Environment Info
    :
  Max readers: 126
  Number of readers used: 101
Status of Main DB
    :

上記の例の場合、最大126セッション中101セッション使用していることが分かる。

# mdb_stat -nr /usr/local/etc/sasldb2
Reader Table Status
    pid     thread     txnid
     15223 801e12000 -
     15229 801612000 -
   :

上記のように、具体的にLMDBファイルをつかんでるPIDのリストが取得できる。

# pgrep -lf -F <(mdb_stat -nr /usr/local/etc/sasldb2 | awk '/[0-9]/ { print $1 }')
15223 imapd: imaps: XXXXXX.XXXXXXXXXX.XXX [XXX.XXX.XXX.XXX] nork@ninth-nine.com ninth-nine.com!user.nork Idle

※ZSH/BASH拡張を使用しているので、SH等では実行できない点に注意。

ここで表示されるPIDのプロセスに対して終了を促すことになるが、とどつまりCyrusIMAPdサーバーの再起動という結論で。 本サーバーがSASLDBライブラリに接続リークを起こすことを確認。

Q.なんでLMDB使う?デフォルトのBDB1でええやん。

A.LMDBと言えばなうでヤングなインメモリデータベースやん。スケーラビリティとか諸々安心という点が売り。

Q.SASLAUTHD、SASLAUTHDと色々うるさいが、SASLAUTHDに恨みでもあるのですか?

A.ありまぁす! pwcheck_method の設定の有効性が、認証方法に依存するなんて、この手の設定の解説を見たことありません! 無条件にインストールしてる例を見ますが、実際には必要かどうか全く検証してないことがわかりました! オリジナルのドキュメントにも一応書いてあるのですが、こっそり過ぎてわかりません!

参考文献

sendmail/cyrus-imapd (最終更新日時 2022-01-06 10:49:07 更新者 NorikatsuShigemura)