FreeBSDからメールの配送がうまくいってなかった

1. メールがこない!

現在、いくつかのホストでは監視用にメールを飛ばすようにしてる。これってsmtpでメールサーバを立てて・・・、って訳ではなく、各ホストのsendmailがmailコマンドでメールを投げてくる、という簡単なものだ。

先日メールサーバを移行したのだけれど、このタイミングであるホストからのメールが来なくなった。送りたいメールはローカルのドメイン宛てで、送りたいプログラムはcactiのアラートメール。phpのmailコマンドを呼んでいると思われるのでシステムのmailコマンドを利用しているような気がしてる。

まずはDNSでの名前解決を当たった。というのも、移行された旧メールサーバこそがこのメールが送れなくなったホストであり、ついでにDNSの機能まで積んでいたものだから、そこのMXレコードあたりの参照が出来なくなったんだろう、っていう予測を。

でもMXレコードでローカルのドメインを引いてもちゃんと引けてる。こまったなぁ。

2. メール配送の仕組み

そもそも、メールってどうやって送られるの?ってちょっと疑問に思ってみた。

メールを送るとき、まずはMTUとなるメールクライアントは、最初の踏み台になる中継サーバの25番を開く。そしてメールを送信。次のその踏まれた中継サーバは次なるサーバの25番を開く、と、バケツリレーのごとくメールを配送していく。

なんとなく基本的なところはわかっているつもりだったけど、でもよくわかってない。

で、実際にFreeBSDとかの端末でmailコマンドを打ったらどうなるの、と思って調べてみた。

実はまず前提として、FreeBSDのmailコマンドは他のLinuxのディストリとかとは違って、その実体はメールを実装するパッケージのmailコマンドを指し示していることが多いんだとか。コレはシンボリックリンクで実現されるのではなく、mailコマンドがそれらの実装系のラッパーとなっているような感じらしい。

こういったちょっとややこしいことになった経緯としては、デフォルトでsendmailが使われているんだけれど、いきなりこのコマンドを取っ払ったりしたらmailが送れなくて困ってしまうようなアプリケーションがおおいため、みんなmailコマンドを挟みましょう、ということらしい。

On-line Manual of “mailer.conf” | FreeBSD 日本語マニュアル検索

つまりFreeBSDのmail配送の仕組みっていうのは、mailコマンドを利用する場合、/etc/mail/mailer.conf が結構重要に関わってくるものらしい。

で、早速問題のホストで mailer.conf を見てみた。

shell> cat mailer.conf
#
# Execute the Courier sendmail program, named /usr/local/bin/sendmail
#
sendmail        /usr/local/bin/sendmail
send-mail       /usr/local/bin/sendmail
mailq           /usr/local/bin/mailq
newaliases      /usr/local/sbin/makealiases

みたらばっちり /usr/local/bin のsendmailコマンドになってる。どうやらCourierに置き換えられてしまったらしい。コメントにもそう書いてある。

このままでもいい、のかもしれないけれど、ひとまずコレを元に戻してみる。他のホストから mailer.conf を拾ってきて復元してやる。

shell> cat mailer.conf
# $FreeBSD: src/etc/mail/mailer.conf,v 1.3.36.1.4.1 2010/06/14 02:09:06 kensmith Exp $
#
# Execute the "real" sendmail program, named /usr/libexec/sendmail/sendmail
#
sendmail        /usr/libexec/sendmail/sendmail
send-mail       /usr/libexec/sendmail/sendmail
mailq           /usr/libexec/sendmail/sendmail
newaliases      /usr/libexec/sendmail/sendmail
hoststat        /usr/libexec/sendmail/sendmail
purgestat       /usr/libexec/sendmail/sendmail

これでどうだろう、メールの送信を試してみる・・・

shell> echo ‘hoge’ | mail <a href="mailto:[email protected]">[email protected]</a>

shell> tail /var/log/maillog

Dec  5 11:00:29 mail sendmail[62881]: pB520TPx062881: <a href="mailto:[email protected]">[email protected]</a>, ctladdr=hogetan (1000/1000), delay=00:00:00, xdelay=00:00:00, mailer=relay, pri=30005, relay=[127.0.0.1] [127.0.0.1], dsn=4.0.0, stat=Deferred: Connection refused by [127.0.0.1]
Dec  5 11:02:52 mailsendmail[63524]: pB522qba063524: from=hogetan, size=27, class=0, nrcpts=1, msgid=<a href="mailto:[email protected]">[email protected]</a>, <a href="mailto:[email protected]">[email protected]</a>

送れない。Connection refused by [127.0.0.1] というエラーが出ているようだ。

