メールサーバーの構築(sendmail SASL)

1.なぜsendmailか

sendmailはインターネット上で最もシェアの高いMTAで、アメリカのSendmail社が開発元です。企業が開発を行っていますが、フリーウェアですので無料で使用可能です。sendmailは柔軟かつ強力なMTAで、メインの設定ファイルを正しく設定すればメールに関するほとんどのことが実現可能です。
しかし、かつてsendmailはroot権限で動作していたためセキュリティーホールが見つかった場合に重大な問題に発展する可能性がありました。またメール配送自体もそれほど高速ではないため、大規模なメーリングリストを運用したり、大量にメール配送するには不向きです。
最近では、メール爆弾、スパムメールといった犯罪、または犯罪として認定されつつある行為に利用されてしまうことになります。このようなメールの中継ホストとして利用されると、他のホストやユーザーに大変な迷惑をかける上、サーバーやネットワークのリソースを利用されてしまいます。また、サーバーの所属する組織と管理者の信用を著しく失墜させることになります。管理し切れない方は素直にqmailかpostfixを使用する事をお薦めします。
しかし、sendmailに付随する各種メールに関するソフトはsendmailを基本に作られていることが多いので
ここは素直にsendmailを引き続き使用する事にします。
そのまま使用するのは危険ですので外出先からでも安心して送信できる環境であるSMTP-AUTH(TLS/SSL)を構築します。

2.インストール

FreeBSDの場合、sendmailはデフォルトでインストールされています。
暗号化の為にSASLが必要ですのでportsから一気にインストールしてします。
# cd /usr/ports/security/cyrus-sasl2-saslauthd
# make install clean
これでSASL2もインストールされます

sendmailですが、2種類の方法があります
1つはFreeBSDにデフォルトでインストールされているものを再度コンパイル
もう1つは最新版をportsでインストールしてデフォルトのsendmailはオフするです。

まず再コンパイルのみの場合を説明します。
まず /etc/make.conf に下記を追加します
SENDMAIL_CFLAGS+= -I/usr/local/include -DSASL=2
SENDMAIL_LDFLAGS+= -L/usr/local/lib
SENDMAIL_LDADD+= -lsasl2
そして下記実行
# cd /usr/src/lib/libsm
# make obj && make depend && make
# cd /usr/src/lib/libsmutil
# make obj && make depend && make
# cd /usr/src/usr.sbin/sendmail
# make obj && make depend && make && make install

portsから最新版にする場合は
# cd /usr/ports/mail/sendmail-sasl
# make install clean
これでインストールは完了しますので、デフォルトをOFFするには
webminなどで現在走っているsendmailを停止して
/etc/rc.confに以下の行を追加します
sendmail_enable="NONE"
そして今度はports側のsendmailを起動時でも走るようにします。
# cd /usr/local/etc/rc.d
# cp sendmail.sh.sample sendmail.sh
# /usr/local/etc/rc.d/sendmail.sh start
これで起動します。

このままですと他のアプリケーションなどから /usr/sbin/sendmail をアクセスしてきてしまいます
幸いにもFreeBSDは/usr/sbin/sendmail というのは、実は /usr/sbin/mailwrapper なのです
そしてこのmailwrapperといのは /etc/mail/mailer.conf を見てメーラーを呼び出しています。
ですので、sendmailの場所が変わっただけで有ればこの /etc/mail/mailer.conf を編集すれば今まで通り
/usr/sbin/sendmail を呼び出せば最新のsendmailが走るということです。
では編集します
/etc/mail/mailer.conf
#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

sendmail        /usr/local/sbin/sendmail
send-mail       /usr/local/sbin/sendmail
mailq           /usr/local/sbin/sendmail
newaliases      /usr/local/sbin/sendmail
hoststat        /usr/local/sbin/sendmail
purgestat       /usr/local/sbin/sendmail
これでportsのsendmailが呼び出されるようになります

され、それではsaslを起動させます

/etc/rc.confに追加
saslauthd_enable="YES"
saslauthd_flags="-a pam"
立ち上げます
# /usr/local/etc/rc.d/saslauthd start
これで暗号化関係は準備が整いました

3.CFファイル設定

