sendmail(8.12.x) tune for mail magazine

日付 2007.02.14
タイトル sendmail(8.12.x) tune for mail magazine
本文
RedHat9をベースシステムとして考えています。


[binaryの調整] ================================================
何もしなくても早くなる余地があるので、バイナリはi686でコンパイルしたものを使用
します。
まず、動作に影響の大きいところをダウンロードまたはi686でsrpmからコンパイルして
rpmを差し替えます。

source http://ftp.kddlabs.co.jp/Linux/packages/RedHat/redhat/linux
ダウンロードで差し替え: kernel, glibc
rpmからコンパイル: sysklogd, sendmail

[例 sendmail]
su -
rpmbuild --rebuild --target=i686 sendmail-[version].src.rpm
rpm -ihv --force sendmail-[version].i686.rpm
rpm -ihv --force sendmail-cf-[version].i686.rpm


[ファイルシステムの調整] ======================================
ext3ファイルシステムを使用している時には mount option に noatime と
data=journalを指定します。意外なことですが、clientmqueueへ連続してデータを入れ
ていく場合にはordered, writebackを押しのけてjournalモードが一番パフォーマンス
が良いです。

data=journalはfstabでは(そのままでは)指定できません。ext3は最初にマウントされ
た時のモードをremountで変更することは出来ないようですので、initrdの時点で
journalモードでマウントする必要があります。


su -
export KERN_VER=[kernel version]
mkdir rdimg

# RedHat9, RHEL-3, CentOS-3.xまで
gunzip -c /boot/initrd-$KERN_VER.img > initrd-$KERN_VER
mount -o loop initrd-$KERN_VER rdimg

vi rdimg/linuxrc
>>> root fsをマウントしているところを変更
- mount -o defaults --ro -t ext3 /dev/root /sysroot
+ mount -o defaults,data=journal --ro -t ext3 /dev/root /sysroot
<<<

umount rdimg &&
gzip -c --best initrd-$KERN_VER > initrd-$KERN_VER.img &&
mv /boot/initrd-$KERN_VER.img \
/boot/initrd-$KERN_VER.img.back`date +%Y-%m-%d` &&
mv initrd-$KERN_VER.img /boot/


# RHEL-4, CentOS-4.x, FedoraCore4以降(未テスト)
cd rdimg
gunzip -c /boot/initrd-$KERN_VER.img | cpio -i

vi init
>>> root fsをマウントしているところを変更
- mount -o defaults --ro -t ext3 /dev/root /sysroot
+ mount -o defaults,data=journal --ro -t ext3 /dev/root /sysroot
<<<
find . | cpio -o -c | gzip -c --best > ../initrd-$KERN_VER.img &&
cd .. &&
mv /boot/initrd-$KERN_VER.img \
/boot/initrd-$KERN_VER.img.back`date +%Y-%m-%d` &&
mv initrd-$KERN_VER.img /boot/

# 共通操作に戻る


vi /etc/fstab
>>> noatimeを追加
- LABEL=/ / ext3 defaults 1 1
+ LABEL=/ / ext3 defaults,noatime 1 1
<<<

sync; sync; reboot


[syslogの調整] ================================================
syslogがmail queueまわりと別のディスクに記録できれば良いのですが、出来ない場
合(1Uサーバだと、ね...)にはsyslogを調整することでパフォーマンスがよくなる場合
があります。

>>> vi /etc/syslog.conf # 出力ファイル名の頭に '-' をつけます。
mail.* -/var/log/maillog
<<<

これをすることで、バッファフラッシュを遅延できるので、disk I/Oでのブロックを
減らすことが出来ます。(代わりにクラッシュ時にデータが無くなる可能性が大きいで
す)


[msp周りの調整] ===============================================
いろいろいじる項目があります。
まず、feature/msp.m4 (redhat9だと /usr/share/sendmail-cf/feature/msp.m4)を
いじります。m4したときにmc側で上書きできない値を変更しておきます。

