はじめに
技術部インフラグループの鈴木です。先日宮崎の都井岬に行きましたが、馬が可愛かったです。 ところで最近仕事でPostfixをよく触っているので、今後のために最新のリリースノートを読んでみました。今回はそれを共有します。
2025/05/26現在、aptで落ちてくるPostfixは3.8.6です。
$ sudo apt show postfix Package: postfix Version: 3.8.6-1build2 ~~略~~
Postfixの公式サイトを確認すると、最新の安定版は3.10でセキュリティ強化や新機能など、現代のメールシステム運用において重要な変更点が多く含まれていました。
そこで今回は日々の運用に役立つ情報や、来るべきアップデートへの対応に備えるため、Postfix 3.9のリリースノートを読んでいくこととします。
なお、全てを解説するというより、私が気になったアップデート内容について深掘りしていきます。
警告を出していた古いオプションの廃止
20年前に非推奨になった下記のオプションが廃止されました。
- permit_naked_ip_address
- check_relay_domains
- reject_maps_rbl
20年残し続けたということにも驚きを隠せない(メールという技術の特殊さを感じる)ですが、実はこのパラメータについて見たことがなかったので現在使われているものを調べたところ、主に対応するパラメータは以下でした。
- smtpd_relay_restrictions
- smtpd_recipient_restrictions
main.cfに以下のように書いていくのはよくあります。
smtpd_recipient_restrictions =
permit_mynetworks,
permit_sasl_authenticated # さらにrejectする設定を書いていく
これに関しても深掘りしたところsmtpd_recipient_restrictions
ではなくsmtpd_relay_restrictions
で設定し、さらに怪しいリクエストに関して早期に検知して遅延させるという設定例を見つけました1。
また、設定例に関してPostfix SMTP relay and access controlを見るとsmtpd_helo_requiredに関して以下の記述があります。
Requiring that the client sends the HELO or EHLO command before sending the MAIL FROM or ETRN command. This may cause problems with home-grown applications that send mail. For this reason, the requirement is disabled by default ("smtpd_helo_required = no").
とあります。つまるところHELO or EHLOを発信しない自作アプリ以外であれば有効と解釈できます。
記事にある挨拶(HELO or EHLO)がないリクエストはろくでもないものというのは同意です。現実と同じですね。.
smtpd_helo_restrictions
やsmtpd_relay_restrictions
に関してもPostfix SMTP relay and access controlのGetting selective with SMTP access restriction listsに例があり、公式にセキュアな設定と解釈できます。
これらを参考にしつつ、怪しいリクエストを拒否するセキュアな設定として、HELO or EHLOを必須にすると以下になります。
# HELO or EHLOの段階で不正なリクエストを拒否 smtpd_helo_required = yes smtpd_helo_restrictions = reject_invalid_helo_hostname, reject_non_fqdn_helo_hostname, reject_unknown_helo_hostname # リレー制御、Postfix SMTP relay and access controlのGetting selective with SMTP access restriction listsの例の通り smtpd_relay_restrictions = permit_mynetworks, permit_sasl_authenticated, reject_unauth_destination
smtpd_*_restrictions
のreject_*
に関しては上記に挙げたsmtpd_relay_restrictions
やsmtpd_recipient_restrictions
に書くこともできますが、SMTPセッションの早い段階で設定するのが理にかなっています。
なぜなら不正なアクセス試行を早期に遮断することで、サーバーへの負荷を最小限に抑えられるからです。
MongoDBの対応
MongoDBデータベースのクエリサポートが行われました。
一般的にPostfixをMySQLのようなRDBやLDAPと連携させるのはPostfixAdminやpostLDAPadmin2といったOSSを使って、エイリアスやバーチャルホストの定義を外部ソースに格納し、連携を行うものが一般的です。
ここにMongoDBが追加されました。Postfixと連携させるとして、真っ先に思いつくのは従業員名簿のような厳格なスキーマです。
その反対にあるスキーマレスのMongoDBに従業員名簿を格納するユースケースとは果たしてどんなものなのでしょうか。
MongoDBがPostfixバックエンドとして役立つ理由
以下のような理由があります。
- JOINを必要としないデータ構造に最適化されるため、参照系クエリのパフォーマンスが安定しやすい
- RDBの場合、仮にバーチャルドメインとユーザーの情報を跨って扱おうとすればJOINが発生し、データ構造の設計やインデックスの貼り方次第で性能に影響が出る可能性がある
- MongoDBでは関連情報を1ドキュメントにまとめておけば、シンプルなクエリで完結する
- 従来のデータベース(スキーマがあるDB)では難しい、メールシステムの動的な要求(例:柔軟なユーザー・エイリアス管理)に応えることが可能
- 部署異動やプロジェクト変更でメール設定が頻繁に変わっても、MongoDBのスキーマレスな特性により、新しい属性を簡単に追加できる
- 例えば、人事システムと連携し、リアルタイムなアカウントプロビジョニングや、柔軟なポリシー適用が容易になる
その他MongoDBによるシャーディングで読み書き性能の向上や、レプリカセットでの高可用性もあります。
とは言っても実例を見ないとイメージがつかないので公式のHowToを見てみましょう。
Postfix MongoDB Howtoを見てみる
Postfix MongoDB Howtoのドキュメントを読むと以下の例があります。
- 例
{ "username": "user@example.com", "local_part": "user", "domain": "example.com", "alias": [ {"address": "admin@example.com"}, {"address": "abuse@example.com"} ], "active": 1 }
- 設定
uri = mongodb+srv://user_name:password@some_server dbname = mail collection = mailbox query_filter = {"$or": [{"username":"%s"}, {"alias.address": "%s"}], "active": 1} result_attribute = username
iniファイルにJsonを書くのはなかなか新鮮です。
比較対象としてPostfixAdminでmain.cfにvirtual_mailbox_domains
を指定し、postfixにDBを参照させる場合は以下のような設定になります。
バックエンドがMongoDBかMySQLかというだけでやっていることはあまり変わりません。
- main.cf
virtual_mailbox_domains =
mysql:/etc/postfix/mysql_virtual_domains_maps.cf
- mysql_virtual_domains_maps.cf
user = hoge password = hoge hosts = hoge dbname = hoge query = SELECT maildir FROM mailbox,alias_domain WHERE alias_domain.alias_domain = '%d' and mailbox.username = CONCAT('%u', '@', alias_domain.target_domain) AND mailbox.active='1' AND alias_domain.active='1'
仮に従業員情報がスキーマレベルで頻繁に変わる組織があったとして、そこにPostfixを使うかどうかという点もあります(SaaSという選択肢もある)。
ただMongoDBを選ぶことで「RDBに閉じた設計からの脱却」「Postfixとの連携オプションが増える」という点は良いですね。
結論、本番導入のハードルはまだ高いものの、選択肢として頭の片隅に置いておく価値はありそうです。
しかしiniファイルにJson/SQLを直接書くと、もともと目が滑りやすいPostfixの設定が、さらに滑りやすくなった気がする
セキュリティ類のアップデート
複数のセキュリティに関するパラメータのデフォルト設定が変更されています。デフォルト設定が変わるので、アップデートの際は要注意です。
とはいってもPostfixは意外と破壊的変更が少ないOSSです(冒頭の20年残っていたオプションなど)。
実際「いつの間にかアップデートされていたけど特に問題なかった」という経験をした方も多いでしょう。
とはいえ、セキュリティ系のデフォルト挙動が変わると、思わぬ副作用(意図せぬ動きやログの急増など)が出る可能性もあります。特に「昔ながらの設定を引きずっている」といった環境では注意が必要です。
"blind" SMTP attacksに対して
- 攻撃方法: SMTPパイプライン処理を悪用し、認証されていない状態のまま応答を待たずに大量のコマンドを送りつけてサーバーリソースを枯渇させたり、予期せぬ動作を引き起こしたりする攻撃です。
- アップデートされたパラメータ:
smtpd_forbid_unauth_pipelining = yes
(デフォルト設定) - パラメータの解説: 認証されていないクライアントからのパイプライン処理を積極的に禁止し、その入力をログに記録します。
SMTP smugglingに対して
- 攻撃方法: メールメッセージの終端を示す標準記号の前に、不正な改行コードを挿入することでメールの境界を偽装します。これにより意図しない内容を注入したり、正規メールの末尾に悪意のある情報を付与したりする攻撃です。
- アップデートされたパラメータ:
smtpd_forbid_bare_newline = normalize
(デフォルト設定) - パラメータの解説: メッセージコンテンツ内の
<CR><LF>
ではなく<LF>
で終わる行を拒否または制限します。
outbound SMTP smugglingに対して
- 攻撃方法: 攻撃者が不正な改行コードを含むメールを送信し、脆弱なPostfixを踏み台にする攻撃です(自分が加害者となりうる)。
- アップデートされたパラメータ:
cleanup_replace_stray_cr_lf = yes
(デフォルト設定) - パラメータの解説: メッセージコンテンツ内の単独の
<CR>
や<LF>
文字をスペースに置換し、他のMTAで不正に解釈されて自身のサーバが攻撃の起点となるのを防ぎます。
DNSルックアップに関するDoS攻撃・リソース枯渇攻撃に対して3
- 攻撃方法: 不正なDNS応答や過剰なDNSクエリによって、Postfixのリソースを枯渇させサービス停止を引き起こす攻撃です。
- アップデートされたパラメータ: DNSクライアントのDNSルックアップ結果のサイズ制限の追加
- 解説: PostfixのDNSクライアントが受け取るレコードの総数を100に制限します。超過分は破棄され、警告がログされます。これはリソース枯渇やDoS攻撃を防ぐもので、アクセス制限におけるDNSリクエストにも同様の制限が適用されます。
読んでみた感想
今回Postfix 3.9リリースノートを読み込み、特にセキュリティ機能の強化に力が入れられていることを強く感じました。
長年放置されてきた古いオプションの廃止や、さまざまな攻撃に対する防御策のデフォルト有効化は、運用する上で心強い変更点に感じます。
またMongoDB対応は正直現時点ではピンときていませんが、今後の動向に注目していきたいです。
次回
次回は3.10に焦点を当てて読んでみたいです。ポスト量子暗号のサポートなどがあり、Postfixにもいよいよ量子コンピュータの影がかかり始めたかとSF好き4として思いました。
参考
Postfix SMTP relay and access control
Postfix Replacements for Deprecated Features.
- Postfix に群がる迷惑メールを追い払う - nakamurakko’s blog↩
- 国産のOSSだった。個人的に応援したい。↩
- リリースノートのDNSルックアップに関するセクションで、「dns_rr_append() as reported by Toshifumi Sakaguchi」という一文を見つけた。日本人の名前がリリースノートに記されているのを見て、普段使いのミドルウェア開発に日本の方が貢献されていることに、ひそかに感動した。↩
- なんとなくグレッグ・イーガンのディアスポラを思い出した。↩