TLS のセキュリティを強化する BoringSSL
そこで2023年、Fastly は TLS セキュリティに大きな投資を行いました。このブログ記事では、OpenSSL からの移行についてご説明し、今後の記事で秘密鍵のオペレーションを隔離する Neverbleed の実装についてご紹介します。
悪名高い Heartbleed バグをはじめ、OpenSSL には深刻度の高い脆弱性に悩まされてきた長い歴史があります。悪用のリスクに加え、新しい脆弱性が公開されるたびに迅速なパッチをテストしてデプロイするには、かなりの運用コストがかかります。OpenSSL を BoringSSL に置き換える主な目的は、お客様のために CVE の頻度と影響を減らし、TLS 終端システムのセキュリティを強化することにあります。
BoringSSL は、Google によって開発、管理されている OpenSSL のフォークです。よりシンプルなため、OpenSSL よりも根本的に安全性が高いと一般的に考えられています。OpenSSL は依然として SSL ライブラリの便利なツールであり、改良するために長年にわたり多くの素晴らしい取り組みが行われてきました。しかし、BoringSSL の方がより優れた保護を提供できると私たちは確信しています。
取り組みの道のり
私たちはおよそ1年前に、Fastly エッジで受信するすべての接続リクエストの処理において OpenSSL を他の方法に置き換えるという野心的なアイディアを実現する取り組みに着手しました。いくつかの代替手段を検討しましたが、以下のメリットが得られることから、BoringSSL への移行という最初のアイディアに落ち着きました。
小さくて先進的なコードベース
安全性の高い API
OpenSSL から派生した BoringSSL はソース互換性が高いため、移行における障害が少ない
広範なファジング
大手企業によって採用され、Google によって管理されている
OpenSSL と同じレベルのパフォーマンス
まとめると、BoringSSL は OpenSSL のように無数のレガシーコードを含まず、より簡潔なコードベースを提供するため、本質的によりセキュアであるというのが一般的な見解です。
以下は、コード行数に関する OpenSSL と BoringSSL の比較です。
上述のように、BoringSSL が同じレベルのパフォーマンスを確実に提供できることが、評価の際に非常に重要でした。そこで、複数の異なる手法を用いてライブラリのパフォーマンスを比較しました。
まだ開発に着手すらしてない段階で、特に暗号化動作に関してパフォーマンスのベンチマークを行いました。
以下は、異なる TLS ライブラリによる鍵交換 (1秒あたりの ECDH 操作回数) の比較を示すグラフです。
BoringSSL ライブラリがテスト可能な状態になったらすぐに「カナリアテスト」を実行し、新しいコードを複数の本番サーバーにデプロイしました。これにより、シミュレートするのが困難な実際のトラフィックパターンを使用してパフォーマンスを比較できるためです。最後に「過負荷テスト」を実施し、特定の Fastly サービス (テストバイナリを実行しているサービスに加えて、コントロールグループとしてのいくつかのサービスを含む) に、より多くのライブトラフィックを処理させました。
メリットばかりではありません
当初から、開発に多くの労力が必要とされることが予想さ れました。また、Fastly のネットワークでこのように大きな変更を行うには、運用やカスタマーサポートにおいて発生する追加作業を想定する必要がありました。お客様に影響を与えることなくこの変更を実施することが最終的な目標でした。
さらに、この変更において以下が利用できなくなることを私たちは認識しています。
バージョニングなし : OpenSSL とは異なり、BoringSSL の管理者は定期的なリリースを行いません。そのため BoringSSL では上流の変更をトラッキングし、変更が適切かどうかを判断する必要があり、頻繁な管理作業が求められます。
ツールおよび設定スクリプト
OCSP ステープリング
一部の脆弱な暗号化のサポート (CBC モードなど)
セッション再開の問題
変更作業の半ばで (少なくともその時は「半ば」と思っていました)、最初の課題に遭遇しました。OpenSSL と BoringSSL のセッションに互換性はありません。BoringSSL を使用する H2O インスタンスで開始されたセッシ ョンを、OpenSSL を使用する別の H2O で使用することはできません (その逆も不可能です)。そのため、ライブラリ間でのチケットとキャッシュのセッション再開が阻止されます。
しかし、Fastly のロードバランサーのアーキテクチャでは、同じクライアントからの接続が異なる接続先サーバーに到達する可能性が高くなります。そのため、何千ものサーバーに対して変更がロールアウトされた際、異なるライブラリを使用する再開の試みが大量に発生することになります。
このようなクロスライブラリでの再開の試行はロールアウトの段階でのみ発生するため、単に TLS セッションのキャッシュをセグメント化し、TLS ハンドシェイク再開の一時的な (部分的な) 損失を処理するだけで、この問題を解消できました。
暗号化の問題
BoringSSL がよりセキュアである理由のひとつに、一部の古い暗号スイートのサポートが排除されたことがあります。そのため BoringSSL への変更により、すべての脆弱な CBC モードの暗号が知らないうちにサポートされなくなったのです。このような暗号に依存しているクライアントの数はごくわずかとはいえ、多くの Fastly のお客様の規模を考えると、たとえトラフィックの小さな割合でも実質的な影響をもたらす可能性があります。テスト中、頻繁に使用されていたある特定の暗号によって移行が阻止されているのに気付きました。そこで私たちは同様の特徴を持つ暗号をシミュレートして実装し、「BoringSLL が使用されていた」ものとしてカウントして後方互換性の実際の損失を評価しました。
この問題は BoringSSL の管理者によって認識され、その後「ECDHE-RSA-AES128-SHA256」という単一の脆弱な CBC 暗号のサポートが復活しました。データの収集と分析を行い、再度テストを実施した後で、次のステップに進むことができました。
以下のデータが示すように、そのたったひとつの脆弱な CBC 暗号へのサポートが復活したことで、互換性のない暗号のカウントは無視できるレベルになりました。しかもこの数値は Fastly の TLS 設定を調べるためのボットやスキャナーによって増大している可能性が高いです。
OCSP
多くのクライアントが失効した証明書を確認するのに OCSP (Online Certificate Status Protocol) の使用を止めています。Google は Chrome で CRLSets に依存しているため、BoringSSL では OCSP の検証関数が排除されています。OCSP 検証を実行しているクライアントは現在も多く存在しますが、デフォルトではそれはネットワーク をブロックする呼び出しであり、パフォーマンスに悪影響を及ぼします。OCSP ステープリングには、サーバーが OCSP レスポンスをハンドシェイクの一環として送信することで、余分なネットワークの呼び出しを回避できるというメリットがあります。Fastly にとって、このようなパフォーマンスを向上する機能を失うことは受け入れられません。そこで私たちはこの欠けていた関数を BoringSSL に追加しました。
まとめ
初期のアイディアで成功したのは、前もって OpenSSL 特有の API 関数に依存していた機能を、可能な限り TLS ライブラリに依存させないようにすることでした。
追加の管理コストは想定内でしたが、上流で BoringSSL に対して行われた最近の変更をすべて分析し、更新が必要か、更新を実行すべきかを判断するのに追加作業が発生しています。例えば前述の CBC 暗号のように、後方互換性が失われていることに気づかない事態を避けるためにモニタリングし続ける必要があります。
このようにいくつかの新たな課題をもたらしている BoringSSL ですが、総合的に見て TLS のセキュリティ向上に投資することにした決定に私たちは満足しています。