flatray.com | 戻る 更新日時: 2022-01-26

milter-greylistで迷惑メール対策

この記事では milter-greylist を使った迷惑メール対策を紹介します。

greylisting とは

greylisting は超簡単に言えば「メールの受信を一旦拒否し、再送してきたら受信する」方法です。 (詳細はちゃんと解説してるサイトを参照してください)

送信元が普通のメールサーバなら再送してくるので若干遅延するだけでメールは届きます。 一方ボットネット等からの送信はまず再送してこない(送信できなければボットネットの他のマシンから送信を試みることが多い)ので、 greylisting するだけで受信自体をいい割合で拒否できます。

ただし一律に greylisting を適用すると正常なメールの受信も遅延しますし送信元にも迷惑がかかります。 またメール事業者によっては送信が拒否されると別のメールサーバ(別のIPアドレス)から再送してくる場合があり、同じIPアドレスからの再送を期待する設定の greylisting とは相性が悪いです。 そのため通常は設定したルールに抵触した送信元に対してだけ greylisting を適用します。 その実装の一つが milter-greylist です。

milter-greylist について

大抵はOSのパッケージで導入できると思いますが、注意点が一つ。 GeoLite2 に対応するためバージョン 4.6.4 (記事執筆時点の最新)かそれ以降を使ってください。 古いパッケージしかない場合は 公式ページ からソースを入手して自分でコンパイルするか、 milter-greylist wiki の Downloads ページ からパッケージを入手してください。

Debian での対応状況は(記事執筆時点の)安定版の Debian 11 (bullseye) は 4.6.2 で残念ながら古いです。 bookworm (testing) では 4.6.4 なので 次の安定版(Debian 12 (bookworm))では 4.6.4 が提供されるでしょう。

私の場合は milter-greylist 本体は自分でコンパイルし、 systemd の設定ファイル等は上記の testing のパッケージから拝借しました。 (コンパイルは難しくありません)

機能

milter-greylist には色々な機能がありますが、今回は以下を紹介します。

末尾に参考の設定ファイルを付けていますが、個々に紹介します。

なお今回はメールの拒否方法として greylisting のみを指定していますが、代わりに blacklist と指定することでとにかく受信を拒否します。 必要に応じて使い分けてください。

postfix との連携

postfix は標準で chroot する設定でしょうから、ソケットの位置を postfix に合わせます。

socket "/var/spool/postfix/var/run/milter-greylist/milter-greylist.sock" 666
user "postfix"

postfix の main.cf の設定例です。

smtpd_milters = { unix:/var/run/milter-greylist/milter-greylist.sock, connect_timeout=1s, default_action=accept }

自分のネットワークやメール事業者をホワイトリストに登録

まずネットワークのリストを定義します。

list "my network" addr { 127.0.0.1/8 192.168.2.0/24 \
xx.xx.xx.xx/xx yyyy:yyyy:yyyy:yyyy::/64 }

list "gmail" addr { \
35.190.247.0/24 \
35.191.0.0/16 \
(中略)
2a00:1450:4000::/36 \
2c0f:fb50:4000::/36 \
}

このリストを使ってホワイトリストに指定します。

racl whitelist list "my network"
racl whitelist list "gmail"

メール事業者のIPアドレスは、メール事業者の公開情報やSPFレコードから確認できます。

DNSRBL での greylisting

DNSRBL (または DNSBL) は超簡単に言えば「迷惑メール送信など悪質なアクセスをしてくるIPアドレスのデータベース」です。 通常は DNS経由で問い合わせます。 誰でも利用可能な形で公開している事業者があるのでそれを利用します。 (なお事業者によってはあまりにもアクセス頻度が高いとブロックされます。その場合は商用版の利用を検討しましょう)

まず利用する DNSRBL を定義します。今回は SORBSBarracuda Reputation Block List (BRBL)SpamCop (Cisco傘下)Spamhaus を利用します。

