text

Postfixのセキュリティ対策

暗号化通信とメールの不正中継の対策


1.メールサーバーの歴史

まずは簡単にメールの歴史を振り返ってみよう。メールが利用され始めたのは 1960年代初頭にマサチューセッツ工科大学で世界最初の電子メールプログラムが開発される。1964年に一部の科学者の間でメールの利用が始まったと言われている。

1972年 BBN 社のレイ・トムリンソン(Ray Tomlinson) が CRYNET と呼ばれるファイル転送プロトコルを利用した最初の電子メール処理用プログラム SNDMSG を開発した。メールアドレスのローカルパートとドメインパートを区切る文字に @ マークを採用したのもレイ・トムリンソンと伝えられている。
その後、メールを送受信するプロトコルが考案されはじめる。

1982年 SMTPが開発
1984年 POPが開発
1985年 POP2が開発
1993年 POP3が開発
1994年 IMAP4が開発

このように、メールのシステムは20年以上も前から使われている非常に歴史のある技術だ。現在、インターネットの世界で使われている技術の中ではきわめて古い技術に分類される。

技術の世界では歴史の長い技術というのはそれだけ安全だ、という評価を受けやすい。多くの人々の評価を受けてきた分、ケーススタディによるノウハウが蓄積されて熟達されている。俗にいう『枯れた技術』というモノで運用面では、非常に安全性が高い、というのが評価の理由だ。

20年以上前に考案されたにも関わらず、別の新技術に指し変わることもなく使用されてきたというのは秀逸だ。さらに、現在ではその利便性から個人・法人問わず欠かすことのできない情報伝達方法となるまでに発展いていることから、斬新な技術だったことが伺える。

コンピュータセキュリティの分野では

歴史のある技術 = 『枯れた技術』 -> 安全性が高い

とは、なり得がたい。
今回取り上げるメールシステムを例に挙げると、メールシステムが考案された当時と現代とでは状況が大きく異なる。
インターネットの普及がはじまった1995年頃からメールシステムに対する様々な攻撃手法が考案され、多くの脆弱性が発見された。
当時どのネットワークでもsendmailというMTA(= Mail Transfer Agent)が使用していた。sendmailは非常に古くからUNIX系ネットワークで使用されてきたMTAで多くの脆弱性を含んでいた。sendmailが最初に開発された当時はコンピュータネットワークの規模は小さく、現代のようなインターネットの普及は全く予想されていなかった。そのため現在のようなセキュリティリスクについて考慮されてはいなかったのは当然のことだ。このことが、QmailやPostfixの開発へとつながっている。

SMTPというプロトコルはインターネットを縦横無尽に横断してノード間で電子メールを送る。送られてきたメールは無条件に受信し、もしそのメールが着信したメールサーバーに登録されているメールアドレスにないモノであれば別のノードに転送して最終的に目的のユーザーに届くようになっている。ネットワークのトポロジィ上で送信者と受信者とのノードが離れていれば、メールはいくつものノード(=コンピュータ)を渡り歩く事になる。メールを転送するためのノードとなるコンピュータはインターネット上にたくさんある。しかも、各々のメールホストのしかるべくポートにアクセスすればユーザー認証なしでログインできてしまう。これが、メールの長所でもあり弱点でもある。
また、MTAはインターネット上でメールの送信を行うためにIPアドレスやホスト名などの情報を公開している。そのため、DoS(=Denial of Service)攻撃の対象になることもあるため、ある程度以上はセキュリティの確保をしておく必要がある。

本章ではPostfixを題材にメールサーバー単独で行う運用上のセキュリティの強化について取り扱っていく。

2.セキュリティ対策(基礎編)− SMTPサーバーの不正利用を防ぐ

メールサーバを運営する際に気をつけなければならないもののひとつとして,メールサーバの不正中継(Third Party Mail Relay,第三者中継)が挙げられる。これは他人の運営しているメールサーバを勝手に使用して大量のスパムなどを送信する不正行為が代表的だ。もし自宅のメールサーバを不正利用された場合,サーバのリソースや回線などを枯渇させるだけでなく、スパムを受信したユーザーからの苦情までも受けなければならなくなる。

本サイトをご覧になられているディープなインターネットユーザーならば、UG(=Under Ground)系サイトというのをご存じだろう。UG系サイトには、不正中継を許可している(=Open Relay)メールサーバのリストを公開しているところもある。もし、そのようなリストに貴殿の管理するサーバが登録された暁には世界各国津々浦々いたるところから不正利用のために接続が繰り返されることになる。

・・・想像だけでも皮膚が泡立つのを覚えるだろう。

メールサーバを運営している場合には,不正中継対策が不可欠だ。

2−1.侵入前調査行為への対策

■ヘッダー情報の隠蔽 <BODY> <P>このページを表示するには、フレームをサポートしているブラウザが必要です。</P> </BODY> <BODY> <P>このページを表示するには、フレームをサポートしているブラウザが必要です。</P> </BODY>

Receivedヘッダとは、メールサーバーを中継するたびにメールのヘッダ部分に追加される。いわば、中継郵便局ごとに押されるスタンプのようなものと考えるとよい。メールの堂堂巡りを防ぐために、メールサーバはReceivedヘッダの数が25個を超えると「ホップカウントオーバー」としてエラー差し戻しを行う。
メーリングリストでは、送信者からメーリングリストサーバを通過してから受信者に到達するまでに多くのメール中継サーバを経由するため、ホップカウントオーバーが起こりやすくなる。例えば、メーリングリストから配信されたメールを別のメールアドレスへと転送をかけたりするととホップカウントオーバーが起こることがある。送信者からメーリングリストサーバまでの経路で付けられたReceivedヘッダを削除することで、「ホップカウントオーバー」が発生しなくなる。

main.cf を編集して、「header_checks = regexp:/etc/postfix/header_checks」を有効にする。

(変更前)

(/etc/postfix/main.cf)
#header_checks = regexp:/etc/postfix/header_checks

(変更後)

(/etc/postfix/main.cf)
header_checks = regexp:/etc/postfix/header_checks

その後、/etc/postfix/header_checks を作成し"/^Received:/ IGNORE"という記述を追加。

# touch /etc/postfix/header_checks

# vi /etc/postfix/header_checks

/^Received:/ IGNORE

header_checks のパーミッションを600にしておく。

注意事項 !

ホップカウントオーバーを防ぐためにReceivedヘッダを削除をすることがあるが、実はこれにはリスクが伴う。もし、登録メンバーが間違って受信メールをメーリングリストに自動転送すれば同じメールが次から次へと配信されることになる。

Receivedヘッダを削除しなければ、いずれホップカウントオーバーが起こって自動的に止まる。また、送信者からメーリングリストサーバまでに付けられたReceivedヘッダを削除すると、不正なメールが投げられた時に送信者を追跡することが困難となる。
最近では、多くのネットワークでメールの中継段数が少なくなっているので、正常な配送でホップカウントオーバーが起こることはほとんどない。どちらかと言えば、より重大な危機を回避するためにReceivedヘッダをあえて残すのが最近の傾向となっている。

■SMTPサーバーのコマンドを無効化

ペネトレーションテストの項目でも述べているが、メールサーバーにコマンドを送り込むことでアカウントの有無の確認をすることができる。対象のサーバーに登録されているアカウントリスト作成はシステム侵入の事前調査としては非常に重要な作業だ。

SMTPサーバーへのコマンドを禁止することで、アカウントリスト作成を防ぐことができる。簡易な作業で非常に有効な対策が講じられるのでぜひ設定を行っておくことをオススメする。

(1) EXPN/VRFYコマンドを拒否

EXPN コマンドによってシステムアカウントの有無を確認することができる。VRFYはメールアカウントが存在するかどうかを確認するもので、存在していればそのユーザー名を表示する。EXPN、VRFYを使うとアカウントの情報が外部から容易に確認することができてしまうため、このような情報はできるなら表示させないように設定することが好ましい。
以下はVRFY コマンドを使ってhogehogeというユーザーが存在するかどうか確認した例。

