MailのSPFで困ったことが起こったので検証してみました。

■説明
とあるドメインからメールを受信するとSPFチェックでpassされているはずなのにSPFチェックではじかれてしまう現象が発生した。
悩んで出た結論は、メール最終配送先MTAの前段階(or 段階)でSPFチェックの結果がヘッダに付与されてるんじゃね?と言う事になって検証してみました。
ちなみに、最終受信MTAでのSPF拒否はメールヘッダを見てSPFの「softfail」があれば受信拒否と言う設定にします。
# 一般的な設定だと思ってる :D

■検証図


予想される動きとして

①example4からexample3にメールを送信
②example3がメールを受信後、DNSにFromドメインのTXTレコードを問い合わせにいく。
③結果、FromドメインのTXTレコードに登録されているIPに一致しなかったので「softfail」がメールヘッダに付与される。しかし、example3では受信拒否しない設定になっているとする。example3では受信拒否しないのでそのままexample2にリレーされる。
④example2がメールを受信後、DNSにFromドメインのTXTレコードを問い合わせにいく。
⑤今度は、FromドメインのTXTレコードにIPが登録されていたのでpassが付与される。しかし、softfailがexample3時点で付いているので拒否される。

取りあえず、example4からメールを送信してみた。

■example3のmaillog

Jun 25 23:50:26 example3 postfix/smtpd[20984]: connect from example4.com[192.168.0.73]
Jun 25 23:50:26 example3 postfix/policy-spf[20988]: : SPF softfail (Mechanism '~all' matched): Envelope-from: root@example4.com
Jun 25 23:50:26 example3 postfix/policy-spf[20988]: handler sender_policy_framework: is decisive.
Jun 25 23:50:26 example3 postfix/policy-spf[20988]: : Policy action=PREPEND Received-SPF: softfail (example4.com: Sender is not authorized by default to use 'root@example4.com' in 'mfrom' identity, however domain is not currently prepared for false failures (mechanism '~all' matched)) receiver=example3; identity=mailfrom; envelope-from="root@example4.com"; helo=mail.example4.com; client-ip=192.168.0.73
Jun 25 23:50:26 example3 postfix/smtpd[20984]: 4138E6CB326: client=example4.com[192.168.0.73]
Jun 25 23:50:26 example3 postfix/cleanup[20989]: 4138E6CB326: message-id=<20110625145023.B2E09AF7C3@mail.example4.com>
Jun 25 23:50:26 example3 postfix/qmgr[20630]: 4138E6CB326: from=<root@example4.com>, size=858, nrcpt=1 (queue active)
Jun 25 23:50:26 example3 postfix/smtpd[20984]: disconnect from example4.com[192.168.0.73]
Jun 25 23:50:26 example3 postfix/cleanup[20992]: 4ABCC6CB32A: message-id=<20110625145023.B2E09AF7C3@mail.example4.com>
Jun 25 23:50:26 example3 postfix/qmgr[20630]: 4ABCC6CB32A: from=<root@example4.com>, size=989, nrcpt=1 (queue active)
Jun 25 23:50:26 example3 postfix/local[20990]: 4138E6CB326: to=<root@example3.com>, relay=local, delay=0.2, delays=0.17/0.01/0/0.02, dsn=2.0.0, status=sent (forwarded as 4ABCC6CB32A)
Jun 25 23:50:26 example3 postfix/qmgr[20630]: 4138E6CB326: removed
Jun 25 23:50:26 example3 postfix/smtp[20993]: 4ABCC6CB32A: to=<root@example2.com>, orig_to=<root@example3.com>, relay=example2.com[192.168.0.71]:25, delay=0.18, delays=0/0.01/0.02/0.16, dsn=5.7.1, status=bounced (host example2.com[192.168.0.71] said: 550 5.7.1 message content rejected (in reply to end of DATA command))
Jun 25 23:50:26 example3 postfix/cleanup[20989]: 7BA416CB32E: message-id=<20110625145026.7BA416CB32E@mail.example3.com>
Jun 25 23:50:26 example3 postfix/qmgr[20630]: 7BA416CB32E: from=<>, size=2897, nrcpt=1 (queue active)
Jun 25 23:50:26 example3 postfix/bounce[20995]: 4ABCC6CB32A: sender non-delivery notification: 7BA416CB32E
Jun 25 23:50:26 example3 postfix/qmgr[20630]: 4ABCC6CB32A: removed
Jun 25 23:50:26 example3 postfix/smtp[20993]: 7BA416CB32E: to=<root@example4.com>, relay=example2.com[192.168.0.71]:25, delay=0.01, delays=0.01/0/0/0, dsn=5.7.1, status=bounced (host example2.com[192.168.0.71] said: 554 5.7.1 <root@example4.com>: Relay access denied (in reply to RCPT TO command))
Jun 25 23:50:26 example3 postfix/qmgr[20630]: 7BA416CB32E: removed