dnsrbl "SORBS" dnsbl.sorbs.net 127.0.0.0/24
dnsrbl "BRBL" b.barracudacentral.org 127.0.0.0/24
dnsrbl "SpamCop" bl.spamcop.net 127.0.0.0/24
dnsrbl "Spamhaus" zen.spamhaus.org 127.0.0.0/24

ログに出力するため、先にDNSRBLを評価します。 ここではルールに continue を指定しており、特に許可/拒否/greylisting の動作はしません。

racl continue dnsrbl "SORBS"    log "match=R1, ip=%i, geoip=%C, from=%f, to=%r, helo=%h spf=%Qs"
racl continue dnsrbl "BRBL"     log "match=R2, ip=%i, geoip=%C, from=%f, to=%r, helo=%h spf=%Qs"
racl continue dnsrbl "SpamCop"  log "match=R3, ip=%i, geoip=%C, from=%f, to=%r, helo=%h spf=%Qs"
racl continue dnsrbl "Spamhaus" log "match=R4, ip=%i, geoip=%C, from=%f, to=%r, helo=%h spf=%Qs"

そして実際に greylisting を適用します。 複数の DNSRBL にマッチするとログの %D には DNSRBL名が列挙されます。

racl continue log "match_rbl='%D', ip=%i, geoip=%C, from=%f, to=%r, helo=%h spf=%Qs"
racl greylist dnsrbl "SORBS"        msg "Goodbye"
racl greylist dnsrbl "BRBL"         msg "Goodbye"
racl greylist dnsrbl "SpamCop"      msg "Goodbye"
racl greylist dnsrbl "Spamhaus"     msg "Goodbye"

なお善意のメールサーバも迷惑メール送信に悪用されると DNSRBL に登録される時があるので、ここで greylist の代わりに blacklist を指定するのは絶対にやめた方がいいです。

GeoLite2 による国単位での greylisting

GeoLite2 を使い国単位で greylisting も可能です。 この例では CN(中国)と RU(ロシア)に適用しています。

racl continue log "eval=blacklist_geoip, ip=%i, geoip=%C, from=%f, to=%r, helo=%h spf=%Qs"
racl greylist geoip "CN" msg "Goodbye"
racl greylist geoip "RU" msg "Goodbye"

SPF による greylisting

SPF (Sender Policy Framework) は超簡単に言えば、メール送信者が「自分のドメインはこのIPアドレスから送信しますよ」と定義し、受信側はその情報を参照して正規の送信元IPアドレスからのメールか判定する技術です。

SPFは一定の効果は期待できますがそんなに完全ではありません。 しかし milter-greylist の標準動作は SPF判定が pass のメールは自動的に greylisting 対象から外されます。 なのでその挙動を無効にします。

nospf

ログに出力するため、先に SPF を評価します。 ここではルールに continue を指定しており、特に許可/拒否/greylisting の動作はしません。

racl continue spf pass

そして SPF判定が softfail や fail のメールに greylisting を適用します。 これで SPFで判定可能なドメイン詐称メールをブロックできます。

racl continue log "eval=spf, ip=%i, geoip=%C, from=%f, to=%r, helo=%h spf=%Qs"
racl greylist spf softfail delay 2m autowhite 3h msg "Goodbye"
racl greylist spf fail delay 10m autowhite 3h msg "Goodbye"

GeoLite2 による国単位でのホワイトリスト

ここまでふるいにかけたら、後は日本とアメリカぐらいは素直に許可してもいいでしょう。 というわけで GeoLite2 でホワイトリストを適用します。

racl continue log "eval=whitelist_geoip, ip=%i, geoip=%C, from=%f, to=%r, helo=%h spf=%Qs"
racl whitelist geoip "JP"
racl whitelist geoip "US"

ログ出力

milter-greylist は標準で、最終的に適用した greylist.conf の行番号をログに出力します。以下の例の「ACL」の後の数字がそれです。

greylisting 適用例
milter-greylist: (unknown id): addr HOST[IP] from <FROM@example.com> to <TO@example.net> delayed for 00:10:00 (ACL 434)

