http://www.sendmail.org/m4/anti_spam.html
ANTI-SPAM (未完)
SPAM 対策
sendmail では主な SPAM 対策の手段として次のものが用意されています。
- 中継は既定値で禁止
- 送信元の検査(確認)強化
- データべース(アクセス表)の利用
- 見出部(header) の検査
中継
つまり自分の機械 (と言ってもクラス{w} で定義しているものを含む)
以外から発信したものを配送することは、
既定で禁止しています。
これは 8.9 以来のことで、それよりも前の版では、既定で許可
になっていました。
もし以前のような動作に戻したい時には
FEATURE(`promiscuous_relay')
と書きます。
あるいは、
RELAY_DOMAIN() や
RELAY_DOMAIN_FILE() を使って クラス{R}にドメイン名や IP アドレスを
加えたり、
後で述べる
ように access_db を使うことで、特定のドメインについては中継を許す
設定が出来ます。内容としては、他のファイル内容の設定の時と同じように
一行に一項目づつ記述します。
sendmail.org
128.32
1:2:3:4:5:6:7
host.mydomain.com
次のように書きますと
FEATURE(`relay_entire_domain')
ローカル・ドメイン、つまりクラス{m} に属する全ての機械の
メールを中継します。
(
これは自ドメインへのメールも、自ドメイン発のものも、
両方受付けます。)
MX 行の、ホスト名の部分が自分向けの時は、全てを中継するというのは次のようにします
FEATURE(`relay_based_on_MX')
例えば
domain.com
の MX が自分の機械を向いていて、
user@domain.com 宛のメールを受取った時にはこれを中継します。
注意しなくてはいけないのは、
確かに スパムを送ろうとしても中継はしないのですが、
もし、部外者が、
MX をあなたの機械に向ければ、そのままで
中継に使われてしまいます。
同じような設定として、
FEATURE(`relay_local_from')
があります。
送信元が Return-Path のドメインをこちらのローカルドメインを
指定すれば (つまり
MAIL FROM: <user@domain>
と言えば)、
中継します。
これは実は大変危険な設定で、単に送信元 (return address)
を、user@your.domain.com と言うだけで中継に使われてしまいます。
したがって、どうしても必要という時以外に使ってはいけません。
もう少し良い設定としては、
FEATURE(`relay_mail_from')
で、送信元が RELAY という名前の表にあれば中継します。
更に domain の引数が付いていれば、
ドメイン部分も調べてから中継を許可します。
この設定は、From: 部分、つまりアクセス表の左半分の設定があって
初めて機能します。
(これについては
微調整
の部分で後述します。)
送信元経路指定 (source routing) が受取人に指定されている場合
(つまり、
RCPT TO: <user%site.com@othersite.com>
となっている場合)、
sendmail は、user@site.com の部分が中継許可の対象になっているかどうか、
つまり、
FEATURE(`relay_entire_domain')
の指定がある場合には、クラス{R} あるいはクラス{m} に含まれるか、
あるいは
FEATURE(`access_db')
の指定の中にあるかを調べます。
宛先が短く変更されてしまわないようにするには、
FEATURE(`loose_relay_check')
とします。
この機能が必要かなと思われる時でも、多分それは間違いのことが殆んどです。
この機能が本当に必要なのは、
中継機能を提供しているのだけれど、
実際には何が通るか良く分らない、制御出来ない、
というような場合です。
これも他の適切な設定なしには、スパム行為を簡単に許してしまうので、
注意して使う必要があります。
【注意】
いくつかの構成では、中継禁止が有効でない場合があります。
FEATURE(`nouucp',`nospecial') (system A)
の設定をしている場合、更には、
次のように
ローカルのメールを メールハブに集めている場合で、
LOCAL_RELAY or LUSER_RELAY) (system B).
次のような設定を全くしていない場合です。
FEATURE(`nouucp')
この場合、
<example.net!user@local.host>
の形をしたメールは、
<user@example.net>
に配送されます。
上記で一番目の
System A は ! を含んだ宛先を認識しないので、メールハブに転送します。
そうしてその後、それをローカルホストからのメールだとして中継とてしまいます。
したがって、
メールサーバが、UUCP 形式の宛先が使えるようにした場合、
他の全ての機械についても、サーバと同じように許可・不許可の設定をする必要
があります。
送信元の確認
8.9 版以来、sendmail は MAIL FROM: で指定されたドメインが存在しない
時には、受取を拒否します。
(
つまりこれは、DNS あるいはその他の名前解決のしくみ、あるいは
ルールセット 3 の例外の設定などでも名前知らずとなった場合のことです。)
このようなメールでも受理したい時、
例えば、防火壁の内側にある機械で、インターネット側の名前空間の一部
しか見えていない場合がこれに当りますが、
( そのような場合、何かかしこいしくみの転送の機械が別にあって初めて、
戻って来るメールを配送出来ます)
その時は、
FEATURE(`accept_unresolvable_domains')
を使います。
sendmail は MAIL FROM: の引数が完全に正当な場合 (FQDN
かつ user も含んでいる場合)
以外は受理しません。
そういうメールも受取りたい時には、次のようにします。
FEATURE(`accept_unqualified_senders')
DaemonPortOptions を u とすると、上記 FEATURE の設定なしでも
既定動作を変更して、受理するように出来ます。
また逆に、FEATURE がない時に、その DaemonPortOptions に f
を付けると、FQDN を要求するようになります。
データべース(アクセス表)
メールの受理・不許可をドメイン毎に設定したい場合、
データべース(アクセス表)を作って設定することが出来ます。
スパム送信元の一覧があって、それに書いてあるものは拒否したい場合、
FEATURE(`access_db')
を使います。この FEATURE 機能は第二引数として、
データべースの形式等を指定出来ます。それには例えば次のようにします。
FEATURE(`access_db', `hash /etc/mail/access')
ここで /etc/mail/access はデータべースであるので、下に説明するように
文字形式のファイルを作った後で、makemap を使って実際のデータべース
形式を作る必要があります。例えば、
makemap hash /etc/mail/access < /etc/mail/access
のようにします。
文字形式の表自体は、下記のように、
e-mail アドレス
ドメイン名
IP アドレスなどを書くことが出来ます。
spammer@aol.com REJECT
cyberspammer.com REJECT
192.168.212 REJECT
こうすると、spammer@aol.com からのメール、 cyberspammer.com から
の全てのユーザ、そうして、192.168.212.* ネットワークの全ての機械
からのメールを拒否します。右側に書ける文字とその意味は次の通り
です。### には数字を書きます。
OK | 全て受取る。他の部分の設定で受取らないとなっていても許可
|
RELAY | 中継する。(受信・送信どちらでもいい)。他での設定に関係なく、OK
の意味を含む
|
REJECT | 汎用のエラーメッセージを示して拒否
|
DISCARD | $#discard メイラを使って、全て拒否。
もし check_compat で指定された時には指定の受取人だけに影響して、
全体には及ばない。本当に必要な時だけ使うこと。
|
### 任意の文字列 |
ここで ### は RFC821 適合の(誤りを示す) 数字で、「任意の文字列」の部分
は結果の表示に使われる。
問題が起きないように引用符で囲んでおくのがいい。
そうでないと空白文字が全て削除されるなどのことが起きる。
|
ERROR:### 任意の文字列 |
上と同じだが、エラーメッセージに使うと良い。
|
ERROR:D.S.N:### 任意の文字列 |
D.S.N ### はRFC 1893 適合のエラーコード。他は上と同じ。
|
実際の設定例としては、次のようになります。
cyberspammer.com ERROR:"550 We don't accept mail from spammers"
okay.cyberspammer.com OK
sendmail.org RELAY
128.32 RELAY
1:2:3:4:5:6:7 RELAY
[127.0.0.3] OK
[1:2:3:4:5:6:7:8] OK
この例では、
okay.cyberspammer.com だけは受取。
cyberspammer.com の、他の機械からはだめ。
sendmail.org ドメインの出入のメールを中継。
128.32.*.* ネットワークの機械の全ての出入のメールを中継。
IPv6 の 1:2:3:4:5:6:7:* のネットワークの機械の全ての出入のメールを中継。
となります。
最後の、二行は、${client_name} の確認に対するもので、
IP アドレスから名前が索けないか、一致しなくて、通常なら
「偽造されている」となる時でも、通すという設定になります。
もし、エラーコードを RFC 821 適合の 550 から変更してしまうと、
RFC 1983 の方も変更する必要があります。例えば、
user@example.com 450 mailbox full
とすると、
"450 4.0.0 mailbox full"
という表示がされて、これは間違っています。
この時は、
"450 4.2.2 mailbox full" か "ERROR:4.2.2:450 mailbox full"
を代りに使う必要があります。
UUCP を使っている場合、hostname.UUCP という名前を
access_db に加えるか、クラス{R}に加える必要があるはずです。
あるいは
FEATURE(`relay_hosts_only')
と書いておけば、sendmail.org という名前の機械については転送を許可
しますが、その他の sendmail.org 内の機械については許可しません。
その場合、クラス{R} に挙げられている名前は FQDN の形式が必要です。
access_db を使えば、逆に、送信元のユーザ名の部分を見て、
それで転送を拒否することも出来ます。例えば次のように書きます。
FREE.STEALTH.MAILER@ ERROR:550 Spam not accepted
ユーザ名の後には @ を付けて、これがユーザ名単位での指定だということを知らせます。
もし次のように書くと、
FEATURE(`blacklist_recipients')
ローカルユーザ、
自分のドメインの機械の名前、
あるいは完全な宛先の形式、
毎に受取らない設定をすることが出来ます。
badlocaluser@ ERROR:550 Mailbox disabled for this username
host.mydomain.com ERROR:550 That host does not accept mail
user@otherhost.mydomain.com ERROR:550 Mailbox disabled for this recipient
上記のように設定すると、
badlocaluser@mydomain.com、
host.mydomain.com の全てのユーザ、
user@otherhost.mydomain.com、
についてはメールを受取りません。
繰返しますが、ユーザ単位の時は @ が必要です。
この機能を使うと、エラーメッセージを返したり、REJECT で拒否したり
出来ます。上の方で示した例を使うと、
spammer@aol.com REJECT
cyberspammer.com REJECT
のようになります。こうすると、
spammer@aol.com や、cyberspammer.com の誰にでもメールを送ることは
出来ません。
MAPS プロジェクト
MAPS プロジェクト (旧
http://maps.vix.com/
)
http://www.mail-abuse.com/
で、
常時更新されている 'Realtime Blackhole List' というものがあります。
これはDNS 内で維持されているスパマーの一覧です。
これを利用するには、
FEATURE(`dnsbl')
と書きます。そうすると、上記データべースに登録されている
地点(site) からのメールを受取りません。
DNS ブラックリストの
既定である
blackholes.mail-abuse.org
は、
MAPS (Mail Abuse Prevent System) で提供されている機能ですが、
2001/07/31 からは登録性のサービスとなり、登録していない
ネットワークアドレスからは、利用出来なくなっています。
登録するには、
(
http://www.mail-abuse.com/
)
にお問合せ下さい。
RBL サーバの代りのものを使いたい時には FEATURE の引数に指定
することが出来ます。
第二引数には文字列を指定出来ます。
既定では、一時的に DNS で見つからない (temporary lookp failure)
という問題は無視されるので、DNS が原因で拒否されるということ
はありません。
第三引数では動作を変更することが出来ます。その場合には
t と書くか、誤り文の全部を書きます。例えば次のようにします。
FEATURE(`dnsbl', `dnsbl.example.com', `',
`"451 Temporary lookup failure for " $&{client_addr} " in dnsbl.example.com"')
もしここに t と指定した場合には、
451 Temporary lookup failure of IP-ADDRESS at SERVER
となります。
この機能を
複数回設定して DNS 理由の拒否が出来ます。つまりこれは
次のダイアルアップのユーザ一覧を使うことを意味します。
http://www.mail-abuse.com/services/mds_dul.html
このしくみで自分自身を拒否してしまうことを避けるために、
次の設定を加えておく必要があります。
Connect:10.1 OK
Connect:127.0.0.1 RELAY
ここで 10.1 は自分のネットワークで、OK と書く代りに RELAY
と書けば、ブラックリストを見て拒否するだけではなく、中継
を出来るようになります。
ここまで説明して来た機能は
check_relay
check_mail
check_rcpt
のルールセットを利用しています
もしこれ以外に、自身で用意したものを使いたい時には、
Local_check_relay
Local_check_mail
Local_check_rcpt
に書いておくことが出来ます。
例えば、ユーザ名が全て数字で出来ているというような場合
(つまり 2312343@bigisp.com のような場合)、
Local_check_mail と、正規表現を使って次のように書きます。
LOCAL_CONFIG
Kallnumbers regex -a@MATCH ^[0-9]+$
LOCAL_RULESETS
SLocal_check_mail
# check address against various regex checks
R$* $: $>Parse0 $>3 $1
R$+ < @ bigisp.com. > $* $: $(allnumbers $1 $)
R@MATCH $#error $: 553 Header Error
check_* ルールセットが呼ばれる
時に対応して、もともとの引数で呼ばれます。
もしこのルールセットが $#OK を返すなら、それ以上の検査は行なわれず、
メールは受理されます。
もしこのルールセットによって、メイラに渡される時、つまり例えば
$#error とか $#discard などになると思いますが、その時には、
それらに対応した処理が行なわれます。
それ以外の場合には、ここでのローカルな書換規則は無視されます。
アクセス表の左項で微調整
この節は
これまでの説明では対応出来ないというような場合にのみ、お読み下さい。
次のような三つのタグを左に付けることが出来ます。
Connect: connection information (${client_addr}, ${client_name})
From: envelope sender
To: envelope recipient
表を参照する時に、まずこれらのタグを付けて一致するか調べ、
その次に(後方互換として)タグ付けないで調べます。例えば、
次のような対応があるとします。
From:spammer@some.dom REJECT
To:friend.domain RELAY
Connect:friend.domain OK
Connect:from.domain RELAY
From:good@another.dom OK
From:another.dom REJECT
(一行目) spammer@some.dom からのメールは拒否しますが、
例え
FEATURE(`blacklist_recipients')
が有効だったとしても、その宛先にメールを送ることは出来ます。
(二行目) friend.domain へのメールは中継しますが、
そこから来るメールは(他に何か許可の設定がない限り)中継しません。
(三行目)
同じドメインからの接続については、例え DNS
原因で拒否されていても許可します。
(四行目)
from.domain からの中継は行いますが、そこへの中継は行いません。
(何故かというと、中継は転送【先】の設定に依存するので Connect:
を使います。
中継について転送【元】の設定については受取人の設定に依存するの
で To: を使います。)
(五六行目)
good@another.dom は受取りますが、同じドメインの他の宛先は全て
拒否します。
Delay all checks
By using
FEATURE(`delay_checks')
the rulesets check_mail and check_relay
will not be called when a client connects or issues a MAIL command,
respectively. Instead, those rulesets will be called by the check_rcpt
ruleset; they will be skipped if a sender has been authenticated using
a "trusted" mechanism, i.e., one that is defined via TRUST_AUTH_MECH().
If check_mail returns an error then the RCPT TO command will be rejected
with that error. If it returns some other result starting with $# then
check_relay will be skipped. If the sender address (or a part of it) is
listed in the access map and it has a RHS of OK or RELAY, then check_relay
will be skipped. This has an interesting side effect: if your domain is
my.domain and you have
my.domain RELAY
in the access map, then all e-mail with a sender address of
<user@my.domain> gets through, even if check_relay would reject it
(e.g., based on the hostname or IP address). This allows spammers
to get around DNS based blacklist by faking the sender address. To
avoid this problem you have to use tagged entries:
To:my.domain RELAY
Connect:my.domain RELAY
if you need those entries at all (class {R} may take care of them).
FEATURE(`delay_checks') can take an optional argument:
FEATURE(`delay_checks', `friend')
enables spamfriend test
FEATURE(`delay_checks', `hater')
enables spamhater test
If such an argument is given, the recipient will be looked up in the access
map (using the tag To:). If the argument is `friend', then the other
rulesets will be skipped if the recipient address is found and has RHS
spamfriend. If the argument is `hater', then the other rulesets will be
applied if the recipient address is found and has RHS spamhater.
This allows for simple exceptions from the tests, e.g., by activating
the spamfriend option and having
To:abuse@ SPAMFRIEND
in the access map, mail to abuse@localdomain will get through. It is
also possible to specify a full address or an address with +detail:
To:abuse@abuse.my.domain SPAMFRIEND
To:me+abuse@ SPAMFRIEND
Header Checks
You can also reject mail on the basis of the contents of headers.
This is done by adding a ruleset call to the 'H' header definition command
in sendmail.cf. For example, this can be used to check the validity of
a Message-ID: header:
LOCAL_RULESETS
HMessage-Id: $>CheckMessageId
SCheckMessageId
R< $+ @ $+ > $@ OK
R$* $#error $: 553 Header Error
The alternative format:
HSubject: $>+CheckSubject
that is, $>+ instead of $>, gives the full Subject: header including
comments to the ruleset (comments in parentheses () are stripped
by default).
A default ruleset for headers which don't have a specific ruleset
defined for them can be given by:
H*: $>CheckHdr
Notice: All rules act on tokens as explained in doc/op/op.{me,ps,txt}.
That may cause problems with simple header checks due to the
tokenization. It might be simpler to use a regex map and apply it
to $&{currHeader}.
After all of the headers are read, the check_eoh ruleset will be called for
any final header-related checks. The ruleset is called with the number of
headers and the size of all of the headers in bytes separated by $|. One
example usage is to reject messages which do not have a Message-Id:
header. However, the Message-Id: header is *NOT* a required header and is
not a guaranteed spam indicator. This ruleset is an example and should
probably not be used in production.
LOCAL_CONFIG
Kstorage macro
LOCAL_RULESETS
HMessage-Id: $>CheckMessageId
SCheckMessageId
# Record the presence of the header
R$* $: $(storage {MessageIdCheck} $@ OK $) $1
R< $+ @ $+ > $@ OK
R$* $#error $: 553 Header Error
Scheck_eoh
# Check the macro
R$* $: < $&{MessageIdCheck} >
# Clear the macro for the next message
R$* $: $(storage {MessageIdCheck} $) $1
# Has a Message-Id: header
R< $+ > $@ OK
# Allow missing Message-Id: from local mail
R$* $: < $&{client_name} >
R< > $@ OK
R< $=w > $@ OK
# Otherwise, reject the mail
R$* $#error $: 553 Header Error
|