うん。
予想通り「softfail」が付与されました。

■example2のmaillog
Jun 25 23:50:26 example2 postfix/smtpd[22550]: connect from example3.com[192.168.0.72]
Jun 25 23:50:26 example2 postfix/policy-spf[22554]: : SPF pass (Mechanism 'ip4:192.168.0.72' matched): Envelope-from: root@example4.com
Jun 25 23:50:26 example2 postfix/policy-spf[22554]: handler sender_policy_framework: is decisive.
Jun 25 23:50:26 example2 postfix/policy-spf[22554]: : Policy action=PREPEND Received-SPF: pass (example4.com: 192.168.0.72 is authorized to use 'root@example4.com' in 'mfrom' identity (mechanism 'ip4:192.168.0.72' matched)) receiver=example2; identity=mailfrom; envelope-from="root@example4.com"; helo=mail.example3.com; client-ip=192.168.0.72
Jun 25 23:50:26 example2 postfix/smtpd[22550]: 9361716705C: client=example3.com[192.168.0.72]
Jun 25 23:50:26 example2 postfix/cleanup[22555]: 9361716705C: reject: header Received-SPF: softfail (example4.com: Sender is not authorized by default to use 'root@example4.com' in 'mfrom' identity, however domain is not currently prepared for false failures (mechanism '~all'  from example3.com[192.168.0.72]; from=<root@example4.com> to=<root@example2.com> proto=ESMTP helo=<mail.example3.com>: 5.7.1 message content rejected
Jun 25 23:50:26 example2 postfix/smtpd[22550]: disconnect from example3.com[192.168.0.72]
Jun 25 23:50:26 example2 postfix/smtpd[22550]: connect from example3.com[192.168.0.72]
Jun 25 23:50:26 example2 postfix/smtpd[22550]: NOQUEUE: reject: RCPT from example3.com[192.168.0.72]: 554 5.7.1 <root@example4.com>: Relay access denied; from=<> to=<root@example4.com> proto=ESMTP helo=<mail.example3.com>
Jun 25 23:50:26 example2 postfix/smtpd[22550]: disconnect from example3.com[192.168.0.72]

次に、example2でpassしているけどexample3でsoftfailが付いちゃってるからheader_checksでREJECTされちゃう(´・ω・`)

うーん。

これの解決策としては

1. SPF自体をやめてしまう。
2. header_checksでのREJECTをやめてしまう。
3. Mail::SPFを改修する。(softfailじゃなくて他の文字を定義する。)


ここでは、「3」の改修を選択することにします。

(1)Mail::SPFをダウンロード
[root@example2 ~]# wget http://search.cpan.org/CPAN/authors/id/J/JM/JMEHNLE/mail-spf/Mail-SPF-v2.007.tar.gz

(2)ダウンロードしたMail-SPF-v2.007.tar.gzを解凍
[root@example2 ~]# tar zxvf Mail-SPF-v2.007.tar.gz

(3)解凍したディレクトリへ移動
[root@example2 ~]# cd Mail-SPF-v2.007

(4)softfailを置換
[root@example2 Mail-SPF-v2.007]# find . -type f -exec sed -i "s/softfail/softfail_example2/g" {} \;
※ここでは「softfail」の代わりに「softfail_example2」を付与することにします。

(5)Mail::SPFをインストール(又は上書きインストール)
[root@example2 Mail-SPF-v2.007]# perl Makefile.PL
# running Build.PL
Created MYMETA.yml and MYMETA.json
Creating new 'Build' script for 'Mail-SPF' version 'v2.7.0'
Dotted-decimal prereq 'v0.002.1' for 'Net::DNS::Resolver::Programmable' is not portable - converting it to '0.002001'
[root@example2 Mail-SPF-v2.007]# make
/usr/bin/perl Build --makefile_env_macros 1
Building Mail-SPF
[root@example2 Mail-SPF-v2.007]# make test
/usr/bin/perl Build --makefile_env_macros 1 test
t/00.00-class-misc.t .......... ok
t/00.01-class-util.t .......... ok
t/00.02-class-request.t ....... ok
t/00.03-class-result.t ........ ok
t/00.04-class-server.t ........ ok
t/00.05-class-macrostring.t ... ok
t/00.99-class-misc.t .......... ok
t/10.00-rfc4408.t ............. skipped: Mail::SPF::Test required for testing Mail::SPF's RFC compliance
t/10.01-rfc4406.t ............. skipped: Mail::SPF::Test required for testing Mail::SPF's RFC compliance
t/90-author-pod-validation.t .. skipped: Test::Pod 1.00 required for testing POD validity
All tests successful.
Files=10, Tests=132,  0 wallclock secs ( 0.05 usr  0.08 sys +  0.54 cusr  0.13 csys =  0.80 CPU)
Result: PASS
[root@example2 Mail-SPF-v2.007]# make install
/usr/bin/perl Build --makefile_env_macros 1 install
Building Mail-SPF
Installing /usr/share/man/man1/spfquery.1
Installing /usr/lib/perl5/site_perl/5.8.8/Mail/SPF/Result.pm
Installing /usr/lib/perl5/site_perl/5.8.8/Mail/SPF/Record.pm
Installing /usr/lib/perl5/site_perl/5.8.8/Mail/SPF/Mech.pm
Installing /usr/lib/perl5/site_perl/5.8.8/Mail/SPF/SenderIPAddrMech.pm
Installing /usr/lib/perl5/site_perl/5.8.8/Mail/SPF/Mech/All.pm
Installing /usr/lib/perl5/site_perl/5.8.8/Mail/SPF/Mech/Include.pm
Installing /usr/share/man/man3/Mail::SPF::Mech::A.3pm
Installing /usr/share/man/man3/Mail::SPF::Term.3pm
Installing /usr/share/man/man3/Mail::SPF::Request.3pm
Installing /usr/share/man/man3/Mail::SPF::Mech::IP4.3pm
Installing /usr/share/man/man3/Mail::SPF::MacroString.3pm
Installing /usr/share/man/man3/Mail::SPF::v2::Record.3pm
Installing /usr/share/man/man3/Mail::SPF::SenderIPAddrMech.3pm
Installing /usr/share/man/man3/Mail::SPF::Mod::Exp.3pm
Installing /usr/share/man/man3/Mail::SPF::Util.3pm
Installing /usr/share/man/man3/Mail::SPF::Server.3pm
Installing /usr/share/man/man3/Mail::SPF::Mod.3pm
Installing /usr/share/man/man3/Mail::SPF::Mech::MX.3pm
Installing /usr/share/man/man3/Mail::SPF::Mech::Exists.3pm
Installing /usr/share/man/man3/Mail::SPF::Record.3pm
Installing /usr/share/man/man3/Mail::SPF::Result.3pm
Installing /usr/share/man/man3/Mail::SPF::Mech.3pm
Installing /usr/share/man/man3/Mail::SPF::v1::Record.3pm
Installing /usr/share/man/man3/Mail::SPF.3pm
Installing /usr/share/man/man3/Mail::SPF::Mech::IP6.3pm
Installing /usr/share/man/man3/Mail::SPF::Mech::All.3pm
Installing /usr/share/man/man3/Mail::SPF::Mech::PTR.3pm
Installing /usr/share/man/man3/Mail::SPF::Mech::Include.3pm
Installing /usr/share/man/man3/Mail::SPF::Base.3pm
Installing /usr/share/man/man3/Mail::SPF::Mod::Redirect.3pm
Installing /usr/sbin/spfd
Installing /usr/bin/spfquery

取りあえず、example2が受信するメールは「softfail」「softfail_example2」が付与されても受信するようにして、maillogを見てましょう。
※DNSのTXTレコードを書き換えてexample3,2のどちらも弱い失敗になるようにする。

■example3 maillog
Jun 26 00:04:41 example3 postfix/smtpd[21024]: connect from example4.com[192.168.0.73]
Jun 26 00:04:41 example3 postfix/policy-spf[21028]: : SPF softfail (Mechanism '~all' matched): Envelope-from: root@example4.com
Jun 26 00:04:41 example3 postfix/policy-spf[21028]: handler sender_policy_framework: is decisive.
Jun 26 00:04:41 example3 postfix/policy-spf[21028]: : Policy action=PREPEND Received-SPF: softfail (example4.com: Sender is not authorized by default to use 'root@example4.com' in 'mfrom' identity, however domain is not currently prepared for false failures (mechanism '~all' matched)) receiver=example3; identity=mailfrom; envelope-from="root@example4.com"; helo=mail.example4.com; client-ip=192.168.0.73
Jun 26 00:04:41 example3 postfix/smtpd[21024]: BBBFB6CB326: client=example4.com[192.168.0.73]
Jun 26 00:04:41 example3 postfix/cleanup[21029]: BBBFB6CB326: message-id=<20110625150439.0138FAF7C3@mail.example4.com>
Jun 26 00:04:41 example3 postfix/qmgr[20630]: BBBFB6CB326: from=<root@example4.com>, size=862, nrcpt=1 (queue active)
Jun 26 00:04:41 example3 postfix/smtpd[21024]: disconnect from example4.com[192.168.0.73]
Jun 26 00:04:41 example3 postfix/cleanup[21029]: BDCB36CB32A: message-id=<20110625150439.0138FAF7C3@mail.example4.com>
Jun 26 00:04:41 example3 postfix/qmgr[20630]: BDCB36CB32A: from=<root@example4.com>, size=993, nrcpt=1 (queue active)
Jun 26 00:04:41 example3 postfix/local[21030]: BBBFB6CB326: to=<root@example3.com>, relay=local, delay=0.02, delays=0.01/0/0/0.01, dsn=2.0.0, status=sent (forwarded as BDCB36CB32A)
Jun 26 00:04:41 example3 postfix/qmgr[20630]: BBBFB6CB326: removed
Jun 26 00:04:41 example3 postfix/smtp[21032]: BDCB36CB32A: to=<root@example2.com>, orig_to=<root@example3.com>, relay=example2.com[192.168.0.71]:25, delay=0.2, delays=0/0/0.02/0.18, dsn=2.0.0, status=sent (250 2.0.0 Ok: queued as 10C9A16705C)
Jun 26 00:04:41 example3 postfix/qmgr[20630]: BDCB36CB32A: removed

■example2 maillog
Jun 26 00:04:41 example2 postfix/smtpd[23091]: connect from example3.com[192.168.0.72]
Jun 26 00:04:42 example2 postfix/policy-spf[23095]: : SPF softfail_example2 (Mechanism '~all' matched): Envelope-from: root@example4.com
Jun 26 00:04:42 example2 postfix/policy-spf[23095]: handler sender_policy_framework: is decisive.
Jun 26 00:04:42 example2 postfix/policy-spf[23095]: : Policy action=PREPEND Received-SPF: softfail_example2 (example4.com: Sender is not authorized by default to use 'root@example4.com' in 'mfrom' identity, however domain is not currently prepared for false failures (mechanism '~all' matched)) receiver=example2; identity=mailfrom; envelope-from="root@example4.com"; helo=mail.example3.com; client-ip=192.168.0.72
Jun 26 00:04:42 example2 postfix/smtpd[23091]: 10C9A16705C: client=example3.com[192.168.0.72]
Jun 26 00:04:42 example2 postfix/cleanup[23096]: 10C9A16705C: message-id=<20110625150439.0138FAF7C3@mail.example4.com>
Jun 26 00:04:42 example2 postfix/qmgr[23089]: 10C9A16705C: from=<root@example4.com>, size=1522, nrcpt=1 (queue active)
Jun 26 00:04:42 example2 postfix/smtpd[23091]: disconnect from example3.com[192.168.0.72]
Jun 26 00:04:42 example2 postfix/local[23097]: 10C9A16705C: to=<root@example2.com>, relay=local, delay=0.19, delays=0.17/0.01/0/0.01, dsn=2.0.0, status=sent (delivered to maildir)
Jun 26 00:04:42 example2 postfix/qmgr[23089]: 10C9A16705C: removed

■受信したメールのヘッダ
Return-Path: <root@example4.com>
X-Original-To: root@example2.com
Delivered-To: root@example2.com
Received-SPF: softfail_example2 (example4.com: Sender is not authorized by default to use 'root@example4.com' in 'mfrom' identity, however domain is not currently prepared for false failures (mechanism '~all' matched)) receiver=example2; identity=mailfrom; envelope-from="root@example4.com"; helo=mail.example3.com; client-ip=192.168.0.72
Received: from mail.example3.com (example3.com [192.168.0.72])
        by mail.example2.com (Postfix) with ESMTP id 10C9A16705C
        for <root@example2.com>; Sun, 26 Jun 2011 00:04:41 +0900 (JST)
Received: by mail.example3.com (Postfix)
        id BDCB36CB32A; Sun, 26 Jun 2011 00:04:41 +0900 (JST)
Delivered-To: root@example3.com
Received-SPF: softfail (example4.com: Sender is not authorized by default to use 'root@example4.com' in 'mfrom' identity, however domain is not currently prepared for false failures (mechanism '~all' matched)) receiver=example3; identity=mailfrom; envelope-from="root@example4.com"; helo=mail.example4.com; client-ip=192.168.0.73
Received: from mail.example4.com (example4.com [192.168.0.73])
        by mail.example3.com (Postfix) with ESMTP id BBBFB6CB326
        for <root@example3.com>; Sun, 26 Jun 2011 00:04:41 +0900 (JST)
Received: from localhost (example4 [127.0.0.1])
        by mail.example4.com (Postfix) with SMTP id 0138FAF7C3
        for <root@example3.com>; Sun, 26 Jun 2011 00:04:24 +0900 (JST)
Message-Id: <20110625150439.0138FAF7C3@mail.example4.com>
Date: Sun, 26 Jun 2011 00:04:24 +0900 (JST)

「softfail_example2」は問題なく付与されている。

これで、header_checksの設定すればいい気がするけど、RFCでは「softfail」って定められていたような・・・。
※取りあえず、コード改修は非推奨。

んー、どうしたものか。

となると、「2」になるのかなぁ(´ω`)


6月 26, 2011 at 12:28 am by 黒ぶちメガネ
Category: Linux, Postfix, spam対策