2018年7月より、Chromeでブラウジングする際、SSL証明書を導入していないすべてのサイトで警告文が表示されるようになりますね。

Chromeの強制的な警告表示が2018年7月から開始 by SAKURA Inernet Inc.

ということで、そもそもHTTPSとはとか、暗号化とか、そのあたりの知識を整理しつつ、これまでSSL証明書を導入してなかったこのブログサイトや、練習で作ったToDoListのアプリにSSL証明書を導入して通信をHTTPS化しました。 この投稿はそのときの経験や調べたことをふまえ、HTTPSとは~というところから、私が実践したAWSを使ったアプリやサイトのHTTPS化についてまとめたものです。

目次

  1. そもそもHTTPSとは
  2. S3の静的コンテンツをCloudFrontでHTTPS化
  3. EC2の動的コンテンツをELBを使ってHTTPS化
  4. まとめ

1.そもそもHTTPSとは

まず、HTTPSを理解するために必要な事前知識を整理していきます。

1-1.HTTPとは

webサーバーとwebクライアント(ブラウザとか)用の通信プロトコル。クライアントがwebサーバーに見たいページを要求して、その内容をwebサーバーがクライアントにレスポンスする。この一連の通信をHTTPでやりとりする場合は、通信が暗号化されていないので、例えば、お問い合わせフォームにPOSTした内容とかをぬすみ見ることができます。(以前Wiresharkでぬすみ見れるか実験したことがありますが、見れました!)

1-2.ハイブリット暗号方式とは

ハイブリット暗号方式とは、共通鍵暗号と公開鍵暗号を組み合わせた暗号方式のこと。

共通鍵暗号

暗号化も復号化も同じ鍵で行う。

公開鍵暗号

  1. 受信者は暗号化する公開鍵と復号化する秘密鍵を生成する
  2. 受信者は暗号化する公開鍵を送信者に送り、送信者はそれを使ってデータを暗号化する
  3. 暗号化されたデータを受信者に送信し、受信者自身が生成した秘密鍵で復号する、

公開鍵暗号は共通鍵に比べてセキュアだが計算コストが高く、共通鍵方式は暗号化、復号化が早くて安いが公開鍵に比べるとセキュアじゃない。なのでこのふたつを組み合わせたハイブリット暗号方式がSSL/TLSには用いられている。

ハイブリット暗号方式

共通鍵を公開鍵で暗号化して受信者に送付する。受信者は秘密鍵で共通鍵を復号化し、その鍵でデータを復号する。

1-3.SSL/TLSとは

SSLはSecure Socket Layerの略で、TLSはTransport Layer Securityの略。TLSはSSLの次世代規格。暗号方式は、先ほど説明したハイブリット暗号方式。SSL/TLSを用いてHTTP通信を暗号化したものがHTTPS。

以下図はSSL/TLSによる暗号化のプロセス(=ハイブリット暗号方式のプロセス)をまとめたもの。

https_process.png

SSL/TLSの役割

  1. 暗号化通信

    インターネット上のデータ通信を暗号化することで、第三者から盗聴を防ぐ。

  2. サイト運営元の確認

    SSL/TLS通信ではウェブサイト所有者の情報、送信情報の暗号化に必要な鍵、証明書発行者の署名データ(ネット上の実印のようなもの)を持つSSL証明書を利用する。そのため、サービス提供者がだれなのかを登録する必要がありサービスの運営元がだれなのかをSSL証明書を通じて利用者は確認することができる。

AWSのACM(AWS Certificate Manager)などは、無料でだれでも発行できるので、とりあえず①の暗号化通信のためのもの、という意味合いが強い感じなのかな…?

1-4.サーバ証明書とルート証明書

サーバ証明書

  • ウェブサイトを運営している団体のいわゆる電子的な身分証明書。
  • シマンテックやグローバルサインなどの認証局事業者に申請し、その事業者が設定する認証を受けて発行してもらうもの。
  • 以下を含む
    1. サーバ運営者である組織名
    2. 証明書を発行した認証局の名前
    3. ウェブサーバの公開鍵や証明書の有効期限
    4. 認証局事業者の署名