telnet localhost 25
Trying ::1...
telnet: connect to address ::1: Connection refused
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
220 mail.criterion.sc ESMTP unknown
EHLO localhost
250-mail.criterion.sc
250-PIPELINING
250-SIZE 10485760
250-ETRN
250-STARTTLS
250-AUTH PLAIN LOGIN DIGEST-MD5 CRAM-MD5
250-AUTH=PLAIN LOGIN DIGEST-MD5 CRAM-MD5
250-ENHANCEDSTATUSCODES
250-8BITMIME
250 DSN
VRFY hogehoge
502 hogehoge

VRFYやEXPNコマンドを無効にするには/etc/postfix/main.cfに以下の記述を追記する。

(/etc/postfix/main.cf)

disable_vrfy_command = yes

(2) HELO コマンドの要求

PostfixではSMTP セッションのはじめに HELO (または EHLO) コマンドを要求するかどうかをクライアントに対して決定することができる。/etc/postfix/main.cfの『smtpd_helo_required 』の記述がデフォルトでは、”no”に設定されており、HELOコマンドの使用を要求しない。 HELOコマンドを要求するようにしておくことで止めることができるスパムメールも多々あるので、”yes”に設定しておくのが好ましい。

(変更前)

smtpd_helo_required = no

(変更後)

smtpd_helo_required = yes

(3) Postfix のバージョンを非表示にする

Telnetなどでメールサーバー(=SMTP)にアクセスした際に、サーバーソフト名とバージョン番号が表示されることは、Hackder達にとっては非常に有益な情報となりうる。
サーバーソフト名からはシステムの特徴やオペレーション方法が明らかになり、バージョン番号からはそのソフトにどのような脆弱性が存在するかを割り出すことを可能にする。

インターネットに公開されているメールサーバーはもっともポピュラーな攻撃対象となって久しい。できる限り攻撃のためのヒントとなるような情報をHacker達に渡さないようにすることがセキュリティの第一歩だ。

/etc/postfix/main.cf中の記述で以下のようになっている行のコメントを削除することでPostfix のバージョンを非表示にすることができる。

(作業前)

#smtpd_banner = $myhostname ESMTP $mail_name

(作業後)

smtpd_banner = $myhostname ESMTP

また、"$mail_name"を削除すればPostfix の名前すら表示させないようにすることも可能。

2−2.SPAM用踏み台サーバーとならないための対策

実際にメールサーバーを運用されている方ならば実感されているかと思うが、他人のサーバーに対して”不正中継の試み”をやらかす悪徳インターネットユーザーが非常に多い。
詳細に見ていくと、まったく面識もないようなサーバを踏み台にしてHELOパケットなどを無遠慮うに送りつけているようだ。

このようなヒジョーにマナーの悪いことを行う輩のIPからアクセス元を割り出していくと、大陸からのアクセスがその大部分を占める。さらに言及すれば、国内の民間企業への不正アクセス試行のアクセス元国別ランキングの上位国がそのほとんどを占めている、のはただ呆れるばかりだ。

この問題に対してただ観察するだけではセキュリティリスクの放置に該当し、好ましくない。また、アタックを仕掛けられたから、とアクセス元のIPに対してDoS攻撃を行うのは言語道断だ。

小生はネットワークエンジニアだ。
ネットワークエンジニアとしてこの現状に対して何ができるか。

Postfixは、sendmailの反省を踏まえてイチから開発が行われたMTAだ。そのため、簡単な設定で堅牢な環境が構築できるのが売りだ。基本的な設定に多少手を加えただけの簡単な設定だけでもかなり堅い壁が作れる。

メールの不正中継に関してはPostfixの設定ファイルmain.cf中の”mynetworks”と”relay_domains”等で設定ができてしまうが、Postfixは細やかなセキュリティ設定が出来るように設計されている。このセクションではセキュリティ設定を中心にmain.cfでのSPAM受信拒否やリレーホストの設定について解説していくものとする。

(1)ブラックリストの利用

■送信元・送信者による制限

Postfixではその設定ファイル(=/etc/postfix/main.cf)の記述”smtpd_client_restrictions”送信者制限を行うことができる。自ネットワーク内の送信元は許可しておくが、ブラックリストに登録された送信元からのメールは拒否するように設定しておく。なお、受信者制限は、設定ファイル(=/etc/postfix/main.cf)の記述”smtpd_recipient_restrictions”で指定する。ここでは、中国・韓国(cn-kr)、ブラジル(brazil)、ロシア(russia)からと、ブラックリストに登録された宛先からのメールは全て拒否する。
また、設定ファイル(=/etc/postfix/main.cf)の記述”check_client_access”は、ブラックリストに登録されていないIPアドレスからのメールを拒否する際に必要となる記述だ。

(/etc/postfix/main.cf内の記述)

smtpd_client_restrictions =
permit_mynetworks,
reject_rbl_client relays.ordb.org,
reject_rbl_client spamcop.net,
reject_rbl_client dynablock.wirehub.net,
reject_rbl_client opm.blitzed.org,
reject_rbl_client sbl.spamhaus.org,
reject_rbl_client list.dsbl.org,
reject_rbl_client cn-kr.blackholes.us,
reject_rbl_client brazil.blackholes.us,
reject_rbl_client russia.blackholes.us,
check_client_access hash:/etc/postfix/reject_client,
reject_unknown_client, //逆引きができないホストの接続を拒否
permit

上記にある”check_client_access hash:/etc/postfix/reject_client”はこのままではPostfixを再起動しても有効にはならない。以下の『送信元クライアント(=送信元IPアドレス)による制限』の作業を行う必要がある

■送信元クライアント(=送信元IPアドレス)による制限

/etc/postfix/reject_clientは、ブラックリストには登録されていないIPアドレスを直接指定して受信を拒否するためのファイル。デフォルトでは用意されていないので利用する場合は作成する必要がある。。

# vi/etc/postfix/reject_client

10.0.3.123 REJECT
10.0.3.92 REJECT

上記の設定を反映させるためには postmap を実行する。postmap を実行すると、reject_client.db というDBファイルが作成され、そのDBをPostfix に読み込ませるためにPostfixの再起動を行う。

# postmap /etc/postfix/reject_client
# ls -la /etc/postfix/reject_client.db
-rw-r--r-- 1 root root 12288 Jul 21 16:21 /etc/postfix/reject_client.db
# postfix stop
# postfix start

■送信元ドメインによる制限

Postfixの設定ファイル(/etc/postfix/main.cf)中の記述”smtpd_sender_restrictions”パラメータは MAIL FROM コマンドの送信者アドレスを制限する。”reject_unknown_sender_domain”は、送信者メールアドレスが ”DNS A”または MX レコードを持たない場合に、要求を拒否する。”reject_non_fqdn_sender”は、クライアントの MAIL FROM コマンドのアドレスが FQDN 形式でない場合に要求を拒否する。

以下の記述を設定ファイルに追加する。

# vi /etc/postfix/main.cf

smtpd_sender_restrictions =
hash:/etc/postfix/reject_sender,
reject_unknown_sender_domain,
reject_non_fqdn_sender

上記の設定を有効にするためには、”/etc/postfix/reject_sender”を作成し、制限したいドメインを記述する。その後、postmap を実行してhash を作成。Postfixを再起動させて設定を反映させる。

# vi /etc/postfix/reject_sender

spam@spam.com REJECT
spam.org REJECT

# ls -la /etc/postfix/reject_sender.db
-rw-r--r-- 1 root root 12288 Jul 21 16:47 /etc/postfix/reject_sender.db
# postfix stop
# postfix start

(2)リレー制御

IPアドレスやドメイン、送信元、宛先などの制限無く、誰でも自由にメール送信を依頼することができるメールホストのことを『オープンリレー』と言う。

かつて、インターネットに公開されていたメールホストはオープンリレー方式のものが一般的だった。元来、インターネットの世界と言うのは『自由』・『平等』を善し、とする風潮がある。この風潮は決して悪いものではないが、いつの時代にもどんな状況でも『自由』の意味を履き違える輩はいるものだ。オープンリレーであることを悪用し、まったく面識もない第三者に大量の広告メール(=SPAM)を送信する輩が現れた。

