2008年11月28日 14:47

postfixでメールの送信制限をしたい

必要に迫られて、特定のアカウントのメールの送信制限をかけることになった。具体的には、特定のユーザに関して、ドメイン外へのメール送信を禁止したいのだ。

postfixのマニュアルやら、サイトやらを参照すると、restricted_sendersとlocal_domainsいうマッピングファイルを作って *1 、smtpd_sender_restrictions *2 とsmtpd_restriction_classesを書き換えることで、制限できると書いてある。

main.cf:
smtpd_sender_restrictions = check_sender_access hash:/etc/postfix/restricted_senders
smtpd_restriction_classes = local_only
local_only = check_recipient_access hash:/etc/postfix/local_domains,reject

/etc/postfix/restricted_senders:
apache@wildtree.jp local_only

/etc/postfix/local_domains:

wildtree.jp OK

以上のようなファイルを作ったら、MAPを更新して、postfixをreloadしてやる。

# postmap /etc/postfix/restricted_senders
# postmap /etc/postfix/local_domains
# /etc/init.d/postfix reload

と、これで、一応の制限は実現される。が、この制限には抜け道がある。そして、その抜け道こそが、問題なのだ。

一般的に、電子メールの送信は、SMTPを使って行なわれる。これはユーザエンドのMUAからでも大体同じだ。MUAはメールサーバに対して、SMTP接続を開いて、メールを送る。postfixではsmtpdがこれを受け取り、上記のチェックなどをした後に、pickupというデーモンへと処理を引き継ぐ。

ところが、メールサーバ上で動作しているMUAや、デーモンなどがメールを送り出すときには、事情が違ってくることがある。直接、pickupデーモンにメールを渡してしまうことがあるのだ。sendmailを直接叩いたり、/bin/mailを使ったりする場合、また、Wanderlustなどもどうやら、SMTPを使わずに直接pickupへとメールを送り込むようだ。

こういった場合には、最初のチェックが全て抜け落ちてしまうので、折角かけた送信先制限が全く生きないことになってしまう。ほとんどの場合、最初のsmtpdが行なうのはリレーチェックなどなので、ローカルのアカウントがメールを出す場合にそれらのチェックをバイパスされても困らないが、メールの宛先制限をしたい場合には、困ってしまう。

幸いに、うちの場合は、AMAVISによるウィルス/スパムチェックをしているので、pickupデーモンから、メールはAMAVISに渡され、そして、別ポートで待ち受けているsmtpdへと戻され、cleanupデーモンへと流れていく。

この、AMAVISからの戻り待ちのsmtpdに、同様のチェックを行なわせれば、ローカルのユーザからの直接送信にも制限をかけることが出来る。これらの制限は、master.cfに書き込むのだが、master.cfに書くときには、ルールの記述に空白を持たせることが出来ない。出来ないので、ユーザ定義のルールを main.cfに作って、その名前を渡すことで、これを代替することが出来る。

/etc/main.cf: (以下を追記)
# rules for master.cf
check_local_only = check_recipient_access hash:/etc/postfix/local_domains,reject
check_sender_restriction = check_sender_access hash:/etc/postfix/restricted_senders

/etc/master.cf:(下線部を追記)
127.0.0.1:10025 inet    n       -       n       -       -       smtpd
-o content_filter=
-o local_recipient_maps=
-o relay_recipient_maps=
-o smtpd_restriction_classes=local_only
-o local_only=${check_local_only}
-o smtpd_client_restrictions=
-o smtpd_helo_restrictions=
-o smtpd_sender_restrictions=${check_sender_restriction}
-o smtpd_recipient_restrictions=permit_mynetworks,reject
-o mynetworks=127.0.0.0/8
-o strict_rfc821_envelopes=yes
-o smtpd_error_sleep_time=0
-o smtpd_soft_error_limit=1001
-o smtpd_hard_error_limit=1000

これで、あらゆるケースに対して、送信先の制限をかけることが出来るようになる。

ところで、何故、このような制限が必要になったのかを書いておく必要があるだろう。本日未明に、突然、apacheから大量のスパムメールが発信された。全ては、ローカルのapacheが送信しているので、おそらくは、いずれかのサービスにセキュリティホールがあるのだろう。これは別途追求する必要がある。お恥ずかしい話だが、まだ、どれがそうであるのかは掴めていない。SpamAssassinおよびclamavが、スルーしているので、危険性はあまりないかもしれないが、いずれにしても塩梅のいい話ではない。

とりあえず、たまっていたメールは破棄させておいたが、他人様に迷惑がかからないように、apacheのドメイン外送信に枷をはめることにした。これが今回のいきさつだ。

よくよく考えてみると、ほとんどのアカウントは、ドメイン外へメールを送る必然性に欠ける。つまり、この制限は今後、各種、デーモン実行用のアカウントに対して、拡大していくべきであろうかと思う。


*1 : ベツに違う名前でもいいのだが。
*2 : またはsmtpd_recipient_restrictionsでもいいらしい。