ルート証明書 

  • クライアントに登録されている認証局の証明書のこと
  • ルート証明書の登録はブラウザの標準的な機能!!ブラウザによって登録されている証明書が異なったりすることがある。
  • 認証局の署名の復元をルート証明書で復号。複合したしたデータがSSLサーバ証明書のハッシュ値と一致すれば、第三者によって改ざんされたものでない、正しく認証局事業者が発行したSSLサーバ証明書であることが確認できる。

それではこれらの情報を、をふまえて…

1-5.HTTPSとは

SSL/TLSを使用して暗号化されたhttp通信。通信内容が暗号化されているので、パケットキャプチャされても、その内容は判別できない。通信の暗号化は、サーバ証明書とルート証明書を使い、先ほど説明したハイブリッド方式と呼ばれる仕組みで行われる。詳細な暗号化のステップは以下。

暗号化仕様交渉

① クライアントがサーバに、こっちはこういう暗号方式で接続したいです、と接続を要求する。

② ウェブサーバがそれに対応した暗号方式の仕様をクライアントにレスポンスする。

クライアントによるサーバー証明書の検証

③ ウェブサーバは、自分の身分を証明するSSLサーバー証明書をクライアントに送付

④ サーバ証明書をクライアントが受け取ったら、クライアントはその証明書が正しいものか、改ざんとかされてないかを検証する。

サーバー証明書には”認証局の署名”が含まれています。この認証局の署名は、サーバ証明書のハッシュ値を、その署名をした認証局の秘密鍵で暗号化したデータです。これによってどの認証局がが認証した証明書かがわかります。クライアント(のブラウザ)には、あらかじめ、信頼されれている認証局のルート証明書の公開鍵が登録されています。この公開鍵を使って、サーバ証明書のハッシュ値を復号します。

⑤ 復号化すると、サーバ証明書のハッシュ値が得られます。送られてきたサーバ証明書のハッシュ値を計算し、複合化して得られた値と、送られてきたサーバ証明書のハッシュ値を比較し、送られてきたサーバ証明書が本物かどうかを検証することができます。

クライアントで共通鍵の素を生成し、それをサーバ証明書から得た公開鍵で暗号化してサーバへ送付

⑥ クライアントは、サーバ証明書からサーバの公開鍵を取得できます。④~⑤のクライアントによるサーバー証明書の検証を経て、送られてきたサーバ証明書が本物だとわかったら、このサーバの公開鍵も本物です。

⑦ クライアントはプリマスタシークレット(共通鍵を生成する基となる乱数データ)をサーバの公開鍵で暗号化する。プリマスタシークレットはクライアント(細かくいうと疑似乱数生成器とやら)が生成するもの。

同じ共通鍵をクライアント、サーバで保持する。

⑧ 暗号化したプリマスタシークレットをウェブサーバに送る。

⑨ ウェブサーバーはクライアントから送付されてきた暗号化されたプリマスタシークレットを、もともと持ってた秘密鍵で復号化し、復号化されたプリマスタシークレットを使って、共通鍵を生成。

⑩ クライアント、ウェブサーバで同じ共通鍵を生成、共有することで、その共通鍵を用いてセッションの暗号化と復号化が可能となり、HTTPSが確立される。

参考サイト様

いまさら聞けない、SSLサーバ証明書とルート証明書の関係 by Symantec

ようは、クライアントがリクエストする対象にサーバー証明書があればいいってことだと私は理解しています。 ではこれらの知識をふまえて、AWSを使ったアプリやサイトのHTTPS化についてまとめます。

2.S3の静的コンテンツをCloudFrontでHTTPS化

S3の静的コンテンツに対して直接HTTPS通信することはできません。なので、間にCDNのCloudFrontを挟み、クライアントとCloudFront間の通信をHTTPS化します。

以下はS3とRoute53のみで、HTTP通信な場合のアーキテクチャ。先週はまだこのブログもこんな感じでした。

S3Websitehosting_withR53.jpg

