管理者向け クイックスタート Postfix + Rspamd + ClamAV 非同期:Dispatcher/Worker

管理者クイックスタート
最小構成での組み込み(開発者寄り)

ここでは 最小手順に絞って、Postfix の Milter チェーンへ ZipCloudMilter(ZCM)を組み込み、 Rspamd / ClamAV と共存させる流れを示します。
ZCM は「SMTP を待たせない」ため、Milter 側は enqueue 中心で、重い処理(ZIP/アップロード/通知/DB記録)は 非同期(Dispatcher/Worker)で行います。

本番適用前にステージングで検証してください。最初は submission(社内送信) から段階導入が安全です。
先に 導入チェックリスト で「DNS/TLS/Nextcloud/クォータ/ポリシー」を確認しておくとスムーズです。

全体像(最小)

[SMTP/Submission]
    |
    v
  Postfix
    |
    +--(milter chain)--> Rspamd milter  ----> (reject / add headers)
    |                     |
    |                     +-- optional: clamd/av
    |
    +--(milter chain)--> ZipCloudMilter (enqueue only)
                           |
                           v
                    /var/tmp/zipcloudmilter/queue(/large)
                           |
                           v
                 Dispatcher -----> Worker(s)
                           |
                           +-- Nextcloud upload/share
                           +-- DB (uploads/logs/tokens/modes/limits)
                           +-- Notify mail (recipient / sender)

重要:ZCM は「メール配送」と「ファイル転送」を分離します。大容量ほどこの分離が効いて、SMTP タイムアウトを避けやすくなります。

1
📦

ZCM の配置と実行ユーザー(権限)

ZCM は Postfix と同じホスト(または同一LAN)で動かす構成が一般的です。まずは 実行ユーザーソケット/キュー の権限を固めます。

# 例(目安)
# - コード配置: /usr/local/zipcloudmilter/
# - 設定:       /usr/local/etc/zipcloudmilter/ など
# - 実行:       postfix(または専用ユーザー)で常駐
# - ソケット:   /var/run/zipcloudmilter.sock
# - キュー:     /var/tmp/zipcloudmilter/queue, /var/tmp/zipcloudmilter/queue_large

# ディレクトリ作成(FreeBSD/Linux共通の例)
install -d -m 0750 -o postfix -g postfix /var/tmp/zipcloudmilter
install -d -m 0750 -o postfix -g postfix /var/tmp/zipcloudmilter/queue
install -d -m 0750 -o postfix -g postfix /var/tmp/zipcloudmilter/queue_large
install -d -m 0755 /var/run
ポイント: キューやソケットの owner/group が揃っていないと、Postfix⇄ZCM 間で接続エラーになります(permission denied)。
2
🐍

Python 仮想環境(venv)と依存導入

運用を安定させるため、ZCM は venv で依存を固定するのが無難です。

# 例:venv
python3 -m venv /opt/zcm-venv
. /opt/zcm-venv/bin/activate
pip install --upgrade pip
pip install -r /usr/local/zipcloudmilter/requirements.txt

# 起動確認(例)
/opt/zcm-venv/bin/python /usr/local/zipcloudmilter/zipcloudmilter.py --help
3
🧷

サービス常駐(FreeBSD rc.d / systemd 例)

FreeBSD(rc.d の考え方)
# 例(概念)
# /usr/local/etc/rc.d/zipcloudmilter を用意し、
# /etc/rc.conf に zipcloudmilter_enable="YES" を設定して常駐化します。
#
# 起動/停止
service zipcloudmilter enable
service zipcloudmilter start
service zipcloudmilter status

※ 実際の rc.d はプロジェクト付属のもの(または配布手順)に合わせてください。

Linux(systemd 参考)
# /etc/systemd/system/zipcloudmilter.service(参考)
[Unit]
Description=ZipCloudMilter
After=network.target

[Service]
User=postfix
Group=postfix
Environment="VIRTUAL_ENV=/opt/zcm-venv"
ExecStart=/opt/zcm-venv/bin/python /usr/local/zipcloudmilter/zipcloudmilter.py
Restart=always

[Install]
WantedBy=multi-user.target

systemctl daemon-reload && systemctl enable --now zipcloudmilter
実運用のコツ: ZCM のログは「system logger」だけに寄せず、アプリ側ログ(例: /var/log/zipcloudmilter.log)も必ず残すと切り分けが速いです。
4
✉️

Postfix へ Milter として組み込み(順序と適用箇所)

最初は submission(社内送信)から適用し、問題がないことを確認してから smtpd(外部受信)へ展開するのがおすすめです。

# /etc/postfix/main.cf(例)
milter_default_action = accept
milter_protocol = 6

# 推奨の目安:
#  ① Rspamd(判定/拒否/ヘッダ付与)
#  ② ZipCloudMilter(添付→リンク化:enqueue中心)
smtpd_milters = inet:127.0.0.1:11332, unix:/var/run/zipcloudmilter.sock
non_smtpd_milters = $smtpd_milters

# Rspamd 例: 127.0.0.1:11332
# ZCM   例: /var/run/zipcloudmilter.sock
注意: 「ZCM でリンク化した後」に Rspamd が本文を改変したり DKIM 署名を付ける構成だと、 署名タイミングやヘッダ整合を考える必要があります。まずは「判定→リンク化」の順序で安定運用してから最適化すると安全です。
# 設定反映
postfix check
service postfix reload   # FreeBSD例
# systemctl reload postfix  # Linux例
5
🧪