デフォルトで /etc/mail/freebsd.mc が有りますので、これを編集してしまします
# DAEMON_OPTIONS(`Name=IPv6, Family=inet6, Modifiers=O') IPv6は使用しないのでコメントアウトする
define(`confDONT_BLAME_SENDMAIL',`GroupReadableSASLDBFile')
define(`confAUTH_MECHANISMS', `EXTERNAL GSSAPI DIGEST-MD5 CRAM-MD5 LOGIN PLAIN')
TRUST_AUTH_MECH(`EXTERNAL GSSAPI DIGEST-MD5 CRAM-MD5 LOGIN PLAIN')
define(`confCACERT_PATH', `/etc/mail/certs')dnl
define(`confCACERT', `confCACERT_PATH/cert.pem')dnl
define(`confSERVER_CERT', `confCACERT_PATH/cert.pem')dnl
define(`confSERVER_KEY', `confCACERT_PATH/privkey.pem')dnl
DAEMON_OPTIONS(`Port=smtps, Name=TLSMTA, M=s')dnl
これが基本です
認証方式で本来はDIGEST-MD5 CRAM-MD5があればよいのですが、
設定の少ないメーラーの場合は平文にSSLだけというのを認可しておかないと駄目な場合があるのでLOGINやPLAINなども入れておきます。
またデフォルトで
define(`confCW_FILE', `-o /etc/mail/local-host-names')
が有るのでこれも念のため、作成しています
/etc/mail/local-host-names
localhost
root
それではmcファイルをすべてコメント付きでまとめてみます。 間違っていたら指摘してください。
dnl divert(-1) から divert(0) の間に記述されたものは、sendmail.cf ファイルを作成するときに無視されます。
dnl またdnlから後ろはコメントになります
divert(-1)
divert(0)

dnl VERSIONID,OSTYPE,DOMAIN,MAILERはあらかじめ定義されているマクロのようなもの
VERSIONID(`$FreeBSD: src/etc/sendmail/freebsd.mc,v 1.30.6.1 2006/04/13 04:00:23 gshapiro Exp $')
OSTYPE(freebsd6)
DOMAIN(generic)

dnl access_dbを有効にし、そのデータベースの型と場所が設定されています
dnl -o でファイルがなくてもエラーにしないようにします
FEATURE(access_db, `hash -o -T /etc/mail/access')

dnl /etc/mail/access.dbにメールを受け取らない受信者設定を有効にする
FEATURE(blacklist_recipients)

dnl ブラックリストを利用する、それぞれのサーバーにブラックリストがあります
FEATURE(dnsbl,`bl.spamcop.net', `"550 rejected, see relays bl.spamcop.net"')
FEATURE(dnsbl,`dnsbl.sorbs.net', `"550 rejected, see relays dnsbl.sorbs.net"')
FEATURE(dnsbl,`relays.ordb.org', `"550 rejected, see relays relays.ordb.org"')
FEATURE(dnsbl,`sbl.spamhaus.org', `"550 rejected, see relays sbl.spamhaus.org"')
FEATURE(dnsbl,`blackholes.mail-abuse.org', `"550 rejected, see relays blackholes.mail-abuse.org"')
FEATURE(dnsbl,`dialups.mail-abuse.org', `"550 rejected, see relays dialups.mail-abuse.org"')
FEATURE(dnsbl,`relays.mail-abuse.org', `"550 rejected, see relays relays.mail-abuse.org"')

dnl ローカルのメーラーに対してLMTPを使用することを指定する
FEATURE(local_lmtp)

dnl mailertableを有効にし、そのデータベースの型と場所が設定されています
dnl -o でファイルがなくてもエラーにしないようにします
dnl mailertableはドメインごとの配送テーブル
FEATURE(mailertable, `hash -o /etc/mail/mailertable')

dnl virtusertableを有効にし、そのデータベースの型と場所が設定されています
dnl -o でファイルがなくてもエラーにしないようにします
dnl virtusertableは配送テーブル
FEATURE(virtusertable, `hash -o /etc/mail/virtusertable')

dnl DNSに登録されていないアドレスからのメールも受ける
FEATURE(`accept_unresolvable_domains')dnl

dnl accessファイルでFromを使ったリレーコントロールを可能にする
FEATURE(`relay_mail_from')

dnl ローカルパート部分に ! が含まれる アドレスに対しリレーチェックが行われる
FEATURE(`nouucp',`reject')

dnl To,Ccなども書き替える
FEATURE(`allmasquerade')

dnl ローカル配送されたメールにもドメイン名を付加する
FEATURE(`always_add_domain')

dnl 書き替えるドメインを制限
FEATURE(`limited_masquerade')

dnl ドメインを書き換える設定をしている場合でも、指定されたユーザだけは変更しません
EXPOSED_USER(`root')

dnl 自ホストから出るメールのFromを指定
MASQUERADE_AS(`$m')
dnl ドメイン名がFromに付加される
FEATURE(`masquerade_envelope')

dnl ローカルとして扱うホスト名を表すクラス{w}に/etc/mail/local-host-namesからホスト名を取り込みます
define(`confCW_FILE', `-o /etc/mail/local-host-names')

dnl IPv4をlistenする
DAEMON_OPTIONS(`Name=IPv4, Family=inet')

dnl define(`confBIND_OPTS',`-DNSRCH -DEFNAMES')
dnl ↑が正解かもしれませんが、このコマンドは意味が良く分かりません、名前解決っぽいのですが?
define(`confBIND_OPTS', `WorkAroundBrokenAAAA')

dnl To:ヘッダが付いていない場合に To: undisclosed-recipients:; を付加
define(`confNO_RCPT_ACTION', `add-to-undisclosed')

dnl コマンド規制
dnl VRFY,EXPNコマンドを制限するためにgoawayでまとめても良い
dnl 一般ユーザーにmailqコマンドを実行させないためにrestrictmailqや
dnl sendmail -qを実行させないためにrestrictqrunなどもある
define(`confPRIVACY_FLAGS', `authwarnings,noexpn,novrfy')

dnl FQDNの指定、直接書くか、$w.$mなどになる
define(`confDOMAIN_NAME',`$m')dnl

dnl LMTP機能(ローカルメーラー)の場所設定(必須)
define(`LOCAL_MAILER_PATH', /usr/libexec/mail.local)dnl

dnl LMTP機能(ローカルメーラー)の場所設定(必須)
define(`LOCAL_MAILER_FLAGS', LOCAL_MAILER_FLAGS`'SP)dnl

dnl /etc/mail/trusted-usersに記載されたユーザーはヘッダーに警告が付加されない
define(`_USE_CT_FILE_', `/etc/mail/trusted-users')

dnl SASLライブラリーを利用するようにする
define(`confDONT_BLAME_SENDMAIL',`GroupReadableSASLDBFile')

dnl 走らせるユーザー
define(`confRUN_AS_USER', `smmsp:mail')

dnl SMTP AUTHに対応する
dnl この場合はDIGEST-MD5とCRAM-MD5だが他にもLOGINとPLAINが設定可能
define(`confAUTH_MECHANISMS', `DIGEST-MD5 CRAM-MD5')
TRUST_AUTH_MECH(`DIGEST-MD5 CRAM-MD5')

dnl TLSに対応するため証明書の場所を指定する
define(`confCACERT_PATH', `/etc/mail/certs')
define(`confCACERT', `confCACERT_PATH/cert.pem')
define(`confSERVER_CERT', `confCACERT_PATH/cert.pem')
define(`confSERVER_KEY', `confCACERT_PATH/privkey.pem')

dnl TCP/IPのオプション
dnl 通常は Port=smtp, Nmae=MTA
dnl TLS(465)の時は Port=smtps, Name=TLSMTA, M=s
dnl M=s はMSAの受信対応
dnl またこのオプションは複数行可、その数だけdaemonが動きます
DAEMON_OPTIONS(`Port=smtps, Name=TLSMTA, M=s')

MAILER(local)
MAILER(smtp)
と、こんな感じになった。
まだあるかもしれないので、あとは調べてください。
何かわかったら教えていただけると幸いです。

次に設定したcertを作成します
# cd /etc/mail
# mkdir certs
# chmod 700 certs
# cd certs
# openssl req -new -x509 -nodes -out cert.pem
Generating a 1024 bit RSA private key
.....++++++
.......++++++
writing new private key to 'privkey.pem'
-----
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [AU]:JP
State or Province Name (full name) [Some-State]:県を入力
Locality Name (eg, city) []:市を入力
Organization Name (eg, company) [Internet Widgits Pty Ltd]:未入力でOK
Organizational Unit Name (eg, section) []:未入力でOK
Common Name (eg, YOUR name) []:名前など
Email Address []:メールアドレス
# chmod 600 *.pem

編集できたらwebminのSendmail M4 Configurationを使用してcfファイルを作成してしまいましょう
その際にmcファイルのありかを設定しておくのを忘れないようにしてください
モジュール設定の「Full path to M4 config file」を/etc/mail/freebsd.mcにして

を押して下に有る

を押します、そして

を押せばcfファイル生成でき反映します
あとはsendmailを再起動すればOKです
変更を反映ではなく、バイナリーを再コンパイルしていますので、しっかりと停止して起動しましょう

4.ユーザー追加

saslのデータにユーザーを追加します
# /usr/local/sbin/saslpasswd2 -u ドメイン名 -c ユーザー名
Password: パスワード入力
Again (for verification):パスワード入力

さて、ちゃんと追加されているか確認しましょう
# /usr/local/sbin/sasldblistusers2
で、出て来ます

削除する場合は -c を -d で削除できます

5.qpopperのインストール

sendmailが動いているだけでは送信は可能ですがメールをメーラーで取り込めません。
メールを取り込むにはPOPサーバーとして動かなければなりません。
POPにはqpopperを使用します。
こちらはパッケージで入れて見ます。
# pkg_add -r qpopper

6.qpopperの設定

POPサーバーは普段からデーモンが走っている必要はあまりないので、inetdで起動するようにします。
/etc/inetd.confに追加
pop3 stream tcp nowait root /usr/local/libexec/qpopper qpopper -s

次にユーザー登録をしますが、これはやらなくても大丈夫のような気がします
だいぶ昔にやった覚えが有るのでとりあえず記録として書きますがまずはやらないでトライして見てください
登録はtelnetでおこないます。
# telnet localhost pop3
trying 127.0.0.1...
Connected to localhost.hogehoge.net
Escape character is '^]'.
+OK QPOP (version 4.0.4) at chaco.hayagui.com starting.
user hogeuser ←ユーザー名入力
+OK Password required for ******.
pass hogepass ←パスワード入力
+OK kenz has 0 visible messages (0 hidden) in 0 octets.
quit ←終了の入力
+OK Pop server at chaco.hayagui.com signing off.
Connection closed by foreign host.

7.APOPの設定

POPそのままではユーザーパスが平文で流れるのでとても危険です、暗号化するAPOPを導入して見ます
まずは初期化します
# qpopauth -init
エラーが出る場合は
/usr/local/etc/qpopper
のディレクトリーを作成して下さい

次にユーザー登録をします
# qpopauth -user ユーザー名
Adding only APOP password for ユーザー名.
New password:(ここでパスを打ち込みます)
Retype new password:(もう一度パス入力)
#

8.ログ

このままだと/var/log/messagesに
qpopper[10399]: Stats: user 0 0 0 0 マシンドメイン クライアントIP
というのが、ずらずら出て来てじゃまですので、これを排除します
まず
/etc/syslog.conf に追加
!qpopper
*.* /var/log/qpopper.log

/etc/inetd.conf のqpoperの部分
pop3 stream tcp nowait root /usr/local/libexec/qpopper qpopper
本当は-sを-dにすればいいはずなのですが、なぜかうまくいかず全部取ったらうまくいきました
これでログは
/var/log/qpopper.log
のみになります

9.POPS(TLS/SSL)

さて受信も暗号化しましょう
qpopperだと意外と簡単でした
まず下記ファイルを作成します
/usr/local/etc/qpopper.config
set clear-text-password      = ssl
# この場合はAPOPだけになるので、APOP無しのSSLのみの場合はalwaysにする
set reverse-lookup           = false
set statistics               = true
set timeout                  = 600
set tracefile                = /var/log/qpoppers.log
set tls-support              = alternate-port
set tls-private-key-file     = /etc/mail/certs/privkey.pem
set tls-server-cert-file     = /etc/mail/certs/cert.pem
set shy                      = true

/etc/inetd.conf に追記
pop3s stream tcp nowait root /usr/local/libexec/qpopper -s -f /usr/local/etc/qpopper.config qpopper
これでinetdを起動し直せば終了です

10.メーラーの設定

すべて動いた所でメーラーを設定します
私はBeckyを使用していますのでBeckyで設定を説明します
アカウントの設定を開きます

赤丸のPOP3s?SMTPSへチェックを入れます
APOPまで行った場合は認証方式のAPOPを選んで下さい。
次に詳細タグへ切替えて

SMTPとPOP3のポート番号は自動で切り替わっているのを確認します
そしてSMTP認証とCRAM-MD5をONします
もし、項目4で説明したパスを変えている人はその下のユーザーIDとおパスワードへ入力しましょう
個人個人設定しないで送信は1種類にするという方法もありますね。
あと、SSL/TLS関係では「証明書を検証しない」「クライアント証明を使用」の2点をONにします
自分で作成した証明書なので検証するとエラーします
証明書がタダで証明してくれる所が有ればApacheも含めてスマートにできるんですけどね
と、これでメールを送受信して見ましょう
リレーを許可していなくてもリレー送信できます
もしFirewallを使用している人は上記ポート番号を開ける事を忘れないで下さい。