Postfixにおけるメールサーバー間の暗号化

メールは平文でやりとりされるから安全な手段ではないとよく言われます。
まあ、メールという手段がそれほど安全なわけではないのは事実であるのは、今もそれほど変わってはいないように感じます。

メールサーバーとクライアントの間の、submission(メール送信)やPOP3/IMAP(メール受信)は認証を伴うのと、単にユーザーが対応すればよいので、国内大手ISPはともかくメールを主とするサービスであればフリーメールでも暗号化するのが当然となってきました。一方で、メールサーバー間のやりとりは平文でのやりとりで危険とされてきました。まあ、その認識は誤ってはいないのですが、一方でそこを暗号化する規格は今のところないと思っていました。ところがある日、メールヘッダを眺めていたら

Received: from www****.sakura.ne.jp (www****.sakura.ne.jp. [2403:********])
        by mx.google.com with ESMTPS id ******
        for <***@nhiroki.net>
        (version=TLSv1 cipher=RC4-SHA bits=128/128);
        ***, ** *** 2013 **** -0800 (PST)

なんでだいぶ前のメールのヘッダを改めてみたのかはともかく、またさくらとGMailの間のやりとりがIPv6だ!というのもともかく、

(version=TLSv1 cipher=RC4-SHA bits=128/128);

んんんっ?

これは暗号化されてやりとりしているのでは?

と思って調べてみたところ、RFC3207で暗号化してSMTPを通信する手段が規格となっており、EHLOコマンドの返答としてSTARTTLSの可否を通知、そこからTLSで暗号化して通信する手段があるとのこと。単に僕が無知だっただけか。

メールサーバー間で暗号化することができれば、メールサーバー群内はともかく、インターネットを利用した通信は基本的に暗号化され、それなりのセキュリティが保たれることになります。もちろんメールサーバー上や、構成によりリレーが多段階に渡る場合はその間のやりとりは(内部ネットワークなど盗聴の心配がないネットワークなのでしょうが)平文になる可能性がありますし、そもそも暗号化をサポートしていないメールサーバーはたくさんあるので想定する必要がありますし、当然メールサーバーの運営者が悪意を持てば盗聴はできるでしょうが、そのあたりさえ信用できればインターネットを通しても安全が保たれることになります。S/MIMEやPGPなどのend to endな暗号化と比べると劣るのは事実ですが、通常利用には利便性と安全性のバランスがとれているといえるでしょう。

というわけで、これを自鯖のPostfixでも実現したいですね。

先に書いておくと、Postfix TLS サポートというウェブページの内容をほぼ参考に自鯖に設定しました。こちらのページを読むといいでしょう。

まず準備として、SSL自体の設定はしてください。submissionを465ポートのSSLとか587ポートからのSTARTTLSで暗号化する方法はあちこちのウェブページにあるでしょう。もちろん、自分で使う場合はオレオレ鍵で充分ですが外から送らせるのでオレオレ鍵はダメです。個人鯖ならStartSSLなどの無償鯖を利用する選択肢もあるでしょうし、商用である場合や個人でもStartComを使いたくない場合はちゃんとした証明書を買いましょう。オレオレ鍵の場合は送信時のみという選択肢があります。

その後の設定は簡単です。main.cfに

smtpd_use_tls=yes
smtpd_tls_received_header = yes
smtp_use_tls=yes

と書きましょう。その後postfixを再起動しましょう。これで完了です。

一、二行目は受信時、三行目は送信時です。テストする場合は別々にしましょう。また、オレオレ鍵しか用意できなかった場合は二行目だけにしておきましょう。

25ポートにつないでEHLOの返答でSTARTTLSが返ってくることや、受信時にtcpdumpしてもSTARTTLSコマンドを確認した後が暗号化された謎のバイト列がくることを確認したりするといいでしょう。また、GMailは暗号化したやりとりはReceivedヘッダでわかるので送信する方はGMailに送るのもありです。

S/MIMEやPGPほどではありませんが、ローコストでそれなりのセキュリティが実現されることになります。とはいえGMailやさくらのメールボックスなどの対応メールサービスのみですが……

また、Postfix TLS サポートには特定サーバーのみポリシーを変える方法も書かれていました。安全性を高めるには、やりとりする相手のメールサーバーについて、平文で接続しないように設定するとよいでしょう。

現実的には暗号化以外受け入れない設定に誰もがするのが安全なので、個人的には、こういうのは大手どこかが「○○ヶ月後からうちは暗号化してないと受信しない」と宣言すれば随分世界中のメールが安全になる気がしますが、まあ現実そうもいかないのでしょうね。

(追記)

ここまで書いておいてなんですが、この設定、普通に運用しているとSTARTTLS使用可否はEHLOへの返答として平文として返されるので、なんかめんどくさい割には中間者攻撃には割と無力な気がしますね。もちろん、特定のホストに大してであればポリシーをサイトごとに設定することで安全性を担保できますが。

現状でメールを使う場合で確実に暗号化された手段を使うには、送信者と受信者が同じメールサーバーを使うか、必要な相手に対してポリシーを設定するか、どちらも特定の相手にしか使えないので結局はPGPかS/MIMEという結論になりますね。STARTTLSの使用可否を安全な方法で通知できる仕組みとかあったらいいんですが。まあ、暗号化がどうしても必要な用途には電子メールは使うな(or PGPやS/MIME使用)、という原則に立ち返りますね。そもそもメールの場合は経路をTLSで暗号化したところでなりすまし防止にもなりませんし。

サーバーのネットワーク設定にご用心

みなさま、あけましておめでとうございます。

さて、新年早々大変残念なミスをやらかしたのでここに。

自宅にあるUbuntuがルーターにもなっていたのですが、先ほど自宅から外へのDNS解決ができなくなっていたので(dnsmasq、LAN内ホストの分は可能だった)ので/etc/resolv.confを見たところ127.0.0.1しかなく、DNSアドレスはPPP接続時に受け取る仕組みになっていたので

$ sudo ifconfig ppp0 down;sudo ifconfig ppp0 up

すると

Write failed: Broken pipe

沈黙しました。外からつながりません。多分中からも繋がっていないと思います。しかも、帰省していて物理的に触れないのでサーバーが外から完全に沈黙してしまったおち。不便。

こういう時(PPP接続をインターネット越しにやり直したい時)はどうやるのが正解なんでしょうか。

(2014/1/4 20:11追記) ifconfig ppp0 downしたあとpon [設定した接続先名]だったらいけたみたいです。どちらにしてもscreenには入れるべきでしたね。