現在ではSPAMがビジネスとして確立している反面、SPAMを受け取るヒトの大部分は多大なる迷惑をこうむっている。そのため、SPAMの温床となるオープンリレーのメールホストは基本的には設定しないことがスタンダードとなっている。

下記の記述を設定ファイルに追記することでオープンリレーを禁止するセキュアなメールホストとなる。

下記の記述は設定ファイル(=/etc/postfix/main.cf)のどこに書いてもよいが、メンテナンスのしやすいように設定ファイルの末尾にコードブロックとしてまとめておく。

#################################
#Blockking invalid Relay
#################################

smtpd_helo_required = yes
disable_vrfy_command = yes
strict_rfc821_envelopes = yes
allow_percent_hack = yes
swap_bangpath = yes
allow_untrusted_routing = no


smtpd_client_restrictions = permit_mynetworks, check_client_access hash:/etc/postfix/restrict_clients, reje
ct_unknown_client, permit
smtpd_helo_restrictions = permit_mynetworks, reject_invalid_hostname, reject_unknown_client, permit
smtpd_recipient_restrictions = permit_mynetworks, permit_sasl_authenticated, permit_auth_destination, reject
#smtpd_sender_restrictions = reject_unknown_sender_domain, reject_sender_login_mismatch
smtpd_sender_restrictions = reject_unknown_sender_domain
smtpd_etrn_restrictions = permit_mynetworks, reject_invalid_hostname

ここまで記述できたら、Postfixを再起動して、変更を反映させる。
サーバーにログインした状態で、コンソールから以下のコマンドを実行すると、メールの不正中継のテストを実施する。

% telnet relay-test.mail-abuse.org

下記が、テストの実行結果。
リレーを許可するような設定になっていると、途中でテストが終了する。

$ telnet relay-test.mail-abuse.org
Trying 168.61.4.13...
Connected to relay-test.mail-abuse.org.
Escape character is '^]'.
Connecting to 220.104.152.105 ...
<<< 220 mail.criterion.sc ESMTP unknown
>>> HELO cygnus.mail-abuse.org
<<< 250 mail.criterion.sc
:Relay test: #Quote test
>>> mail from:
<<< 250 2.1.0 Ok
>>> rcpt to: <"nobody@mail-abuse.org">
<<< 554 5.7.1 : Recipient address rejected: Access denied
>>> rset
<<< 250 2.0.0 Ok
:Relay test: #Test 1
>>> mail from:
<<< 250 2.1.0 Ok
>>> rcpt to:
<<< 554 5.7.1 : Recipient address rejected: Access denied
>>> rset
<<< 250 2.0.0 Ok
:Relay test: #Test 2
>>> mail from:
<<< 250 2.1.0 Ok
>>> rcpt to:
<<< 450 4.1.8 : Sender address rejected: Domain not found
>>> rset
<<< 250 2.0.0 Ok
:Relay test: #test 3
>>> mail from:
<<< 250 2.1.0 Ok
>>> rcpt to:
<<< 554 5.7.1 : Recipient address rejected: Access denied
>>> rset
<<< 250 2.0.0 Ok
:Relay test: #Test 4
>>> mail from:
<<< 250 2.1.0 Ok
>>> rcpt to:
<<< 554 5.7.1 : Recipient address rejected: Access denied
>>> rset
<<< 250 2.0.0 Ok
:Relay test: #Test 5
>>> mail from: <>
<<< 250 2.1.0 Ok
>>> rcpt to:
<<< 554 5.7.1 : Recipient address rejected: Access denied
>>> rset
<<< 250 2.0.0 Ok
:Relay test: #Test 6
>>> mail from:
<<< 250 2.1.0 Ok
>>> rcpt to:
<<< 554 5.7.1 : Recipient address rejected: Access denied
>>> rset
<<< 250 2.0.0 Ok
:Relay test: #Test 7
>>> mail from:
<<< 250 2.1.0 Ok
>>> rcpt to:
<<< 554 5.7.1 : Recipient address rejected: Access denied
>>> rset
<<< 250 2.0.0 Ok
:Relay test: #Test 8
>>> mail from:
<<< 250 2.1.0 Ok
>>> rcpt to:
<<< 554 5.7.1 : Recipient address rejected:
<<< 554 5.7.1 : Recipient address rejected: Access denied
>>> rset
<<< 250 2.0.0 Ok
:Relay test: #Test 9
>>> mail from:
<<< 250 2.1.0 Ok
>>> rcpt to:
<<< 554 5.7.1 : Recipient address rejected: Access denied
>>> rset
<<< 250 2.0.0 Ok
:Relay test: #Test 10
>>> mail from:
<<< 250 2.1.0 Ok
>>> rcpt to: <"nobody@mail-abuse.org">
<<< 554 5.7.1 : Recipient address rejected: Access denied
>>> rset
<<< 250 2.0.0 Ok
:Relay test: #Test 11
>>> mail from:
<<< 250 2.1.0 Ok
>>> rcpt to: <"nobody%mail-abuse.org">
<<< 554 5.7.1 : Recipient address rejected: Access denied
>>> rset
<<< 250 2.0.0 Ok
:Relay test: #Test 12
>>> mail from:
<<< 250 2.1.0 Ok
>>> rcpt to:
<<< 501 5.1.3 Bad recipient address syntax
>>> rset
<<< 250 2.0.0 Ok
:Relay test: #Test 13
>>> mail from:
<<< 250 2.1.0 Ok
>>> rcpt to: <"nobody@mail-abuse.org"@[220.104.152.105]>
<<< 554 5.7.1 : Recipient address rejected: Access denied
>>> rset
<<< 250 2.0.0 Ok
:Relay test: #Test 14
>>> mail from:
<<< 250 2.1.0 Ok
>>> rcpt to:
<<< 554 5.7.1 : Recipient address rejected: Access denied
>>> rset
<<< 250 2.0.0 Ok
:Relay test: #Test 15
>>> mail from:
<<< 250 2.1.0 Ok
>>> rcpt to: <@p2105-ipad73marunouchi.tokyo.ocn.ne.jp:nobody@mail-abuse.org>
<<< 554 5.7.1 : Recipient address rejected: Access denied
>>> rset
<<< 250 2.0.0 Ok
:Relay test: #Test 16
>>> mail from:
<<< 250 2.1.0 Ok
>>> rcpt to: <@[220.104.152.105]:nobody@mail-abuse.org>
<<< 554 5.7.1 : Recipient address rejected: Access denied
>>> rset
<<< 250 2.0.0 Ok
:Relay test: #Test 17
>>> mail from:
<<< 250 2.1.0 Ok
>>> rcpt to:
<<< 554 5.7.1 : Recipient address rejected: Access denied
>>> rset
<<< 250 2.0.0 Ok
:Relay test: #test 18
>>> mail from:
<<< 250 2.1.0 Ok
>>> rcpt to:
<<< 554 5.7.1 : Recipient address rejected: Access denied
>>> rset
<<< 250 2.0.0 Ok
:Relay test: #test 19
>>> mail from:
<<< 250 2.1.0 Ok
>>> rcpt to:
<<< 554 5.7.1 : Recipient address rejected: Access denied
>>> rset
<<< 421 4.7.0 mail.criterion.sc Error: too many errors
Connecting to 220.104.152.105 ...
<<< 220 mail.criterion.sc ESMTP unknown
>>> HELO cygnus.mail-abuse.org
<<< 250 mail.criterion.sc
>>> QUIT
<<< 221 2.0.0 Bye
Tested host banner: 220 mail.criterion.sc ESMTP unknown
System appeared to reject relay attempts
Connection closed by foreign host.

上記のように、19項目のテストが行われた場合はオープンリレーになっている項目がなかったことを示す。

3.セキュリティ対策(発展編)− SMTP AUTH

