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
運用の「型」:ポリシー先行で決め打ちする
ここが 新人管理者向けの要。先に「こう運用する」を言語化して、設定はその写経にします。
セキュリティポリシー雛形(コピペ可)
- メールの基本方針
- 中継は自ネットワーク(
mynetworks)のみ許可。外部中継は常に拒否。 - 送受信は TLS を“できる限り”使う(
*_tls_security_level = may以上)。 - SPF + DKIM + DMARC を必ず有効化。DMARCは段階的に
none→quarantine→reject。 - 試験・障害対応以外で root から直接操作しない。変更は
dnf/systemctl/postfixと設定管理に限定。 - ログ(
/var/log/maillog)は毎朝ざっと見る。異常は Fail2ban で一次封じ、原因は後追い。
- 中継は自ネットワーク(
- 権限と分離
- MTA は
postfix標準ユーザーで動かす。 - Web や PHP とはプロセス分離(php-fpm プール・chroot・SELinux)。
- 設定ファイルは Git 等で差分管理(抜粋でも可)。
- MTA は
- 変更手順(変更要求→レビュー→反映)
main.cfの差分作成postfix checksystemctl reload postfixjournalctl -u postfix -n 100で確認- 外部テスターへ送受信試験
デイリー/リリース前チェックリスト
- [ ]
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