そして以下が現在のこのブログのアーキテクチャです。 S3にブログのコンテンツを置き、CDNであるCloudFrontとDNS(ドメインネームシステム)兼ドメインレジストラサービスのRoute53を使っています。

CloudFrontは、世界中に配置されたエッジサーバにコンテンツをキャッシュすることができます。CloudFrontを活用することで、クライアントからアクセスがあった際に、最も近くのエッジサーバからレスポンスを返すことができ、低レイテンシで効率的な配信が可能です。

ここではAWSの証明書作成サービス、ACMで作成した証明書をCloudFrontに設置し、クライアントとCloudFront間の通信を暗号化しています。

各サービス詳細はリンク先を参照ください。。

S3Websitehosting_withCF&R53.jpg

CloudFront、Route53でのHTTPS通信の設定の際につまったポイントをまとめておきます。

オリジンの設定

S3でStatic Website Hostingを設定している場合、Origin SettingsのOrigin Domain Nameには以下を設定します。

bucket-name.s3-website-region.amazonaws.com

Origin Domain Nameのところをクリックすると、こんな感じでそれっぽい選択肢がでてくるのですが、Static Website HostingをS3で設定している場合は、これを選択せず、

origin_setting.png

以下を入力します。

bucket-name.s3-website-region.amazonaws.com

詳しくはこちらを参照ください。 オリジンのウェブサイトエンドポイントとして構成されたAmazon S3バケットの使用

証明書の作成はバージニアで!

CloudFrontを使って、ブラウザとS3の静的サイト(独自ドメイン)との通信をHTTPS化するとき証明書をACMで作っている場合は、バージニアリージョンで作らないといけません。東京リージョンとかで作っても、CloudFront上に反映されません。

memo.png

Route53でブログのドメインにCloudFrontのドメインを設定する

HTTPS設定されていない旧アーキテクチャでは、コンテンツが入っているS3のエンドポイントをRoute53で取得したドメインにAriasレコードで設定していました。しかし、CloudFrontをはさむ場合は、クライアントはCloudFrontのエッジにキャッシュされたコンテンツにアクセスしに行くことになrります。なので、Route53で取得したドメインに対して、CloudFrontのドメインを設定しなければなりません。

(おまけ)S3の静的サイトをHugoで作っている場合

config.tomlのbaseURLを【https://ドメイン名】にしなければならない。 CloudFrontでhttps設定をしていて、baseURLを【http://ドメイン名】で設定していると、httpのページでhttpsのコンテンツを読み込もうとすることになる。これにより、ミックスドコンテントと呼ばれる状態になり、セキュアでない状態になってしまう。ブラウザによっては読み込みをブロックしてしまうらしい…今回私のブログでは、CSSが読み込まれず、htmlだけの残念な感じになってしまいました…

html.jpg

3.EC2の動的コンテンツをELBを使ってHTTPS化

EC2をサーバーとする場合は、ELBに証明書を置きます。(EC2に個別に証明書を配置することもできるが)

以下は、前回投稿した”Expressでアプリを作る2/3 -EC2とELBとR53などを使ってデプロイする-”でサンプルアプリを作ったときのアーキテクチャです。CloudFront同様に、ACMで作成した証明書を使い、それをELBに配置します。

SampleExpressAppV2.jpg

こっちはそんなにつまることもないので、以下のチュートリアルなど参考にすれば難なくできます。チュートリアルはCLBのものしかないようですが、ALBで設定するのもほぼ同じ内容なので参考に。

HTTPS リスナーを使用した Classic Load Balancer の作成

また前回投稿した以下記事でもELBでのHTTPS通信の設定方法を簡単に説明していますので、参考まで。

Expressでアプリを作る2/3 -EC2とELBとR53などを使ってデプロイする-

4.まとめ

HTTPS通信について調べていると、わからない言葉や理解できないことががどんどんでてきて沼にはまっていくような気分でした。証明書には具体的にはどんな感じで情報がつまっているのかとか、SSLとTLSの違いとか、わからないことをひたすら調べていると深みにはまっていってる感じがしたので、今回の記事ではこんな感じで簡単にまとめました。

これを皮切りに、セキュリティの知識も深めていこうと思います!