自宅サーバを外部から利用しないのであれば,ローカルエリアからの接続以外はすべて拒否するように設定を行っておけばいいが,出張先や旅先など,出先から自宅メールサーバを利用してメールを送信したい場合には,すべての接続を拒否しておくと利用できなくなってしまう。

特定のドメインのみで利用可能にするのも効果的だが、メールサーバの不正利用対策として、RFC2554にもあるSMTPサーバに「SMTP Authentication」、「POP before SMTP」などの機能を追加して利用してみてはいかがだろう。このうち今回は,SMTP Authenticationの導入について解説していく。

SMTP Authentication
SMTPへのアクセス時にユーザー認証を行い,許可されたユーザーのみメールの送信を受け付ける。

SMTPサーバでもユーザー名,パスワードにて認証を行う。

3−1.PostfixでのSMTP Authenticationの導入

本講ではSMTPサーバとしてPostfixを利用している場合のSMTP Auth導入について紹介する。今回実装する環境は、ディストリビューションはOpenBSD 4.0,Postfixのバージョンは2.4を使用する。

(1) Cryrus SASLのインストール

PostfixでのSMTP Auth導入には,SASL(Simple Authentication and Security Laye-RFC2222)として”Cyrus SASL”ライブラリを利用する。なお,OpenBSDのPortsパッケージには既にCyrus SASLが組み込まれたPostfixが用意されているのでそれを利用しよう。”Cyrus SASL”導入のために改めてソースファイルからインストールを行うと正常に動作しなくなる事があるので注意しよう。

■パッケージの取得及びインストール

# wget ftp://ftp.openbsd.org/pub/OpenBSD/4.0/packages/i386/postfix-2.4.20060727-sasl2.tgz
# wget ftp://ftp.openbsd.org/pub/OpenBSD/4.0/packages/i386/pcre-6.4p1.tgz

# pkg_add pcre-6.4p1.tgz
# pkg_add postfix-2.4.20060727-sasl2.tgz

インストール後の設定に関しては、OpenBSD編の『Mailサーバーの構築』を参照して欲しい。

(2) Cryrus SASLライブラリの設定

Cryrus SASLのインストールが終わったらCryrus SASLライブラリに関する設定を行う。<BR> Cryrus SASLライブラリはライブラリのインストールディレクトリ以下の『アプリケーション名.conf』ファイルを読み込んで動きが決定される。Postfixの場合、smtpdがCryrus SASLライブラリを扱うため、『/usr/local/lib/sasl2/smtpd.conf』がそれに該当する。

だが、ソースコードやパッケージからインストールした場合、『/usr/local/lib/sasl2/smtpd.conf』は自動作成はされないので下記の操作により作成する。

# touch /usr/local/lib/sasl2/smtpd.conf
# vi /usr/local/lib/sasl2/smtpd.conf

smtpd.confに以下のように記述して、sasldb2を認証に使うようにする。

pwcheck_method: auxprop
auxprop_plugin: sasldb
mech_list: cram-md5 digest-md5 plain login

sasldb2になってからsasldbの時とは記述方法が変わったのでよく注意すること。

(設定パラメータ)

pwcheck_method ・・・認証に何を利用するかを指定します。デフォルトはauxprop。
auxpropの場合、後述するauxprop_pluginで指定する認証プラグインを利用した認証方法をとる。
auxprop以外にはsaslauthdがよく利用される。

auxprop_plugin ・・・ 認証プラグインの指定。デフォルトはsasldb。
mysqlなどのプラグインを指定することもできる。

mech_list ・・・利用可能な認証メカニズムをスペース区切りで記述する。

SMTP AUTHで利用するパスワードを作成する。
ここではSMTP AUTHへのログインパスワードはsasldb2を参照するように設定を行っている。作成したユーザーアカウント,パスワードは,メールアカウントを持つ各ユーザー別に作成して利用する方法のほかに,いくつかのユーザーアカウント,パスワードをSMTP AUTH専用に共有して利用することもできる。

SMTP_AUTHでこのデータベースを利用するためには、Postfixからこのファイルが参照できるようになっている必要があるので、あらかじめファイルの所有者を変更しておく必要がある。

# chown root:_postfix /etc/sasldb2

OpenBSD環境でパッケージからインストールした場合は、 /etc/sasldb2 ではなく、 /etc/sasldb2.db を用いるので以下のようなオペレーションになる。

# chown root:_postfix /etc/sasldb2.db


Postfixからsasldb2(=sasldb2.db)が参照できることが必須条件のため、ファイルの所有者までpostfixにしてしまいがちだ。たしかに、ディストリビューションによっては問題ない場合もあるが、システムの仕様としてsasldb2のファイル所有者はroot、グループをpostfixとすることが前提になっている。

■ユーザの新規登録

SASLの認証データベースにSASLを利用するユーザーとパスワードを登録する。登録の際には下記のような操作を行う。

# saslpasswd2 -u mail.criterion.sc -c hogehoge: <- realmにユーザーアカウントhogehogeと登録
Password: <- パスワードはhackerheheheと入力
Again (for verification): <- パスワードはhackerheheheと入力

また、下記のように操作してもユーザーアカウントとパスワードを登録することができる。

echo "SMTP-AUTHで使用したいパスワード" | saslpasswd2 -p -u mail.criterion.sc -c hogehoge <- realmにユーザーアカウントhogehogeと登録

この方法だと、設定したいパスワードがコンソールに表示されるので入力ミスのチェックができる。 ただし、パスワードが標準出力に表示されてしまうのでこの方法はshellscriptなどで一括処理をするときにのみに使用して欲しい。

上記の操作ではrealmの値をmail.criterion.scとしてユーザhogehogeを新規登録している。realmの値には/etc/postfix/main.cf中の記述『smtpd_sasl_local_domain』に指定した値を指定しなければならない。
上記の例では/etc/postfix/main.cf中の記述で『smtpd_sasl_local_domain = $myhostname』の『$myhostname』の値が『mail.criterion.sc』なのでmail.criterion.scと指定している。

■ユーザの一覧表示

SASLに登録したユーザエントリを一覧は以下のようにして得られる。

# sasldblistusers2
hogehoge@mail.criterion.sc: userPassword
hogehoge@mail.criterion.sc: cmusaslsecretOTP

■ユーザのパスワード変更

既に登録済みのユーザのパスワードを変更する場合は-cオプションは必要なく、以下のように実行します。

# saslpasswd2 -u mail.criterion.sc hogehoge

■ ユーザの削除

登録したユーザを削除する場合は-dオプションを利用します。

# saslpasswd2 -u mail.criterion.sc -d hogehoge

ここまででSASL側の設定は終了。
(3)からはSMTPサーバー側の設定を行う。


上記の例で作成したSASL用のユーザーアカウントやパスワードはsasldb2というバークレイ形式のデーターベースファイルに格納される。ただし、OpenBSD環境にパッケージからインストールした場合は、/etc/sasldb2.db というデータベースファイルも自動的に作成されている。
OpenBSDのPortsパッケージでPostfixやSASL2をインストールされている場合は、Postfix自体がjail化されているため標準的なsasldb2ではなく、/etc/sasldb2.db が使用される。

(3) 認証SMTPサーバーにするための設定

SASL設定が完了したら、次にPostfixの設定が必要となる。そのためにはPostfixからSASLの認証メカニズムを利用するために、『/etc/postfix/main.cf』の末尾(=最後尾のリレー制御の記述の直前)に以下のコードブロックを追記する必要がある。

#============================================================================
# SMTP_AUTH(cyrus=sasl)の設定
#=============================================================================

#-----------------------------------------------------------------------------
# smtpd_sasl_auth_enable = SASLによるSMTP_AUTHを有効にする設定
#-----------------------------------------------------------------------------
smtpd_sasl_auth_enable = yes

#----------------------------------------------------------------------------
# smtpd_sasl_security_options = anonymousでの認証はとおさない
#-----------------------------------------------------------------------------
smtpd_sasl_security_options = noanonymous