cd /usr/share/sendmail-cf/feature
cp -pi msp.m4 msp.m4.orig
>>> vi msp.m4 # とにかく一度キューイングするようにします。
- define(`confDELIVERY_MODE', `i')
+ define(`confDELIVERY_MODE', `q')
--
-`DAEMON_OPTIONS(`Name=NoMTA, Addr=127.0.0.1, M=E')dnl')
+`DAEMON_OPTIONS(`Name=NoMTA, Addr=127.0.0.1, M=C')dnl')
<<<

その後、submit.mc, sendmail.mcを変更します。sendmailコマンドの実行速度に影響
が大きいのは submit.c のほうらしいです。
21-Jul-2006

cd /etc/mail
>>> vi submit.mc # 差し替えや追加になると思います
dnl DECnet supportはいりません
dnl define(`_USE_DECNET_SYNTAX_', `1')dnl support DECnet

dnl
dnl 状況によっては一度に読み込む量を制限することでファイルシステムのブロック
dnl 時間を減らせます。
define(`confMAX_QUEUE_RUN_SIZE', `1000')dnl
dnl
dnl confQUEUE_SORT_ORDERをTimeベースにしておきます。sqlでドメイン毎にソートし
dnl て出したときに相応の効果が期待できます。
define(`confQUEUE_SORT_ORDER', `Time')dnl
dnl
dnl あまりよくありませんが... SuperSafeをfalseにすると応答性能がよくなります。
define(`confSAFE_QUEUE', `False')dnl
dnl
dnl buffer sizeは十分取っておいたほうが良い結果になるようです。
define(`confDF_BUFFER_SIZE', `65536')dnl
define(`confXF_BUFFER_SIZE', `65536')dnl
dnl
dnl メール配信PGを実行するユーザを追加しておくとチェックが早くなります。
define(`confTRUSTED_USERS', `[deliv_prog_users]')dnl
dnl
dnl 引数の番号はsendmail.mcの値とあわせる必要があります。
define(`confSHARED_MEMORY_KEY', `1')dnl
dnl
dnl ログレベルを減らすことでパフォーマンスが出ます。でも、sendmail.mc側は絶対
dnl に減らしてはいけません。
define(`confLOG_LEVEL', `3')dnl
dnl
dnl mspは第二引数に何も与えないほうが良いパフォーマンスでキューイングできるよ
dnl うに見えました。
FEATURE(`msp', `', `MSA')dnl
<<<
m4 submit.mc > submit.cf


>>> vi sendmail.mc # 差し替えや追加になると思います
dnl
dnl 必要に応じてメールサーバ(このサーバ)のホスト名を指定します。
define(`confDOMAIN_NAME', `[global my host name]')dnl
dnl
dnl ローカルアドレスを外部に出さないように、確実にマスカレードします。
MASQUERADE_AS(`[domain name]')dnl
MASQUERADE_DOMAIN(`[local host name]')dnl
FEATURE(`masquerade_entire_domain')dnl
FEATURE(`limited_masquerade')dnl
FEATURE(`masquerade_envelope')dnl
dnl
dnl こちらはinteractivve modeで動作させます
define(`confDELIVERY_MODE', `i')dnl
dnl
dnl キューイングはinteractiveを使用します。
define(`confSAFE_QUEUE', `interactive')dnl
dnl
dnl 再送信までの時間を指定します。
define(`confMIN_QUEUE_AGE', `11m')dnl
dnl
dnl buffer sizeは十分取っておいたほうが良い結果になるようです。
define(`confDF_BUFFER_SIZE', `65536')dnl
define(`confXF_BUFFER_SIZE', `65536')dnl
dnl
dnl submit.mcと同一のユーザです。
define(`confTRUSTED_USERS', `[deliv_prog_user]')dnl
dnl
dnl 引数の番号はsubmit.mcの値とあわせる必要があります。
define(`confSHARED_MEMORY_KEY', `1')dnl
dnl
dnl 配信出来ないホストに対する接続を抑制します。
define(`confHOST_STATUS_DIRECTORY', `/var/spool/hoststat')dnl
define(`confTO_HOSTSTATUS', `3m')dnl
dnl 重要度高のメール以外警告メールは止め、リターンメールのみにします。
define(`confTO_QUEUEWARN', `0s')dnl
define(`confTO_QUEUEWARN_URGENT', `5m')dnl
define(`confTO_QUEUERETURN', `1d')dnl
dnl
FEATURE(`nocanonify')dnl
dnl
dnl SMTP AUTHを使用した場合、認証されているユーザはLOCAL_RULESETSをパスして許可されます。
FEATURE(`delay_checks')dnl
dnl
dnl EよりもCで動作させた方が早い
DAEMON_OPTIONS(`Name=MTA, Port=smtp, M=C')dnl
DAEMON_OPTIONS(`Name=MSA, Port=submission,Addr=127.0.0.1, M=C')dnl
dnl
dnl 不正なホストからのメールを受け取り拒否します。
dnl sendmail.mcの末尾に追記
dnl
LOCAL_RULESETS
SLocal_check_relay
R$* $: $&{client_resolve}
RTEMP $#error $@ 4.7.1 $: "450 Access denied. Cannot resolve PTR record for " $&{client_addr}
RFAIL $#error $@ 4.7.1 $: "450 Access denied. IP name lookup failed " $&{client_name}
RFORGED $#error $@ 4.7.1 $: "450 Access denied. IP name possibly forged " $&{client_name}
<<<
m4 sendmail.mc > sendmail.cf

# confHOST_STATUS_DIRECTORYで指定したdirです。
mkdir /var/spool/hoststat

# デーモンオプションを変更します。携帯への配信では値が違います。
>>> vi /etc/sysconfig/sendmail
DAEMON=yes
QUEUE=7m
SMQUEUE=11s
<<<


[携帯への配信] ================================================
#
# 携帯キャリアに配信する場合、キュー周りの扱いを変える必要があります。
#
cd /var/spool/mqueue
mkdir -p generic \
docomo.ne.jp \
ezweb.ne.jp \
vodafone.ne.jp/{c,d,h,k,n,q,r,s,t} &&
chown -R root:mail generic docomo.ne.jp ezweb.ne.jp vodafone.ne.jp &&
chmod -R 700 generic docomo.ne.jp ezweb.ne.jp vodafone.ne.jp

cd /etc/mail
>>> vi sendmail.mc
dnl
dnl 携帯キャリア各社以外へのメールをまとめるキューを指定します。
define(`QUEUE_DIR', `/var/spool/mqueue/generic*')dnl
dnl
dnl デーモンのチェック頻度が上がるので、キューのサイズを制限します。
define(`confMAX_QUEUE_RUN_SIZE', `100')dnl
dnl
FEATURE(`queuegroup')dnl
QUEUE_GROUP(`docomo', `P=/var/spool/mqueue/docomo.ne.jp,R=3,F=f,J=10')dnl
QUEUE_GROUP(`ezweb', `P=/var/spool/mqueue/ezweb.ne.jp,R=3,F=f,J=10')dnl
QUEUE_GROUP(`vodafone-c', `P=/var/spool/mqueue/vodafone.ne.jp/c,R=2,F=f,J=10')dnl
QUEUE_GROUP(`vodafone-d', `P=/var/spool/mqueue/vodafone.ne.jp/d,R=2,F=f,J=10')dnl
QUEUE_GROUP(`vodafone-h', `P=/var/spool/mqueue/vodafone.ne.jp/h,R=2,F=f,J=10')dnl
QUEUE_GROUP(`vodafone-k', `P=/var/spool/mqueue/vodafone.ne.jp/k,R=2,F=f,J=10')dnl
QUEUE_GROUP(`vodafone-n', `P=/var/spool/mqueue/vodafone.ne.jp/n,R=2,F=f,J=10')dnl
QUEUE_GROUP(`vodafone-q', `P=/var/spool/mqueue/vodafone.ne.jp/q,R=2,F=f,J=10')dnl
QUEUE_GROUP(`vodafone-r', `P=/var/spool/mqueue/vodafone.ne.jp/r,R=2,F=f,J=10')dnl
QUEUE_GROUP(`vodafone-s', `P=/var/spool/mqueue/vodafone.ne.jp/s,R=2,F=f,J=10')dnl
QUEUE_GROUP(`vodafone-t', `P=/var/spool/mqueue/vodafone.ne.jp/t,R=2,F=f,J=10')dnl
<<<


>>> vi access # watcher2を使用している場合はaccess_default
QGRP:docomo.ne.jp docomo
QGRP:ezweb.ne.jp ezweb
QGRP:c.vodafone.ne.jp vodafone-c
QGRP:d.vodafone.ne.jp vodafone-d
QGRP:h.vodafone.ne.jp vodafone-h
QGRP:k.vodafone.ne.jp vodafone-k
QGRP:n.vodafone.ne.jp vodafone-n
QGRP:q.vodafone.ne.jp vodafone-q
QGRP:r.vodafone.ne.jp vodafone-r
QGRP:s.vodafone.ne.jp vodafone-s
QGRP:t.vodafone.ne.jp vodafone-t
<<<


# デーモンオプションを変更します。
>>> vi /etc/sysconfig/sendmail
DAEMON=yes
QUEUE=7s
SMQUEUE=11s
<<<


[DNS] =========================================================
cache DNSをローカルで動作させます。
軽量レゾルバ(liblwres.so)を組み込むと早くなるのかどうかは検証中。

[その他] ======================================================
sendmail全般に関していえることですが、バーチャル環境で動かすときのホスト名は
ローカル名にしておくほうがよいです。グローバル名を与えていると、同一ホスト内
で、メールを送信するときに名前解決がおかしなことになって大変です。

携帯への大量配送時に、キューランナーのデーモンは別に立ち上げてチェック頻度を
調整するほうが良いかもしれません。


[memo] ========================================================
# コマンドラインオプションでマクロの上書きをするには -o 'M...'とする。
/usr/sbin/sendmail -t -i -o 'Mjlivewell.jp'

# sendmailのローカルの名前解決状況を見る
sendmail -bt -d0,1 < /dev/null

# SMTP AUTHのチェック
>>> vi perl.prog
#!/usr/bin/perl -w
use MIME::Base64;

$U="[user_id]";
$P="[password]";
#printf "$U\0$U\0$P" | openssl base64
print MIME::Base64::encode("$U\0$U\0$P");
<<<


#
# 外部から来たメールをローカルのSMTPサーバへ転送するには
#
cd /etc/mail
>>> vi access
# 以下を追加
mail.domain.name RELAY
<<<
makemap hash access < access # watcher2を使用しているときには access_default

>>> vi mailertable
mail.domain.name smtp:[local.ip.addr]
<<<
makemap hash mailertable < mailertable


#
# メールのリレーチェック
#
http://www.rbl.jp/svcheck.php
http://www.abuse.net/relay.html

#
# cyrus imapd v2を使用する場合
#
以下の設定を追記します。
>>> vi sednmail.mc
dnl
define(`confLOCAL_MAILER', `cyrusv2')dnl
define(`CYRUSV2_MAILER_ARGS', `FILE /var/lib/imap/socket/lmtp')dnl
dnl # .forwardを使用する場合は以下を有効にします。`w'が.forwardのチェックを有効にします。
dnl define(`CYRUSV2_MAILER_FLAGS', `A5@w/:|m')dnl
dnl
<<<


[参考] ========================================================
sendmail official
http://www.sendmail.org/m4/readme.html

和訳
http://www.fujiwara.jp/software/cf/

sendmailの使い方
http://livewell.jp/mente/linux/howto-sendmail.html

CF -R3にFedora Core 3をインストール(cpioフォーマットに関して)
http://t-munu.phys.s.u-tokyo.ac.jp/aso/linux/CF-R3-FC3.html

cpioコマンド
http://www.wakhok.ac.jp/~maruyama/Super/section2.10.4.html

FreeBSD sendmail のセットアップ
http://www.infolab.ne.jp/~hatanou/freebsd/sendmail.html