3. ローカルホストで弾かれてる?

さて、ここでさっきのエラーメッセージを見てみると、ループバックアドレス宛にメールを送ろうとしたらしい。

mailコマンドはローカルホストの25番を開けようとしたのか。ここでちゃんとメールが送れるホストの25番ポートを見てみる。

shell> sockstat | grep sendmail

root     sendmail   9739  4  tcp4   127.0.0.1:25          *:*

どうやらループバックアドレスで”のみ”待ち受けをしているらしい。外向きアドレス(ループバックアドレスではない、LANではプライベートアドレス)では待ち受けをしていないので、他のホストからのメール配送は受け付けないみたい。

ちょっと疑問に思ったのは、一昔前、FreeBSD3とか4とかの時代あたりに入門したとき、rc.confでsendmail=”NONE”にしましょう!踏み台にされないように!とかの記述を見かけて、右も左もわからなかった自分は言われるままにそう設定したりしてた。

最近だとそういった記述も少なくなった(?)ような気がして、設定するのも忘れたりして設定してこなかった。

で、どうやらFreeBSDでメールを送るには、sendmailを立ててないとイケないらしい。

rc.confにはsendmail_enable=”NO”でも構わないのだけれど、sendmail_msp_queue_enableとかが動いてないとmailコマンドがローカルホストに25番でメールを送れないらしい。

どれが本当に必要なのかは面倒なのでやってないけれど、どうやらそのようだ。下記のようにsendmailのプロセスが走っていれば確かにメールが送れる。

shell> ps ax| grep mail
 9739  ??  Ss     0:00.02 sendmail: accepting connections (sendmail)
 9743  ??  Is     0:00.00 sendmail: Queue [email protected]:30:00 for /var/spool/client
 9834  ??  Is     0:00.00 sendmail: Queue [email protected]:30:00 for /var/spool/client
 9876  50  S+     0:00.00 grep mail

で、この辺の起動を司るのはrc.confのsendmail*あたりの設定。デフォルトだとsendmail本体は動かないようになってる。

shell> grep sendmail /etc/defaults/rc.conf
mta_start_script="/etc/rc.sendmail"
# Settings for /etc/rc.sendmail and /etc/rc.d/sendmail:
sendmail_enable="NO"    # Run the sendmail inbound daemon (YES/NO).
sendmail_pidfile="/var/run/sendmail.pid"        # sendmail pid file
sendmail_procname="/usr/sbin/sendmail"          # sendmail process name
sendmail_flags="-L sm-mta -bd -q30m" # Flags to sendmail (as a server)
sendmail_submit_enable="YES"    # Start a localhost-only MTA for mail submission
sendmail_submit_flags="-L sm-mta -bd -q30m -ODaemonPortOptions=Addr=localhost"
sendmail_outbound_enable="YES"  # Dequeue stuck mail (YES/NO).
sendmail_outbound_flags="-L sm-queue -q30m" # Flags to sendmail (outbound only)
sendmail_msp_queue_enable="YES" # Dequeue stuck clientmqueue mail (YES/NO).
sendmail_msp_queue_flags="-L sm-msp-queue -Ac -q30m"
# Flags for sendmail_msp_queue daemon.
sendmail_rebuild_aliases="NO"   # Run newaliases if necessary (YES/NO).

で、結論を言えばメールが送れないホストというのはこの辺の設定が間違っていた。以下はメールが送れないホストのrc.confの設定。

shell> grep sendmail /etc/rc.conf
sendmail_enable="NO"
sendmail_submit_enable="NO"
sendmail_outbound_enable="NO"
sendmail_msp_queue_enable="NO"

これはcourierが25番ポートを利用するため、そこを先にsendmail周りで乗っ取られないように、起動しないように設定されていたものと思われる。

おかげさまでcourierをやめたのでばっちりメールが送れなくなっていたようだ。上記の設定を全てコメントアウトしてsendmailを起動する。

なお、デフォルト通りになるよう、YESにするのではなくコメントアウトにした。

するとメールが送れた!やったね!

4. 最後に

なんとなく今回の件でメール配送の実装系の仕組みがわかった気がした。

/etc/mailあたりをいじればメールのfromが現在おかしい問題(現状だとhostnameの結果ではなく、自ホストをdnsで逆引きした名前になってる)とか、踏み台サーバを指定してメールを配送できたりするのかな、って感じ。

と思ったら後者はすでに自分で調べてた、あらら。

sendmailが次に踏むmtaの指定 | L2TP

でも今回はちょっと疲れたので、その辺はまた元気があるときに。

コメントを残す