#-----------------------------------------------------------------------------
# smtpd_sasl_local_domain = ローカル認証のREALMの指定。
# 前述したsaslpasswd2設定時のREALMと同じものを利用。
# 『=$myhostname』とするのが無難
#-----------------------------------------------------------------------------
smtpd_sasl_local_domain = $myhostname

#-----------------------------------------------------------------------------
# broken_sasl_auth_clients = Outlook LOGIN 認証を利用するための設定
#-----------------------------------------------------------------------------
broken_sasl_auth_clients = yes

(3-1) 認証SMTPサーバー設定の補足

上記のコードブロックについていくつかの補足を行う。

まずは、smtpd_sasl_auth_enablesmtpd_sasl_local_domainを設定する。さらに目的に合わせてsmtpd_recipient_restrictionssmtpd_client_restrictionsのどちらかに『permit_sasl_authenticated』を追加しておく。
SASL対応のPostfixではsmtpd_sasl_auth_enableパラメータをYesと設定することでSASLによる認証を行うことができます。

次に、認証のために用いるドメイン名をsmtpd_sasl_local_domainに指定する。これは、『■ユーザの新規登録』で登録したrealmと一致するようにする。上記の例では『$myhostname』としている。

smtpd_recipient_restrictionsはPostfixの使用を制限する主要なパラメータで、SPAMの判別と排除のタイミングやSMTPコマンドが入力された時点での判断の条件となる。主に初期の条件では『permit_mynetworks, reject』が指定されているが、これに『permit_sasl_authenticated』を加えることで、SASL認証をしたクライアントに対してSMTPサーバーを中継に使うことを許可するようになる。

SASL認証したクライアントだけにPostfixのサーバーの認証をするにはsmtpd_client_restrictionsに『permit_sasl_authenticated』だけを指定するとよい。

(3-2) SASLに関する高度な設定

ここで関連するパラメータ設定はbroken_sasl_auth_clientssmtp_sasl_security_optionsだ。
SASLには認証時のパスワードが平分でネットワークを流れてしまうPLAIN認証や匿名でアクセスできてしまうANONYMOUSプロトコルがそれぞれ用意されている。

PLAIN認証にはパスワード盗聴の脅威、ANONYMOUS認証にはユーザーの特定ができない問題がそれぞれ存在する。
そこで、これらの使用の許可・不許可を制御するのが broken_sasl_auth_clients と smtpd_sasl_security_options のパラメータである。これらのパラメータにPLAIN認証を行わないように指定する『noplaintext』や匿名認証を行わせないように『noanonymous』をそれぞれ設定することができる。

(設定例)

smtp_sasl_security_options = noplaintext, noanonymous
smtpd_sasl_security_options = noanonymous

上記のようにパラメーター設定を行えば、smtpdは匿名認証を行わないでsmtpはPLAIN認証と匿名認証を行わない。
PLAIN認証にしか対応していないMUAもあるためPLAIN認証を完全に使わないようにすることは難しい。ならば、通信経路をTLSで暗号化しておけば、少なくともパケット盗聴によるパスワード漏洩を防ぐことができる。TLSによる暗号化は『4.セキュリティ対策(応用編)− 暗号化通信』にて述べることとする。

SASLの登場から随分たつが、SASL関連のRFCが世に出る前に実装されたいくつかのMUAでは同じパラメータを指定しているにもかかわらず、挙動の異なるものがある。

broken_sasl_auth_clients のパラメータはそのような挙動の異なるMUAにに対応するためのパラメータだ。RFC2554で定義されているAUTHコマンドではEHLOのレスポンスとしてサーバーから送られてくる以下のようなAUTH行に対して、クライアントはAUTHコマンドを送信することになっている。

(AUTH行)

250 AUTH CRAM-MD5

しかし、下記の形式のメッセージにしか反応できないクライアントと言うのが少なからずある。

(AUTH行)

250 AUTH=CRAM-MD5

broken_sasl_auth_clientsは『AUTH CRAM-MD5』と『AUTH=CRAM-MD5』のメッセージ両方とも送信することによって、このようなクライアントに対応する。

(4) SMTP-AUTH実装のためのmore one trick

ここまでで、SMTP-AUTHをPostfixで利用するための設定は95%は完了。
世間に多く、普及しているLinux(=FedoraCore、Debian、Redhat、・・・)ならば上記で述べてきた設定で稼働してしまうだろう。
本サーバーを稼働させている環境であるOpenBSDの場合では、上記の設定だけではメールソフトでの認証ではじかれてしまう。
メールサーバーのログファイルを読み説くと、DBファイルがオープンできていないようだ。

わざわざ、Cryrus SASLライブラリや設定ファイルの内容を編集しているのにも関わらずだ!
これは、OpenBSDが非常にSecureなOSとして設計されていることに由来する。
OpenBSDではPortsなどのパッケージからPostfix(=SASL2サポート)をインストールすると、jail化されたメールシステムとしてインストールされる。
・・・一見インストールパスを見ても、通常のPostfixにしか見えないのが高度な技法の片鱗を伺わせる。

では、どのようにすればSMTP-AUTHを実装できるのか。
以下で解説していく。

(4-1) sasl2のインストールディレクトリの問題

実は、パッケージからSASL2サポートのPostfxをインストールしていたとしても、Postfixは正しいパスにSASL2のライブラリを読みに行く事はできない。パッケージからインストールすると、SASL2のライブラリは『/usr/local/lib/sasl2/』にインストールされる。だが、Postfixは『/usr/lib』に sasl2/ があるものと見当違いをして読みに行ってしまう。そのため、初期状態ではSASL2のライブラリが読み込めない。これは、Linuxディストリビューションをはじめとした多くのUNIXクローンOSでは『/usr/lib』にsasl2のライブラリがインストールされているためだ。

対策としては、Postfixの読みに行くパスにシンボリックリンクを張ってあげればよい。

# ln -s /usr/local/lib/sasl2/ /usr/lib

(4-2) sasldb2.dbファイルが開けない問題

これは、Postfixがjail化されていることに由来する。
jail化されていなければ、本件の障害は起こらない。

Postfixがjail化されていると、設定ファイル(=main.cf)での指定できないファイルの読み込みは /var/spool/postfix/etc/ に限定される。本来、 /etc/ 直下に置かれるsasl2.dbが読み込めない。よって、 can not open db といったエラーメッセージが発生して、SMTP-AUTHでユーザー認証ができない。
/etc/sasl2.db ファイルはSMTP-AUTHでの認証時にユーザーアカウントと認証パスワードの組み合わせが格納されているDBである。このファイルが読めないと、SMTP-AUTHが使用できない。
解決方法としては、jail化されたPostfixが読み込める /var/spool/postfix/etc/ 直下にsasl2.dbを作ってあげればよい。だが、SASL2はjail化されたPostfixに関係なく、アカウント情報が登録された際には /etc/sasl2.db にアカウント情報が書き込まれる。
そこで、 /var/spool/postfix/etc/ に /etc/sasl2.db のシンボリックリンクを張ることで、問題が解決する。場合によっては、シンボリックリンクではなく、ハードリンクでなければ有効化しない事もあるので、その点はよく確認しておくことが重要だ。

(作業例 : シンボリックリンクの場合)

# ln -s /etc/sasldb2.db /var/spool/postfix/etc/sasldb2.db

(作業例 : ハードリンクの場合)

# ln /etc/sasldb2.db /var/spool/postfix/etc/sasldb2.db

セキュリティや保守の安全性を考えてストレージを分けて運用している場合は、デバイスを超えてリンクは張れない事に留意しておくこと。
OpenBSDに限らず、多くのUNIX系OSでは標準状態で下記のようにストレージを切り分ける事が多い。

/dev/wd0a /
/dev/wd0g /home
/dev/wd0d /tmp
/dev/wd0f /usr
/dev/wd0e /var

/etc は / パーテーションだが、 /var/spool/postfix/etc/sasldb2.db は /var パーテーションとなる。 この場合はリンクではなくコピーを行う。

# cp -p sasldb2.db /var/spool/postfix/etc

(5) master.cfファイルの編集