Rspamd / ClamAV 共存チェック(どこで弾かれるか)

Rspamd(milter)
# 例:ヘッダの扱い(必要に応じて)
# /usr/local/etc/rspamd/local.d/milter_headers.conf
extended_spam_headers = true;

Rspamd が「reject」した時点で ZCM の処理には到達しません。まずは Rspamd の判定を安定させるのが先です。

ClamAV(容量/時間)
# clamd.conf の見直し(例:概念)
# - StreamMaxLength(大きすぎる添付の扱い)
# - ReadTimeout / CommandReadTimeout(スキャン時間)
# - MaxThreads(過負荷時)
#
# ※ 大容量添付はスキャン時間が伸びやすいので注意

スキャンで拒否されたメールはリンク化されません。大容量運用では「スキャン方針」と「リンク化方針」の整合が重要です。

6
🧵

非同期(Dispatcher / Worker)構成の確認

ZCM はキュー(JSON 等)へ投入し、Dispatcher が Worker に割り当てます。 典型的には normallarge の 2 キューを使います。

要素役割運用メモ
Queue(normal) 通常サイズのジョブ 通知が速い。一般運用の主経路。
Queue(large) 大容量のジョブ 分割/再試行等で安定転送(構成により)。通知は数秒〜。
Dispatcher キュー監視・割当・遅延/リトライ制御 「processing の停滞検知」「delay キュー」などの挙動をログで追う。
Worker 添付抽出・ZIP化・アップロード・共有・DB記録・通知 CPU/IO を食うのはここ。並列数は段階的に上げる。
運用の目安: 最初は Worker の並列数を控えめにし、Nextcloud/DB の I/O を見ながら増やすと事故りにくいです。
7
☁️

Nextcloud 側の事前確認(接続・権限・クォータ)

  • WebDAV/API 認証(アプリパスワード等)が有効
  • 保存先(ユーザー/グループ/フォルダ)とクォータの整合
  • 共有リンクの発行ポリシー(パスワード必須、期限必須など)
  • TLS 証明書(チェーン含む)の妥当性
体験・検証段階では「体験用ユーザー」「体験用フォルダ」で分離しておくと安全です。
8
⚙️

既定ポリシー(最小)

運用として「誰が/どの相手に/どの程度の期限・回数」を標準にするかを先に決めると、現場が混乱しません。

項目推奨初期値メモ
#EXPIRE7日案件クローズ基準で短め。延長は個別上書き。
#LIMIT5回二次配布抑止と利便性のバランス。
#ZIP重要案件は必須パスワード別送の徹底(社内ルール化)。
既定モードcloud(リンク配布)相手ドメインにより zip/off/reply を切替(管理画面/DB)。
9
🧪

試験送受信(コマンド付き)

件名コマンドを使って、ZCM の分岐が意図通りかを確認します。

基本テスト
# 1) ZCM 無効(通常送信)
#OFF 添付テスト(通常送信)

# 2) ZIP化 + リンク配布
#ZIP 添付テスト(ZIPリンク)

# 3) 回数/期限
#ZIP #LIMIT=3 #EXPIRE=3 添付テスト(制限付き)
返信リンク(運用により)
# 4) 返信用アップロードリンク(REPLY)
#REPLY 返信リンク発行テスト

# 5) 複合
#ZIP #REPLY #LIMIT=1 #EXPIRE=1 複合テスト
確認観点: ①通知メール(受信者/送信者)が届くか、②リンクが開くか、③パスワードが通るか、④LIMIT/EXPIRE が効くか、⑤公開停止が効くか。
10
📊

ログ/監視(切り分け最短ルート)

レイヤ見るもの症状の例
Postfix milter 接続/拒否/タイムアウト milter socket へ接続失敗、mail accepted だが ZCM が動かない等
Rspamd reject/soft reject/headers ZCM より前に弾かれている、スコア過大
ClamAV スキャン時間/サイズ上限 大容量で時間切れ、StreamMaxLength で落ちる
ZCM(Dispatcher/Worker) enqueue→processing→done / retry / failed キュー滞留、processing 停止、Nextcloud エラー、DB エラー
Nextcloud WebDAV 応答、ストレージ、クォータ 401/403、507、タイムアウト、共有リンク作成失敗
DB uploads/logs/tokens の更新 アップロードは成功してるのに DB に記録されない等
よくある初期トラブル: 「milter socket の権限」「キュー dir の権限」「Nextcloud 認証」「ClamAV のサイズ/時間制限」「Rspamd で先に reject」。 まずはここを潰すと早いです。
11
🚀

本番導入の進め方(安全な段階導入)

  • Phase 1: submission のみ(社内送信)で適用
  • Phase 2: 特定ドメインのみ cloud/zip を有効(宛先別ポリシー)
  • Phase 3: 全体へ展開(既定 #EXPIRE/#LIMIT を固定)
  • Phase 4: large 経路の最適化(Worker 数・Nextcloud I/O)
運用後は 処理件数 停止件数 エラー率 を月次で振り返り、既定値・ポリシーを最適化しましょう。