greylisting バイパス例
milter-greylist: (unknown id): skipping greylist because (from=<FROM@examle.com>, rcpt=<TO@example.net>, addr=HOST[IP]) ACL 459

ただこれだけだとルールがどこまで適用されたのかログを見るだけでは分かりにくいため、判定の各段階でログを出力し分かりやすくしています。 不要だ、ログを減らしたい、等の場合はログを出力するだけのルールは削除しても問題ありません。

設定ファイルの例

実際に私が利用している greylist.conf を簡略化したものです。

pidfile "/var/run/milter-greylist.pid"
dumpfile "/var/lib/milter-greylist/greylist.db" 600
dumpfreq 10m

# postfixと連携するsocket設定
socket "/var/spool/postfix/var/run/milter-greylist/milter-greylist.sock" 666
user "postfix"

# GeoLite2
geoip2db "/usr/share/GeoLite2/GeoLite2-Country.mmdb"

report none
greylist 2m
autowhite 30m
domainexact
nospf
nodrac
multiracl

# 送信元に greylisting の残り時間を返さない設定
quiet

# 自分のネットワーク(自宅など) →ホワイトリストに登録する
list "my network" addr { 127.0.0.1/8 192.168.2.0/24 \
xx.xx.xx.xx/xx yyyy:yyyy:yyyy:yyyy::/64 }

## メール事業者の定義 →ホワイトリストに登録する
# Gmail
list "gmail" addr { \
35.190.247.0/24 \
35.191.0.0/16 \
64.233.160.0/19 \
66.102.0.0/20 \
66.249.80.0/20 \
72.14.192.0/18 \
74.125.0.0/16 \
108.177.8.0/21 \
108.177.96.0/19 \
130.211.0.0/22 \
172.217.0.0/19 \
172.217.32.0/20 \
172.217.128.0/19 \
172.217.160.0/20 \
172.217.192.0/19 \
172.253.56.0/21 \
172.253.112.0/20 \
173.194.0.0/16 \
209.85.128.0/17 \
216.58.192.0/19 \
216.239.32.0/19 \
2001:4860:4000::/36 \
2404:6800:4000::/36 \
2607:f8b0:4000::/36 \
2800:3f0:4000::/36 \
2a00:1450:4000::/36 \
2c0f:fb50:4000::/36 \
}

# Microsoft
list "outlook" addr { \
20.47.149.138/32 \
40.92.0.0/15 \
40.107.0.0/16 \
51.4.72.0/24 \
51.4.80.0/27 \
51.5.72.0/24 \
51.5.80.0/27 \
52.100.0.0/14 \
65.54.51.64/26 \
65.54.61.64/26 \
65.54.121.120/29 \
65.54.190.0/24 \
65.54.241.0/24 \
65.55.33.64/28 \
65.55.34.0/24 \
65.55.52.224/27 \
65.55.78.128/25 \
65.55.81.48/28 \
65.55.90.0/24 \
65.55.94.0/25 \
65.55.111.0/24 \
65.55.113.64/26 \
65.55.116.0/25 \
65.55.126.0/25 \
65.55.174.0/25 \
65.55.178.128/27 \
65.55.234.192/26 \
65.55.238.129/26 \
70.37.151.128/25 \
94.245.112.0/27 \
94.245.112.10/31 \
104.47.0.0/17 \
111.221.23.128/25 \
111.221.26.0/27 \
111.221.66.0/25 \
111.221.69.128/25 \
111.221.112.0/21 \
157.55.0.192/26 \
157.55.1.128/26 \
157.55.2.0/25 \
157.55.9.128/25 \
157.55.11.0/25 \
157.55.49.0/25 \
157.55.61.0/24 \
157.55.157.128/25 \
157.55.225.0/25 \
157.56.24.0/25 \
157.56.232.0/21 \
157.56.240.0/20 \
157.56.248.0/21 \
207.46.4.128/25 \
207.46.50.192/26 \
207.46.50.224 \
207.46.58.128/25 \
207.46.116.128/29 \
207.46.117.0/24 \
207.46.132.128/27 \
207.46.198.0/25 \
207.46.200.0/27 \
207.68.169.173/30 \
207.68.176.0/26 \
207.68.176.96/27 \
213.199.161.128/27 \
213.199.177.0/26 \
2a01:111:f400::/48 \
2a01:111:f403::/48 \
2a01:4180:4050:0400::/64 \
2a01:4180:4050:0800::/64 \
2a01:4180:4051:0400::/64 \
2a01:4180:4051:0800::/64 \
}

