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で暗号化する方法はあちこちのウェブページにあるでしょう。もちろん、 submission であれば自分しか使わない場合はオレオレ鍵で充分ですが、通常メールは外から送らせるのでオレオレ鍵はダメです。Let’s Encrypt が無料で利用できる時代なので、公開サーバーでオレオレ鍵という選択肢はありませんね。一応、オレオレ鍵の場合は送信時のみで受信は平文という選択肢はあります。(2018/3/28 StartCom, Let’s Encrypt 関連情勢を反映して記事更新)

その後の設定は簡単です。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 サポートには特定サーバーのみポリシーを変える方法も書かれていました。安全性を高めるには、やりとりする相手のメールサーバーについて、平文で接続しないように設定するとよいでしょう。

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

(追記)

これを実施しても、 DNS の MX レコードは正しいことを前提としていたり、そもそも STARTTLS が可能であることは平文で署名なくやりとりしたりしているため、(例えば)接続時点で https であることを指示し、署名されているべきホスト名も URL で指定する HTTPS と同等の安全性にはなりません。

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

とはいえ、改竄を伴わない盗聴と改竄では、技術的にも盗聴されていることに気付かれるかどうかという点でも、大きくハードルが違うでしょう。そのあたりのリスクと利点をどうとるかは運用の判断となります。

(追記)この記事はいくつか執筆後の加筆・修正があります。

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

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

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

自宅にある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には入れるべきでしたね。