あの頃の sendmail.cf は呪文だった——踏み台を経てたどり着いた Postfix 時代の設計哲学

webの仕組み

TL;DR(要点)

  • sendmail は“巨大単一コア”で柔軟だが、運用の複雑さが致命的。
  • Postfix は“プロセス分割”+“読める設定”で安全・保守性を両立。
  • まず リレー拒否・TLS・SPF/DKIM/DMARC・fail2ban の4点で「転ばぬ先の杖」。
  • セキュリティポリシーを先に決めるのが勝ち筋。設定はその写経でよい。

Turbolinux→CentOS→AlmaLinux と渡り歩く中で、sendmail の設定ミスで踏み台化 → ドメインがBL入りという苦い経験をしました。
でもその挫折が、権限分離・ポリシー先行・監視ログ運用の重要性を腹落ちさせてくれた——この記事は、その“昔の自分”に向けた手紙でもあります。


なぜ sendmail は「呪文」だったのか

  • 1つの巨大なコアに多機能を詰め込む設計。
  • 設定は m4 マクロ → sendmail.cf 生成という二段構え
  • 読みにくい/間違えやすい/テストしづらい。

典型的な落とし穴

  • open relay(アクセス制御の漏れ)。
  • 逆引き・HELO 不一致。
  • ログが読み取りづらく、事故後に原因追跡が困難。

Postfix の思想:プロセス分割と「人間が読める」設定

  • 役割ごとにプロセス分割(smtpd / cleanup / qmgr …)。
  • 設定は main.cfそのまま書く
  • 例外処理は map(hash:/etc/postfix/xxx)で管理。

メリット:バグや誤設定が局所化しやすく、保守しやすい。設定が読める

呪文 → 人間語 対応表(よく使う場面だけ)

目的 sendmail の例 Postfix の例
リレー拒否 FEATURE(`access_db')dnl など smtpd_recipient_restrictions = permit_mynetworks, reject_unauth_destination
ローカル受信 Cwlocalhost mydestination = $myhostname, localhost.localdomain, localhost
自ネットワーク /etc/mail/relay-domains mynetworks = 127.0.0.0/8
仮想転送 virtusertable virtual_alias_maps = hash:/etc/postfix/virtual
ドメイン偽装 MASQUERADE_AS(example.com) smtp_generic_maps = hash:/etc/postfix/generic
キュー確認 mailq postqueue -p
キュー操作 (難解) postsuper -d ALL
リロード service sendmail restart systemctl reload postfix

AlmaLinux での最小・堅牢スタート(実務手順)

1) Postfix 最小設定(外部中継しない/自ドメイン受信のみ)

/etc/postfix/main.cf 要点のみ:

# /etc/postfix/main.cf(要点)
myhostname = mail.example.com
myorigin = /etc/mailname
mydestination = $myhostname, localhost.localdomain, localhost, example.com
mynetworks = 127.0.0.0/8
inet_interfaces = all
inet_protocols = ipv4 # リレー拒否の肝
smtpd_recipient_restrictions = permit_mynetworks, reject_unauth_destination # TLS(Let’s Encrypt 例)
smtpd_tls_cert_file=/etc/letsencrypt/live/example.com/fullchain.pem
smtpd_tls_key_file=/etc/letsencrypt/live/example.com/privkey.pem
smtpd_use_tls = yes
smtpd_tls_security_level = may
smtp_tls_security_level = may
# 反映
sudo systemctl enable --now postfix
sudo systemctl reload postfix

2) 送信ドメイン認証(DNS)

  • SPF(TXT)v=spf1 a mx ip4:YOUR.PUBLIC.IP ~all
  • DKIM(opendkim 推奨):秘密鍵生成→公開鍵を TXT で登録
  • DMARC(TXT)_dmarc.example.com IN TXT "v=DMARC1; p=quarantine; rua=mailto:dmarc@example.com"

まずは SPF + DMARC(p=none) から始め、運用ログで誤判定を潰してから quarantine / reject へ。

3) Fail2Ban でブルートフォース抑止

/etc/fail2ban/jail.d/postfix-auth.conf

[postfix-sasl]
enabled = true
filter = postfix[mode=aggressive]
logpath = /var/log/maillog
maxretry = 5
findtime = 600
bantime = 3600
sudo systemctl enable --now fail2ban
sudo fail2ban-client status postfix-sasl

運用の「型」:ポリシー先行で決め打ちする

ここが 新人管理者向けの要。先に「こう運用する」を言語化して、設定はその写経にします。

セキュリティポリシー雛形(コピペ可)

  • メールの基本方針
    1. 中継は自ネットワーク(mynetworks)のみ許可。外部中継は常に拒否
    2. 送受信は TLS を“できる限り”使う(*_tls_security_level = may 以上)。
    3. SPF + DKIM + DMARC を必ず有効化。DMARCは段階的に none→quarantine→reject
    4. 試験・障害対応以外で root から直接操作しない。変更は dnf / systemctl / postfix と設定管理に限定。
    5. ログ(/var/log/maillog)は毎朝ざっと見る。異常は Fail2ban で一次封じ、原因は後追い
  • 権限と分離
    • MTA は postfix 標準ユーザーで動かす。
    • Web や PHP とはプロセス分離(php-fpm プール・chroot・SELinux)。
    • 設定ファイルは Git 等で差分管理(抜粋でも可)。
  • 変更手順(変更要求→レビュー→反映)
    1. main.cf の差分作成
    2. postfix check
    3. systemctl reload postfix
    4. journalctl -u postfix -n 100 で確認
    5. 外部テスターへ送受信試験

デイリー/リリース前チェックリスト

  • [ ] postqueue -pに近い(詰まりなし)
  • [ ] journalctl -u postfix | egrep -i 'reject|warning|error' が異常なし
  • [ ] 送信試験:Gmail / Outlook.com に届く(SPF/DKIM/DMARC PASS)
  • [ ] 証明書の有効期限 ≥ 30日(certbot renew --dry-run
  • [ ] Fail2ban の ban が増えすぎていない(誤BANなし)
  • [ ] DNS 逆引き(PTR)と myhostname が一致

「同じ轍を踏まない」ための学び

  • 人間が読める設定を選ぶ(Postfixの勝ち筋)。
  • 役割を分ける・権限を分ける(事故は局所化できる)。
  • ポリシーを先に決める(設定は後付け、可視化できる)。
  • ログを見る習慣(朝5分で世界が変わる)。
  • 反省は次回のチェックリストへ(ノウハウは属人化させない)。

まとめ:祈りの呪文はいらない

sendmail の時代は、祈りのチェックでした。
Postfix の時代は、読み書きできる規律です。
新人管理者へ——セキュリティポリシーを決めて、堅牢に組む。設定はその写経でいい。祈らなくて、いい

付録:テストコマンド早見表(新人に渡す用)

# 受信テスト(25番ポート、EHLO/HELO 確認)
telnet mail.example.com 25 # 送信キュー確認
postqueue -p # 送信キュー全削除(緊急時)
sudo postsuper -d ALL # 設定チェック
postfix check # ログ確認(直近)
journalctl -u postfix -n 200 --no-pager # TLS 有効性(サーバー側の証明書確認)
openssl s_client -starttls smtp -connect mail.example.com:25 -servername mail.example.com | openssl x509 -noout -dates -issuer -subject