main.cfファイルの編集のみでは、SMTP-AUTHは使用できない。
master.cfファイルの記述を以下のように書き換える。

(変更前)

smtps inet n - - - - smtpd
# -o smtpd_tls_wrappermode=yes
# -o smtpd_sasl_auth_enable=yes
# -o smtpd_client_restrictions=permit_sasl_authenticated,reject

(変更後)

smtps inet n - - - - smtpd
# -o smtpd_tls_wrappermode=yes
-o smtpd_sasl_auth_enable=yes
-o smtpd_client_restrictions=permit_sasl_authenticated,reject

下2行のコメントを解除している。

4.セキュリティ対策(応用編)− 暗号化通信

SSLはインターネット上のデータ交換を安全に行う目的でNetscape Communication社が提唱した暗号化プロトコルである。
SSLではTCP/IPのTCP層の上に暗号化通信を実現するための階層を定義している。SSLを使うと、メールの送受信を暗号化し、安全な通信を行うことができる。本章では、SSLとそれを標準化したTLSの概要について解説していく。

4−1.暗号化通信(=TLS)によるSTARTTLSの実装

通常のSMTPのセッション中では、通信はすべて平文のデータがネットワーク上を流れる。前セクションで述べたようにSMTP AUTHではDIGEST-MD5やCRAM-MD5などの認証方式を使用していればパスワードのみ暗号化されたデータが流れるが、PLAIN認証やLOGIN認証を行っている場合は認証パスワードも平文でネットワーク内を流れてしまう。

電子メールのセキュリティ上の弱点の1つとしてネットワーク盗聴による通信の秘密の曝露がある。
通信内容保護のためにTLS(= Transport Layer Security)を使って暗号化したSMTPセッションを使用することでこの弱点を補うことができる。

SSLで暗号化された通信の中にSMTPの通信を通すTLSという技術を使うことで、ポップ間の暗号化された通信経路の確保とクライアント認証によるアクセス制御が実現する。しかし、TLSはクライアントPCと送信元メールサーバーとの通信暗号化なので、そこから先の中継ホストや最終的な配送先のキュー、メモリ、ファイル上では平文の状態でデータが扱われていることに注意をしなければならない。

対策としては、暗号化された通信の中に平文のデータを流すのではなく、はじめから暗号化されたデータを通信に流す方法。
これは、主に『PGP』や『S/MIME』などと呼ばれる暗号化方式である。

■ PostfixをTLS対応サーバーにする

PostfixをTLS(=SSL)対応サーバーにするには秘密鍵の作成、証明書署名要求、自己署証明書関連する作業が必要になる。 TLSでは鍵と証明書とVeriSignのような証明書発行機関(=rootCA)を使って認証を行う。本格的に使うには、正しい証明書発行機関の認証をうける必要があるが、自己署名した証明書でも通信路の暗号化はできる。

(1)暗号方式の歴史と選定 − DESとAES

一般的なSSLを使用したWebサイトでは、トリプル DES 暗号標準という方式で作成した秘密鍵を使用している。この方式は生成した1024 bit の秘密鍵を秘密鍵自体を共通鍵暗号のDES(= 64bitブロック暗号)で3回暗号化している。

この話だけでは、よく分からないながらも、3回も暗号化を行っているだけに堅牢な暗号のような気がする。

以下にDES暗号方式について歴史的な背景を踏まえて解説していく。

DES暗号というのはかつてのアメリカ合衆国の国家暗号規格として規格化された共通鍵暗号方式だった。しかし、この暗号化規格はアメリカ政府標準技術局(National Institute of Standards and Technology/ NIST)に採用されたのは1977年と20年以上も前のもので、DESの56 bit 鍵長(=64bitのうち8ビット毎に1ビットのパリティ・チェック・ビットがつくため実際には56bit)では安全性に疑問が生じてきた。当時に比べコンピュータの処理速度は格段に高速化しており、時間さえかければ鍵が破られるケースが出てきた。そのため、DESの処理を3重にかけることで安全性を高めたトリプルDESという方式が考案され、通信で用いられる暗号の標準となった。トリプルDESでは1つのブロックに対して3つの鍵でDESの処理を3度かけるため、168ビット長(= 56×3(bit))の暗号鍵を利用しているのと同じ強度になる。

DESは1993年松井充により提案された線形解読法により初めて、鍵総当たりよりも効率的な解読方法が存在することが示された。
1990年代末には、総当たり攻撃 (Brute Force Attack) を用いた完全解読が実際に可能であることが実証された。有名なところでは、1999年1月にRSAセキュリティ社が主催したDESクラッキングコンテストでは22時間でDistributed.NetによりDESが解読された。この時の解読にはDES解読専用機とインターネット経由で募集された10万台の電算機が用いられていた。

それほど高性能でなくとも、それなりに多くの台数さえ用意すればDESが容易に解読できる事が分かった後、DESの代わりにトリプルDESと呼ばれる方式が使用されるようになり、SSLを用いるWebサイトでは標準的に実装されるようになり、現在に至る。

上記の経緯からDESが時代遅れになったため、1997年9月にNIST(=米国国立標準・技術院)がAES暗号方式を公募した。世界から募集された15種類の共通鍵暗号方式から選定された後5つの候補に絞られ、最終的にベルギーのルーヴェン・カトリック大学の研究者ホアン・ダーメン(=Joan Daemen)とビンセント・ライメン(=Vincent Rijmen)が考案した Rijndael (ラインデール、ラインダール、あるいはラインドールと読む。)が2000年10月に採用され、新しい米国標準暗号方式(Advanced Encryption Standard)になった。

Rijndael はトリプルDESのようなad-hocな方法で設計された暗号方式とは事なり、SPN構造と呼ばれるより整備された構造を持つ暗号方式である。AESの制定後、DESは米国標準暗号方式から取り下げられた。

(2)サーバー秘密鍵の作成 (server.key)

一般的にはDES暗号方式を用いて作成したサーバー秘密鍵を採用しているネットワークが多いが、本章では暗号方式にAESを用いることを前提にして解説していくこととする。

秘密鍵を作るにはPostfixに限らず、システムにOpenSSL ツールキットがインストールされていてかつ、 Postfix の設定で秘密鍵を読み込むように設定されている必要がある。以下の例では、デフォルトの /usr/sbin/ ディレクトリにある OpenSSL のコマンドラインツールを使う。また、OpenSSL のコマンドラインツールがあるディレクトリが $PATH に追加されていることを想定しているものとする。

秘密鍵を作るには2048 bit で RSA の秘密鍵を生成し、秘密鍵そのものを共通鍵暗号の AES 256 bit で暗号化する。

#openssl genrsa -aes256 2048 > server.key
Generating RSA private key, 2048 bit long modulus
................+++
......................+++
e is 65537 (0x10001)
Enter pass phrase: (Hackerhehehe) <- 8文字以上のパスフレーズ
Verifying - Enter pass phrase:(Hackerhehehe) <- 8文字以上のパスフレーズ

上記の設定のままでは、Postfixが起動する度にパスワード入力が求められるので、非常に煩わしい。
よって、パスワードを削除する。

# openssl rsa -in .key -out .key <- サーバー鍵からパスワード削除
Enter pass phrase for .key: <- サーバー鍵作成時に設定したパスワード(Hackerhehehe)を応答する。
writing RSA key <- サーバー鍵からパスワードが削除された。

# ls -l
-rw-r--r-- 1 root wheel 887 Sep 28 16:37 .key

パーミッションが644なので600に変更する。

# chmod 600 .key

サーバー鍵のパーミッションが600に設定されていることを確認しておくこと!

(3)証明書要求の作成(server.csr)

証明書要求を作成する。一般的に『公開鍵』に相当する。

# openssl req -new -key .key -out .csr
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) []:JP <- 国名
State or Province Name (full name) []:Tokyo <- 都道府県名
Locality Name (eg, city) []:Chiyoda <- 市区町村名
Organization Name (eg, company) []:Criterion <- サイト名
Organizational Unit Name (eg, section) []:Research <- 部署名
Common Name (eg, fully qualified host name) []:mail.criterion.sc <- サーバーのホスト名
Email Address []:hogehoge@criterion.sc <- 管理者のメールアドレス

Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []: <- パスワードは未入力で[Enter]
An optional company name []:<- 未入力で[Enter]

