3
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

spam と判定されたメールは転送せず、ローカル配送のみを行う

Last updated at Posted at 2019-12-12

概要

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 オプションを設定する。

/etc/postfix/main.cf
header_checks = regexp:/etc/postfix/check_spam_header

/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 オプションを(原則として)無効化しておく.

/etc/postfix/main.cf
receive_override_options = no_header_body_checks

その上で,10025番ポートで待ち受けている smtpd から呼び出される cleanup(b) にのみheader_checks オプションを有効にするため、receive_override_options オプションを下記のように上書きしておく。

/etc/postfix/master.cf
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 配送は、以下のように定義しておく。

/etc/postfix/master.cf
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 の中身は以下の通り。

/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 を用意する。

/etc/postfix/main.cf
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.jpalice@spam-forward.example.jp)の内、不要な置換を書き戻してからキューに投入する配送である。具体的には、以下のように /etc/postfix/master.cf に定義しておく.

/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 の中身は以下の通り.

/etc/postfix/spam_backward
@spam-forward.example.jp     @example.jp

また、canonical_classes オプションおよび canonical_maps オプションによる書き戻しを行わせるため、/etc/postfix/main.cf に以下の設定が必要.

/etc/postfix/main.cf
local_header_rewrite_clients = static:all

なお,spamsmtp 配送の段階で envelope recipient のみを置換(alice@example.jpalice@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 配送で処理するという方針を採った。その設定内容は以下の通り。

/etc/postfix/main.cf
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 に設定。
  1. なお、spam 送信元に bounce メールを返送していると、大規模メールプロバイダ(例えば Yahoo や Google など)によって、spam 中継サーバであると誤判定され、メールをブロックされるトラブルが発生することがある。

3
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?