▼sendmail の _FFR_* で追加できる機能▼

sendmail には、 コンパイル時にのみ指定できる FFR (For Future Release) オプション での追加機能があります。 新しいバージョンでは正式機能に昇格しているものもあります。

$Id: sendmail_ffr.html,v 1.3 2009-12-22 11:49:35+09 kabe Exp $


▼FFRの設定

まずソースのdevtools/Site/site.config.m4に、 必要な -D コンパイル引数を書き込みます。

...
APPENDDEF(`conf_sendmail_ENVDEF', `-D_FFR_BLOCK_PROXIES -D_FFR_TLS_1')
...

あとは普通に cd sendmail; sh ./Build -c にてコンパイル。

▼組込済 FFR の確認

コンパイル済の sendmail などは、-d デバッグオプションで 設定を吐かせます。 sendmail/conf.c に個別に記載が必要なので全部出てくる保証はないですが、 大抵は大丈夫でしょう。

% sendmail -bt -oQ/dev/null -d0.13 < /dev/null | grep FFR
   FFR Defines: _FFR_BLOCK_PROXIES _FFR_TLS_1
% _

FFR一覧

SMTPサーバー設定

_FFR_BLOCK_PROXIES

HTTPのproxy要求に見えるものを拒否します。 HTTP proxy経由でむりやり接続しようとした際に発生します。

% telnet 127.0.0.1 25
Trying 127.0.0.1...
Connected to localhost4.
Escape character is '^]'.
220 mail.host.name ESMTP mail
GET http://www.yahoo.com/ HTTP/1.0
421 4.7.0 mail.host.name Rejecting open proxy localhost4 [127.0.0.1]
Connection closed by foreign host.
% _

Sendmail 8.14.0 では正式対応。

_FFR_TLS_1

SSL (STARTTLS) 機能を強化します。 SSLv2 を無効にするための CipherList オプションを使うために必要。
紛らわしいですが、 SSLv3/TLSv1 はこの FFR をつけなくても 使えます。

sendmail.cf:
O CipherList=DEFAULT:!SSLv2:!MD5

設定する文字列は openssl ciphers(1) を参照。

なお、sendmail.mc の専用defineは無いので、 *.mc に入れたいなら地で直接書く (とsendmail.cfでは変な場所に入る) か、

sendmail.mc:
define(`confSERVER_KEY',  `/etc/mail/server.key
# CipherList support needs -D_FFS_TLS_1 in devtools/Site/site.config.m4
O CipherList=DEFAULT:!SSLv2:!MD5
')dnl
のような姑息な書き方が必要。

_FFR_CRLPATH

無効証明書の検査のための、単一ファイルの O CRLFile= に加え、 ハッシュディレクトリ O CRLPath=/usr/ssl/crl.d を使えるようにします。OpenSSL 0.9.7以降が必要。

_FFR_SOFT_BOUNCE
/* Turn all errors into temporary errors */

O SoftBounce=True オプションを追加。 5xx 5.x.x ステータスを返すところを、問答無用で 4xx 4.x.x ステータスに書き換えます。

Sendmail 8.14.0 では正式対応。

_FFR_MAXNOOPCOMMANDS

/* runtime option for "MaxNOOPCommands" */

O MaxNOOPCommands=20 を追加します。 NOOPとVERBが発行された回数を数え、デフォルトは20回となっている 攻撃緩衝ロジックの回数を調整できます。
Oct 22 17:17:10 mail sendmail[1000]: n9M8GtSJ001000: localhost6 [IPv6:::1]: possible SMTP attack: command=NOOP, count=20

Sendmail 8.14.0 では正式対応。

_FFR_LOG_GREET_PAUSE

FEATURE(`greet_pause', `5000') で SMTPバナーの 遅延をかけているとき、クライアントが待たずに何秒後に喋りだしたかを ログに記録します。 1秒単位、四捨五入。
計時のための gettimeofday(2) は軽くないシステムコールなので、 デフォルトでは計時しない模様。

Sendmail 8.14.0 では正式対応。

_FFR_DM_ONE
/* deliver first TA in background, then queue */

O DeliveryMode=o を使えるようにします。 SMTPで受信している複数の宛先のメールについて、1人目は即配送、 2人目以降はqueueに取り込んで遅延配送します。

DeliveryMode(d) は i (即配送、デフォルト), q (一旦queueに取り込む) などに設定できますが、 o にすると1人目は i, 2人目以降は q 動作になります。 大量配信メーリングリストはqueueに取り込んでバッチ配送、 通常の一対一メールは即配送、という設定ができる。

サーバ全体に対する設定なので注意。(alias毎の設定ではない)

_FFR_DAEMON_NETUNIX

SMTP受信用ポートとして、TCPではない UNIX ソケットを使えるようにします。 F[amily]=local を指定します。

O DaemonPortOptions=Name=MTA-local, Family=local, Addr=/var/run/submit.sock

単独ではあんま用途ないですが、 127.0.0.1:25へのbindもしたくないとか、 そもそも TCP/IP スタックを持ってないとか、 milterを重ねるような使い方で有用?

_FFR_MSG_ACCEPT

SMTP DATA 受信後の、 250 2.0.0 qUEuE1D Message accepted for delivery のメッセージ部分をカスタマイズできるようにします。
デフォルトはO MessageAccept=$&i Message accepted for delivery相当。

_FFR_MAX_SLEEP_TIME

-D_FFR_MAX_SLEEP_TIME=86400 などとすると、 内部で使われる sleep()にこれを超える値が渡された際に 警告ログを出します。(sleep動作は行われる。) GreetPauseに外部マップなどを使用していて、おかしな値が来る可能性の ある時などの保険やデバッグ用と思われます。

_FFR_DOTTED_USERNAMES

RunAsUser と DefaultUser オプションの読み込み時に、 ユーザ名にドットが入っている場合に対応。 デフォルトでは":"と同様、グループ指定との区切りになる。
(一般ユーザへの配送はこのFFRがなくても問題ない、はず)
あんまり O DefaultUser=sendmail.runner:smmsp とかは 指定しないでしょうが、 devtools/OS/MPE-iX で指定があるのでそういうOSのためでしょう。

_FFR_MEMSTAT
メモリ不足のときに SMTP接続拒否や即配送せずqueueに溜めるようにします。 通常の設定でも、 load average に基づいて (QueueLA, RefuseLA) そういう動きをしますが、 同じことを空きメモリで行います。 数値の単位はOSによって違います。(byteだったりkBだったり…)

この機能を使うためには、FFRの他に以下の #define (-DUSESWAPCTL=1など) が必要です。 OSによって自動選択とかは全くやってくれないので、 各自で調べて選んで site.config.m4 に書き込む必要あり。

USESWAPCTL
Solaris の swapctl(2) を使用。
USEKSTAT
Solaris の kstat_open(3KSTAT) を使用。 O MemoryResource=freemem で、 kstat_data_lookup(3KSTAT) で取り出す値を指定できる。 デフォルトは "freemem"
USEPROCMEMINFO
Linux の /proc/meminfo を使用。 MemoryResource 指定も必須だがデフォルト値がない。 O MemoryResource=SwapFree あたりが適当?

ただ、UNIX系のOSでは空きメモリはディスクキャッシュに使われるので、 「空きメモリ」がほとんどない状態が正常です。 あんまり役に立たないかも。

_FFR_PRIV_NOACTUALRECIPIENT
O PrivacyOptions=noactualrecipient を使えるようにします。 エラーメールに X-Actual-Recipient: ヘッダを追加しません。

Sendmail 8.14.0 では正式対応。

SMTPクライアント設定

_FFR_HELONAME

O HeloName=helo.host.nameオプションを追加。 HELOで名乗るホスト名を明示できます。 (sendmail 8.14.0では正式機能に昇格)

_FFR_CLIENT_SIZE

メール送信時、メッセージ長が 宛先サーバの EHLO 応答の SIZE 値より大きかったら 送信をあきらめます。 (つまりデフォルトではSIZEは見てない。) 巨大電文を無駄に送ってしまうのを避けられます。

** NOTE: _FFR_CLIENT_SIZE is untested.
とあるので、実験段階?

_FFR_IGNORE_EXT_ON_HELO

EHLO ではない素の HELO で、SMTPオプション応答があった場合に ログに記録します。 昔のsendmailとかで複数行のSMTPバナーを出している相手の検出用?

_FFR_LOG_NTRIES

配送完了時だけでなく、配送試行毎に ", ntries=回数" の ログを出力します。 配送エラー率の高い宛先の状況を見るのに有用かも。 (Y!Jとか…)

_FFR_CATCH_BROKEN_MTAS

SMTP の DATA送信時、まだ終了の ".\r\n" を送っていないのに MTAが何らかのステータスを返してきたら、ステータス値にかかわらず エラー扱いします。

電文の終了をちゃんと確認しない他MTAの検出用と思われますが、 変な他MTAのデバッグ用か。 実用性は不明。

キュー処理、ルールセット設定

_FFR_SKIP_DOMAINS

queueを処理するときは、通常は頭から順番に (場合によっては何個かおきに) 処理しますが、 メッセージ単位ではなく宛先ドメイン単位で数えます。 特定の宛先ドメインに大量のメールが滞留する場合に、 他の宛先まで遅延してしまうのを緩和できる、かもしれない。

_FFR_HOST_SORT_REVERSE

複数のメールを queue に投入するときは、宛先のホスト名で 並べ替えた順で投入しますが、 ホスト名の末尾からの比較で並べ替えるようにします。 つまり *.co.jp 宛が隣同士になる。 配送性能のチューニングに使えそうですが、

/* XXX maybe compare hostnames from the end? */
なので、効果のほどはさだかではないかも。

_FFR_TRUSTED_QF

通常、queueファイルは RunAsUser (smmspなど) の所有で、 それ以外のownerになっていると色々な警告が出ますが、 aliases の加工などを行う TrustedUser の所有では警告しないようにします。 TrustedUser が滞留 queueの出し入れをするなど、 直接に操作することを想定。

_FFR_CHECK_EOM

DATAの受信後、check_eom ルールセットを起動します。
引数: メッセージ長
MaxMessageSize による制限チェックの後に起動されます。

Sendmail 8.14.0 では正式対応。

_FFR_MAIL_MACRO

$&{mail_from} マクロを使えるようにします。 要するに envelope from ですが、$&f と違い SMTPのMAIL FROM: の値がそのまま参照できます。 (毒入りの可能性があるので注意!)

_FFR_ALIAS_DETAIL

aliases を索く際、map指定にて %0 はユーザ名に置換されますが、 %1 をホスト名に置換できるようにします。 LDAPでaliasesを索くときに役に立つかもしれません。

_FFR_LDAP_VERSION

-D_FFR_LDAP_VERSION=3 で LDAPの接続プロトコルバージョンのデフォルト値を指定。 ldap mapでバージョン指定 -w3 を 毎回明示したくない場合、とか。

_FFR_LDAP_SINGLEDN
        **  The LDAP database map code in Sendmail 8.12.10, when
        **  given the -1 switch, would match only a single DN,
        **  but was able to return multiple attributes for that
        **  DN.  In Sendmail 8.13 this "bug" was corrected to
        **  only return if exactly one attribute matched.
	

sendmail 8.12.10 のLDAP索きバグの互換動作。
LDAPを索いた際、(同一属性名で)複数マッチをさせず 値が1つだけ欲しいときは ldap map の-1 オプションを 使いますが、 8.12.10 では 単一の dn: からは複数返すことができました。 この旧動作が欲しい、dn: をまたぐものは欲しくない、 という場合に、この FFR を入れると -2 オプションが 使えるようになります。

_FFR_MAXDATASIZE

O Milter.macros.maxdatasize=65535 オプションを追加。 milterへ書き出すバッファの最大長を調整します。 デフォルトは 65535。

配送処理

_FFR_MAX_FORWARD_ENTRIES

O MaxForwardEntries=0 オプションを追加。 .forward の転送先の数を制限します。 デフォルトは 0 (制限無し)

_FFR_REDIRECTEMPTY

DSN (エラーメール、差出人が<>) の宛先が alias で、 owner-recipient のaliasも存在する場合は、 メンバーに配信せず owner- に配送します。

DSN (Delivery Status Notification) が通常のメーリングリストに 届くことはない、はず、です。 メーリングリストなら必ず owner-listname: の aliasも作ってあるはずので、 配信時は差出人は owner- に書き換わっており、 エラーは owner- に戻るはず。

素のlistnameに差出人が空のメールを出すのは spamだけだと想定し、配信しない、と。

_FFR_USE_SETLOGIN

配送メーラー起動時に、 setsid(2)+setlogin(2) にて 制御端末をsendmailから切り離します。 全メーラーに適用。

_FFR_DM_PER_DAEMON

O DaemonPortOptions=DeliveryMode=[qdib] が使えるようにします。 daemon毎に、DeliveryMode が変更できます。 Sendmail 8.14.0 以降は正式対応。

なお _FFR_DM_ONE を定義しても o は使えません。 (sendmail/daemon.cをちょこっと改造すればOK)

Sendmail 8.14.2 では正式対応。

_FFR_SS_PER_DAEMON
O DaemonPortOptions=T=[ip] で、 Daemon毎に O SuperSafe オプション相当が指定できます。 "S" は SndBufSizeSize として使われているので、 "T"で指定。 Interactive と PostMilter だけが指定できます。
参照: O DeliveryMode=i[nteractive]


かべ@sra-tohoku.co.jp