(4)自己証明書の作成(=server.pem)

# openssl x509 -days 365 -in server.csr -out server.pem -req -signkey server.key
Signature ok
subject=/C=JP/ST=Tokyo/L=Chiyoda/O=Criterion/OU=Research/CN=deborah.criterion.sc/emailAddress=hogehoge@criterion.sc
Getting Private key

パーミッションを一律で400にそろえる。
# chmod 400 server.*
# ls -l
total 12
-r-------- 1 root wheel 1070 Dec 23 15:51 server.csr
-r-------- 1 root wheel 1679 Dec 23 15:47 server.key
-r-------- 1 root wheel 1330 Dec 23 15:53 server.pem

(5)個人認証局をつくる-認証局の鍵をつくる- (=cakey.pem)

# openssl genrsa -out cakey.pem 2048
Generating RSA private key, 2048 bit long modulus
..........................................................................................................................................................................................+++
.......................................................................................................................................................................................................
.....................................................................+++
e is 65537 (0x10001)

(6)個人認証局をつくる-認証局の証明書をつくる- (=cacert.pem)

# openssl req -new -x509 -days 365 -key cakey.pem -out cacert.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) []:JP <- 国名
State or Province Name (full name) []:Tokyo <- 都道府県名
Locality Name (eg, city) []:Chiyoda <- 市区町村名
Organization Name (eg, company) []:Criterion <- サイト名
Organizational Unit Name (eg, section) []:Research <- 部署名
Common Name (eg, fully qualified host name) []:mail.criterion.sc <- サーバーのホスト名
Email Address []:hogehoge@criterion.sc <- 管理者のメールアドレス

(7)サーバーの証明書をつくる(=server.crt)

自前の個人認証局をつかって、サーバー証明書を作成する。
VeriSign社やCAcert.orgなどに証明をお願いするならこの行程は必要なくなる。。

1.まずターミナルに以下のコマンドを入力しリターンで実行する。このコマンドは何をするのかというと、自前の認証局が発行する証明書につくシリアルナンバーのファイル(=ca-cert.srl)を作成するものだ。

# echo 01 > ca-cert.srl

2.次に以下のコマンドを入力しリターンで実行する。一行だけなので注意すること!

# openssl x509 -CA cacert.pem -CAkey cakey.pem -CAserial ca-cert.srl -req -days 365 -in server.csr -out server.crt
Signature ok
subject=/C=JP/ST=Tokyo/L=Chiyoda/O=Criterion/OU=Research/CN=pop3s.criterion.sc/emailAddress=hogehoge@criterion.sc
Getting CA Private Key

この作業でできた『server.crt』がサーバーの証明書。

(8)IMAPとPOP用の証明書(=mail.pem)をつくる。

前のステップでつくったサーバー鍵(=server.key)とサーバー証明書(=server.crt)はPostfixでは使えるが、IMAPやPOPでは使うことができないことがある。これはIMAPやPOPはサーバー鍵(=server.key)とサーバー証明書(=server.crt)が1つのファイルにくっついていないといけないからだ。ここではサーバー鍵とサーバー証明書を結合させて、IMAP用、POP用の証明書を作成することとする。

# (cat server.crt ; cat server.key) > mail.pem

(9)パーテーションの設定

# chmod 400 .*

# ls -l
-r-------- 1 root wheel 3 Dec 24 11:37 ca-cert.srl
-r-------- 1 root wheel 1330 Dec 24 11:33 cacert.pem
-r-------- 1 root wheel 1675 Dec 24 11:31 cakey.pem
-r-------- 1 root wheel 3001 Dec 24 11:43 mail.pem
-r-------- 1 root wheel 1326 Dec 24 11:37 server.crt
-r-------- 1 root wheel 1074 Dec 24 11:14 server.csr
-r-------- 1 root wheel 1675 Dec 24 11:11 server.key
-r-------- 1 root wheel 1338 Dec 24 11:16 server.pem

(10)PostfixのSSL用設定

PostfixをSSL(=TLS)に対応させるために、設定ファイル(= /etc/postfix/main.cf)に以下の記述を書き加える。
メンテナンスを行いやすくするように、下記のコードブロックのまとまりは設定ファイルの末尾、SASL設定のコードブロックの直後に書き込んでおこう。

#=======================================================================
# SSL/TLS Setting
#=======================================================================

#-----------------------------------------------------------------------
# smtpd_use_tls starttls (=starttlsコマンドの利用の可否の指定)
#-----------------------------------------------------------------------
smtpd_use_tls = yes

#-----------------------------------------------------------------------
# smtpd_tls_cert_file(= 証明書ファイルの指定)
#-----------------------------------------------------------------------
smtpd_tls_cert_file = /etc/postfix/ssl/server.crt

#-----------------------------------------------------------------------
# smtpd_tls_key_file(= 秘密鍵ファイルの指定)
#-----------------------------------------------------------------------
smtpd_tls_key_file = /etc/postfix/ssl/server.key

#-----------------------------------------------------------------------
# smtpd_tls_loglevel = TLS Logging Level ( = TLSのログレベル指定)
#-----------------------------------------------------------------------
smtpd_tls_loglevel = 3

smtpd_tls_received_header = yes

#-----------------------------------------------------------------------
# smtpd_tls_session_cache_database = TLS Session Cache Database
# ( = TLSセッションキャッシュデータベースの指定)
#-----------------------------------------------------------------------
#smtpd_tls_session_cache_database = sdbm:/etc/postfix/ssl/smtpd_scache
smtpd_tls_session_cache_database = btree:/etc/postfix/ssl/smtpd_scache

smtpd_tls_ask_cert = yes
smtpd_tls_CAfile = /etc/postfix/ssl/cacert.pem

(11)トラブルシューティング

設定変更後にPostfixの再起動を行うと、エラーが発生してメールが送信できないことがある。原因調査のためMailサーバーのログを確認すると『fatal: unsupported dictionary type: sdbm』というログがあがっていた場合には設定ファイル(=/etc/postfix/main.cf)中の『smtpd_tls_session_cache_database』という記述をコメントアウトすると、エラーは解消する。

また、このセクションではPostfixにTLSを適用しているため設定ファイル(=/etc/postfix/main.cf)中に「smtpd_tls_session_cache_database」が定義されている。
エラーメッセージに上がってきたsdbmだが、postfix Ver2.2からは「sdbm」を別途インストールする事によりサポートされるようになる。
sdbmを別途インストールしない場合は

smtpd_tls_session_cache_database = btree:/etc/postfix/smtpd_scache

と書き換えるとよい。
ちなみに、設定は現行のままでpostfix Ver2.2で起動すると、TCPポート465を使用するサービスをシステムがサポートしていないためにメール送信する事が出来ない。

PFの465番ポートをオープンしているはずなのに、nmapなどを使用してポートの状況を見ると、465番ポートはcloseされたままになっている。

この場合は、以下のようにPostfix設定ファイル(=/etc/postfix/master.cf)編集すればよい。

(変更前)

#smtps inet n - - - - smtpd
# -o smtpd_tls_wrappermode=yes
# -o smtpd_sasl_auth_enable=yes
# -o smtpd_client_restrictions=permit_sasl_authenticated,reject

(変更後)

smtps inet n - - - - smtpd
# -o smtpd_tls_wrappermode=yes
# -o smtpd_sasl_auth_enable=yes
# -o smtpd_client_restrictions=permit_sasl_authenticated,reject

次に、 /etc/services と /var/spool/postfix/etc/services の『# Unofficial services』の行以降に

smtps 465/tcp # Postfix (TLS/SSL) Server

と付け加えておく。

確認事項として同一のネットワークセグメントにいるなら、ポートスキャンを対象のサーバーに仕掛けて、smtpsのポートがオープンになっているかを確認する。

nmap -O 10.0.1.201