# MessageLabs
list "messagelabs" addr { \
46.226.48.0/21 \
67.219.240.0/20 \
85.158.136.0/21 \
95.131.104.0/21 \
103.9.96.0/22 \
117.120.16.0/21 \
193.109.254.0/23 \
194.106.220.0/23 \
195.245.230.0/23 \
216.82.240.0/20 \
}

# DNSRBL の定義
dnsrbl "SORBS" dnsbl.sorbs.net 127.0.0.0/24
dnsrbl "BRBL" b.barracudacentral.org 127.0.0.0/24
dnsrbl "SpamCop" bl.spamcop.net 127.0.0.0/24
dnsrbl "Spamhaus" zen.spamhaus.org 127.0.0.0/24

## ここから実際に評価開始

# まず自分のネットワークを許可
racl whitelist list "my network"

# ログに出力するために先にSPFを評価しておく
racl continue spf pass

# メール事業者のホワイトリスト適用
racl continue log "eval=whitelist_isp, ip=%i, geoip=%C, from=%f, to=%r, helo=%h spf=%Qs"
racl whitelist list "gmail"
racl whitelist list "outlook"
racl whitelist list "messagelabs"

# ログに出力するために先にDNSRBLを評価しておく
racl continue dnsrbl "SORBS"    log "match=R1, ip=%i, geoip=%C, from=%f, to=%r, helo=%h spf=%Qs"
racl continue dnsrbl "BRBL"     log "match=R2, ip=%i, geoip=%C, from=%f, to=%r, helo=%h spf=%Qs"
racl continue dnsrbl "SpamCop"  log "match=R3, ip=%i, geoip=%C, from=%f, to=%r, helo=%h spf=%Qs"
racl continue dnsrbl "Spamhaus" log "match=R4, ip=%i, geoip=%C, from=%f, to=%r, helo=%h spf=%Qs"

# DNSRBLに引っ掛かった送信元は greylisting
racl continue log "match_rbl='%D', ip=%i, geoip=%C, from=%f, to=%r, helo=%h spf=%Qs"
racl greylist dnsrbl "SORBS"        msg "Goodbye"
racl greylist dnsrbl "BRBL"         msg "Goodbye"
racl greylist dnsrbl "SpamCop"      msg "Goodbye"
racl greylist dnsrbl "Spamhaus"     msg "Goodbye"

# GeoLite2 の国コードで greylisting
racl continue log "eval=blacklist_geoip, ip=%i, geoip=%C, from=%f, to=%r, helo=%h spf=%Qs"
racl greylist geoip "CN" msg "Goodbye"
racl greylist geoip "RU" msg "Goodbye"
# 必要に応じて国を適時追加してください

# SPF判定がpassじゃない送信元は greylisting
racl continue log "eval=spf, ip=%i, geoip=%C, from=%f, to=%r, helo=%h spf=%Qs"
racl greylist spf softfail delay 2m autowhite 3h msg "Goodbye"
racl greylist spf fail delay 10m autowhite 3h msg "Goodbye"

# GeoLite2 の国コードのホワイトリスト
racl continue log "eval=whitelist_geoip, ip=%i, geoip=%C, from=%f, to=%r, helo=%h spf=%Qs"
racl whitelist geoip "JP"
racl whitelist geoip "US"

# どれにもマッチしなければ標準の greylisting
racl continue log "eval=default, ip=%i, geoip=%C, from=%f, to=%r, helo=%h spf=%Qs"
racl greylist default

(以上)