概要
3000人程度の利用者に対するメールシステムを、かれこれ12年間、オンプレミスで運用してきたのですけれど、ついに G Suite に移転することになりました。その間に得たノウハウを、このままロストテクノロジーにするのも惜しいので、過去の作業ログの中から、ある程度汎用性がありそうなトピックを取り出して、公開しようと思います。
近年、spam メールが急増しており、なんらかの spam 対策は必須の状況です。もっとも一般的な対策は、商用またはフリーの spam 検出エンジンを導入するという対策になります。しかし、spam 検出エンジンには必ず、誤検出(実際には spam ではないメールを spam と誤って判定する)問題があります。そのため、spam と判定されたメールについても、単に破棄するのではなく、利用者が必要に応じて探し出せる場所(迷惑メールフォルダ)に保存しておくことは必須になります。
また、多くの利用者は、大学のメールサーバに届いたメールを、自分の携帯電話や ISP のメールサーバに転送しています。そのため、多くの携帯電話利用者から「月極め転送容量を無駄遣いしないために、spam は転送しないようにしてほしい」という要望を受けます。
そこで本稿では、
- spam と判定されなかったメールについては、通常のローカル配送(利用者による転送設定による転送を含む)を行う。
- spam と判定されたメールについては、利用者による転送設定を無視して、迷惑メールフォルダへの配送のみを行う。
という設定を説明します。
前提
幾つかの前提があります。
- SMTP は Postfix で処理している。
- IMAP/POP3 は Dovecot で処理している。
- ローカルなメールボックスへの配送(Postfix → Dovecot)は、LMTP で行う。
- ユーザによる転送先設定は LDAP に格納されている。
構成
全体的な構成は、以下の通りです。
-
高度なコンテンツフィルタを利用して、spam メールに
X-Spam-Flag: YES
というヘッダを付加する。 -
X-Spam-Flag: YES
ヘッダを持たないメールは、通常通りにローカル配送を行う。 -
X-Spam-Flag: YES
ヘッダを持つメールは、特別な spam 配送用ドメインに配送する。特別なドメインは、LMTP 配送のみを行う。 -
X-Spam-Flag: YES
ヘッダを持つメールを迷惑メールフォルダに振り分ける処理は、Dovecot IMAP サーバから呼び出された sieve スクリプトが行う。
配送経路を図示すると、以下のようになります。
↓
+-------------+
|smtpd(25/tcp)|
+-------------+
↓
+----------+
|cleanup(a)| (receive_override_options=no_header_body_checks により header_checks 無効)
+----------+
↓
+----+
|scan| (content_filter)
+----+
↓
+--------------+
|spam検出エンジン| (例えば ClamSMTP など)
+--------------+
↓
+----------------+
|smtpd(10025/tcp)|
+----------------+
↓
+----------+ +--------+
|cleanup(b)|→(X-Spam-Flag:YES)→|spamsmtp| (alice@example.jp → alice@spam-forward.example.jp に書き換え)
+----------+ +--------+ (卒業・退職済みアカウント宛は,ここで bounce → discard)
↓ ↓
+-----+ +-----------+ +----------------+
|queue|←|spamcleanup|←|smtpd(10024/tcp)| (receive_override_options=no_header_body_checks により header_checks 無効)
+-----+ +-----------+ +----------------+ (alice@spam-forward.example.jp → alice@example.jp に書き戻し)
↓
内部または外部への配送
設定内容
spam 判定を行う
spam と判定されたメールを spam 配送用ドメインに配送する
ここでは、spam と判定されたメールを、ヘッダおよび本文を変更することなく spam 配送用ドメインに配送し、spam と判定されていないメールは通常配送する設定について述べる。
最初に、X-Spam-Flag: YES
ヘッダを有するメールを spamsmtp 配送に送るように header_checks
オプションを設定する。
header_checks = regexp:/etc/postfix/check_spam_header
/etc/postfix/check_spam_header
の中身は以下の通り。
/^X-Spam-Flag:\s+YES$/ FILTER spamsmtp:[127.0.0.1]:10024
header_checks
オプションや content_filter
オプションによって経路がループにならないように注意が必要。以下のように整理する。
- cleanup(b) のみが
header_checks
オプションによる経路変更を行い、cleanup(a) と spamcleanup はheader_checks
オプションによる経路変更は行わない。 - cleanup(a) のみが
content_filter
オプションによる配送を行い、cleanup(b) と spamcleanup はcontent_filter
オプションによる配送を行わない。
そのため、header_checks
オプションを(原則として)無効化しておく.
receive_override_options = no_header_body_checks
その上で,10025番ポートで待ち受けている smtpd から呼び出される cleanup(b) にのみheader_checks
オプションを有効にするため、receive_override_options
オプションを下記のように上書きしておく。
10025 inet n - n - 64 smtpd
-o syslog_name=postfix/scan
-o content_filter=
-o receive_override_options=no_unknown_recipient_checks,no_address_mappings
-o smtpd_helo_restrictions=
-o smtpd_client_restrictions=
-o smtpd_sender_restrictions=
-o smtpd_recipient_restrictions=permit_mynetworks,reject
-o mynetworks=127.0.0.0/8,133.15.2.64,133.15.2.65
-o smtpd_authorized_xforward_hosts=127.0.0.0/8,133.15.2.0/24
これで、cleanup(b) は header_checks
オプションによるヘッダ検査を行うようになる。
/etc/postfix/check_spam_header
は、X-Spam-Flag: YES
というヘッダを持つメールは spamsmtp 配送に送るよう指定している。spamsmtp 配送は、以下のように定義しておく。
spamsmtp unix - - n - 64 smtp
-o syslog_name=postfix/spam
-o smtp_send_xforward_command=yes
-o smtp_enforce_tls=no
-o smtp_generic_maps=hash:/etc/postfix/spam_forward
-o bounce_service_name=discard
spamsmtp 配送は、smtp_generic_maps
オプションを用いて envelope/header に出現する全ての alice@example.jp を、特別な spam 配送用ドメインのアドレス alice@spam-forward.example.jp に置換する配送である。smtp_generic_maps
オプションに指定されているファイル /etc/postfix/spam_forward
の中身は以下の通り。
@example.jp @spam-forward.example.jp
また、退職・卒業済みアカウントに対する spam は、この段階(spamsmtp → 127.0.0.1:10024)で bounce させる。bounce メールが送信者(つまり spam 送信元)に戻らないように bounce_service_name
オプションを用いて bounce メールを破棄している1。
spamsmtp 配送で書き換えられたメール(すなわち、spam 配送用ドメイン宛のメール)を受け付けるために、10024 番ポートで待ち受ける smtpd を用意する。
127.0.0.1:10024 inet n - n - 64 smtpd
-o syslog_name=postfix/spam
-o content_filter=
-o smtpd_helo_restrictions=
-o smtpd_client_restrictions=
-o smtpd_sender_restrictions=
-o smtpd_recipient_restrictions=permit_mynetworks,reject
-o mynetworks=127.0.0.0/8
-o smtpd_authorized_xforward_hosts=127.0.0.0/8
-o cleanup_service_name=spamcleanup
最後の cleanup_service_name
オプションが重要で、spam 用に特別に用意した spamcleanup 配送に送るように指定している。また、10025 番ポートで待ち受けている smtpd とは異なり、退職・卒業済みアカウントに対する spam を bounce するために、receive_override_options=no_unknown_recipient_checks
は指定していない.
spamcleanup 配送は、spamsmtp 配送によって行われた置換(alice@example.jp → alice@spam-forward.example.jp)の内、不要な置換を書き戻してからキューに投入する配送である。具体的には、以下のように /etc/postfix/master.cf
に定義しておく.
spamcleanup unix n - - - 0 cleanup
-o syslog_name=postfix/spam
-o canonical_classes=envelope_sender,header_sender,header_recipient
-o canonical_maps=hash:/etc/postfix/spam_backward
/etc/postfix/spam_backward
の中身は以下の通り.
@spam-forward.example.jp @example.jp
また、canonical_classes
オプションおよび canonical_maps
オプションによる書き戻しを行わせるため、/etc/postfix/main.cf
に以下の設定が必要.
local_header_rewrite_clients = static:all
なお,spamsmtp 配送の段階で envelope recipient のみを置換(alice@example.jp → alice@spam-forward.example.jp)できれば, spamcleanup 配送で書き戻す処理は不要になる。 かなりマニュアルを調べたが、smtp 配送で使えるアドレス置換用オプションは smtp_generic_maps
のみであり、このオプションは envelope/header の全てを置換してしまうため、やむを得ず spamcleanup 配送で書き戻している。
メールボックスに配送する
ここまでの設定で、
-
X-Spam-Flag: YES
ヘッダを持つメールは、spam-forward.example.jp 宛である。 -
X-Spam-Flag: YES
ヘッダを持たないメールは、example.jp 宛である。
とヘッダの有無に応じて、配送先ドメインが異なるようになっている。よって、後は、各ドメインのためのローカル配送を用意すれば良い。
筆者の場合は、example.jp 宛のメールは local 配送で処理し、spam-forward.example.jp 宛のメールは virtual 配送で処理するという方針を採った。その設定内容は以下の通り。
mydomain = example.jp
mydestination = $myhostname, $mydomain
alias_maps = ldap:/etc/postfix/forward.cf
local_recipient_maps = $mailbox_transport_maps
mailbox_transport_maps =
ldap:/etc/postfix/active_mailbox.cf
ldap:/etc/postfix/expired_mailbox.cf
virtual_mailbox_domains = spam-forward.example.jp
virtual_mailbox_maps = ldap:/etc/postfix/active_mailbox.cf
virtual_transport = lmtp:imap.example.jp:8024
この設定の前半部分は、local 配送に関する部分である。前半部分では、卒業・退職済み利用者宛のメールは転送のみを行うように設定している。
この設定の後半部分は、spam と判定されたメールを配送するための virtual 配送に関する部分である。後半部分の設定は、以下の3つからなる。
- spam 配送用ドメイン spam-forward.example.jp 宛のメールが virtual 配送によって処理されるように、
virtual_mailbox_domains
オプションを設定。 - spam と判定されたメールを受け取るユーザは、
/etc/postfix/active_mailbox.cf
の指定に基づいて現役の利用者のみに限定(言い換えれば、卒業・退職済み利用者宛の spam と判定されたメールは破棄) - virtual 配送に届いたメールは LMTP に転送するように、
virtual_transport
に設定。
-
なお、spam 送信元に bounce メールを返送していると、大規模メールプロバイダ(例えば Yahoo や Google など)によって、spam 中継サーバであると誤判定され、メールをブロックされるトラブルが発生することがある。 ↩