Starting Nmap 4.01 ( http://www.insecure.org/nmap/ ) at 2006-12-23 18:03 JST
Interesting ports on 10.0.1.201:
(The 1666 ports scanned but not shown below are in state: closed)
PORT STATE SERVICE
22/tcp open ssh
25/tcp open smtp
53/tcp open domain
80/tcp open http
443/tcp open https
465/tcp open smtps
MAC Address: 00:09:6B:A0:A1:1E (IBM)
Device type: general purpose
Running: OpenBSD 3.X
OS details: OpenBSD 3.6

Nmap finished: 1 IP address (1 host up) scanned in 4.321 seconds

これで、TCPの465番ポートも有効になったことが確認できた。

4−2.暗号化通信(=TLS)による SMTP over SSLの実装

すでに何度も述べているが、メールの送信プロトコルであるSMTPはネットワーク上に平文のデータをながします。そのため、通信内容の盗聴や改ざんに対しての脆弱性を持っている。
この脆弱性に対して通信を暗号化して通信内容の保護をおこなう。また、インターネットとりわけWebの通信で多くの実績を上げているSSLを用いることでサーバーとクライアント間通信の信頼を確立することで第三者による通信内容の改ざんを防いでいる。
SMTPの通信をSSLにより暗号化する方法として、STARTTLSとSMTPSがある。この2つの方式の違い・メリット・デメリットを考察しつつ、設定方法を解説していく事とする。

(1)STARTTLSとSMTPSの違い

『4−1.暗号化通信(=TLS)によるSTARTTLSの実装』では、STARTTLSという手法でSMTPセッションを暗号化して通信を安全にしている。SMTPの暗号化通信としてSMTPS(=SMTP over SSL)が有名だ。この手法もSMTPセッションを暗号化して通信の内容を安全にする。実は、STARTTLSもSMTPSも同じく暗号化にSSLを使用している。
Web以外ではSSLを使用した暗号化通信をSSL通信と呼ばずにTLS(=Transport Layer Security)と呼ぶのが一般的になっている。

では、STARTTLSとSMTPSは同じものなのか?

通信方法が多少違う。

SMTPSの通信はWEBのHTTPSと同じく、最初からSSLで暗号化したパケットを用いてクライアントとサーバー間を接続する。
クライアントサーバー間の通信としては、クライアントからSSLで暗号化されたパケットがサーバーの465ポートに接続することで通信が確立される。

STARTTLSは最初に通常のSMTPと同じく平文のパケットをサーバーに接続して通信が確立した後でSSLで暗号化されたSMTPの通信を行う。クライアントサーバー間の通信としては、暗号化の前後の通信ともサーバーの25番ポートに接続する。

SMTPSとSTARTTLSともに、SSLを使用しているので暗号化されている通信は一般的に知られている技術の範疇では安全なのだが、STARTTLSは通信が確立するまでは平文の通信を行っている分だけ若干脆弱といえる。クライアントがサーバーに接続すればすぐにTLS通信を始めるようになっているが、何らかの理由でTLSが使用できない状況に陥ったとき、通常のSMTPとして平文の通信を行ってしまう。SMTPSはサーバーに対していきなり暗号化されたパケットを送りつけるので、STARTTLSのように平文のパケットは扱わない。SMTPSはSTARTTLSとは異なって特別なポート(=465番)に接続するので、SMTP over SSLに対応していないメールソフトでは使用できない。このことが、STARTTLSより普及度が低い理由となっている。何らかの理由でTLSが使用できない状況に陥ったとき、SMTPSは通信ができない。

STARTTLSは通信ができる事を重視し、SMTPSは通信の安全性を重視する。

よく勘違いしがちだが、TLSの通信そのものは送信元のメールクライアントとメールサーバー間の通信を暗号化する。メール配信のすべての経路が暗号化で守られているわけではないのだ。送信元メールサーバーと宛先メールサーバー間は中継するサーバーがTLSに対応していない限り平文のパケットが流れる。これはSTRTTLSもSMTPSも共通して同じことが言える。

暗号化通信をシステム的に構築していく上では、運用上の利便性とセキュリティの堅牢性のバとのランスをよく考え適切に運用していただきたい。

(2)SMTPSに対応したPostfixの構築

本セクションでは、SMTPSに対応したPostfixの構築がテーマだが、設定のほぼ100%は、STARTTLSの設定で完了している。よって /etc/postfix/main.cf で行う設定はない。
/etc/postfix/main.cf の設定を一カ所のみ変更すればよい。

設定のPoint

STARTTLSとSMTPSの設定の違いは /etc/postfix/main.cf のみ

(作業前)

smtps inet n - - - - smtpd
# -o smtpd_tls_wrappermode=yes
-o smtpd_sasl_auth_enable=yes
-o smtpd_client_restrictions=permit_sasl_authenticated,reject

(作業後)

smtps inet n - - - - smtpd
-o smtpd_tls_wrappermode=yes
-o smtpd_sasl_auth_enable=yes
-o smtpd_client_restrictions=permit_sasl_authenticated,reject

Postfixを再起動すると、設定の変更が反映されて、SMTPSが有効になる。

5.メールソフトでの送受信テスト

長らくかかったが、ようやくメールソフトを使って送受信テストを行うことができる。本章ではMac OS X (10.3以降)に標準搭載されているAppleMailを使用して、SSL経由での送受信テストを行う。

(1)アカウント設定

Mail.appを起動して、メニュー画面より[環境設定]を選択する。
[アカウント]の項目をクリックすると、メール設定画面が表示されるので下記のように該当項目を入力する。

(入力例)

・アカウントの種類 : POP
・メールアドレス : jackie@criterion.sc
・受信用メールサーバー : mail.criterion.sc
・ユーザー名 : jackie
・パスワード : (任意のパスワード)

(2)送信用メールサーバー設定

次に送信用メールサーバーの設定を行う。
まずは、[サーバー設定]ボタンをクリックして送信サーバーの設定画面を表示させる。

本稿では、SMTP-AUTH認証とSMTPSの実装をしているが、以下にSMTP-AUTH認証とSTARTTLS / SMTP-AUTH認証とSMTPSを設定した場合の設定画面のキャプチャを添付する。

基本的な設定は同じだが、唯一違うのはSTARTTLSはPort:25、SMTPSはPort:465をそれぞれ使用することだ。
SMTP-AUTHを使う場合は、必ずsasldbに登録したユーザー名とパスワードを入力することを意識しておこう。

(3)受信用メールサーバー設定

本稿では、POP3Sも実装しているのでついでに設定しておく。
設定は至って簡単で通常のPOP3と同じだが、[詳細]タブの項目で[□SSLを使用]にチェックを入れると、ポート番号が110から自動的にPOP3Sの995番に変更される。

以上で、メールソフトの設定は完了だ。

メール受信時とメール送信時に下記キャプチャ画面が表示され、メールの送受信ができれば正常に設定が反映されていることが伺える。

上記のキャプチャ画面ではSSLサーバーからの警告メッセージが発せられている。
『SSLサーバー "Mailサーバー名" を確認できません』とエラー表示されるが心配には及ばない。本稿で解説した方法では、自前の認証局(=個人認証局)でサーバー証明書を作成している。VeriSign社やCAcert.org社のような公的な認証機関で発行されたサーバー証明書を使用していないことで発せられるものでサーバーの設定ミスではない。

公的な認証機関が発行したサーバー証明書を使用するにはコストがかかる。認証機関の代表例としてVeriSign社を取り上げると、1番安いプランでも年間で85,050円(税込)掛かる。個人で運用しているサーバーのSSL証明書にこの金額は掛けられない。ビジネス用途で顧客にSSL接続を提供していない限りは個人認証局のサーバー証明書で十分だ。

[続ける]ボタンをクリックするとサーバーとの通信が暗号化されて、処理が行われる。ちなみに本設定では[続ける]ボタンをクリックしないと、SSLによる暗号化通信がされないために、クライアントソフト側で通信が失敗しメールの送受信ができないことを覚えておこう。