カテゴリー
Windows

本家のお世話-#117。(HTTP/2 対応のための HTTPS 化)

The same article in English
投稿アップデート情報  追記(11/2) 追記2(11/6) 追記3(2017/6/20)

 10/13 に Apache 2.4.17 が出たのだが, Steffen のとこでも, 10/12 に同バージョンが出ていた。今回のバージョンからコアモジュールに mod_http2 が含まれるようになった。 Steffen はそのために, nghttp2 v1.3.4 も含めてビルドしてくれているようだ。その辺は, ChangeLog を見ていただきたい。というわけで,自鯖で HTTP/2 のテストが出来る。あくまで,テストだよ~ん。だって,「This module is experimental.」て書いてあるんだモン。

 でも,その前にすることが多くて。アヘッ。なにしろ,全サイトを HTTPS 化しなくてはいけない。スペックを読むと,「HTTP/2 does not require encryption」と書いてあるんだが,実際問題として,今のところ HTTPS になっていないと,受けつけてくれるブラウザがない。 2013/6 から,ずっと, WordPress のアドミンエリアではクライアント認証を使ってきたが,いまだに自前証明書だかんね。使うのが自分だけだったからそれでよかったわけだが,今回はそれではまずい。全サイトを HTTPS 化すると,当然,他の人も使える証明書を用意しないといけない。けどねぇ,ちゃんとした証明書で,クライアント認証までというと,結構お高いのヨ。そんなこんなで,アドミンエリアでのクライアント認証はあきらめて,ベーシック認証で行くことにした。まあ,全エリア HTTPS 化するから,ベーシック認証もそれ越えになるというわけで,幾分,安全らしいし。
 
 で,どこで証明書を手に入れるかということだが, StartSSL に行った。くりくりさんから,いつも,例に上がっていたし(汗)。もちろん,只のを入手。手に入れ方はいろんなサイトに書いてあるから省くが,以下の 2 点には気をつけたほうがいいよ。

  1. server.key と server.csr は,自鯖上で作ったほうがいいと思う。だって, server.key ってのは,秘密鍵だよ。これがネット上をあっちゃこっちゃ飛び回って落ちてくるって,不安じゃん。ねっ?
  2. もう一つは, SSLCertificateChainFile (=sub.class1.server.ca.pem) がいるんだが,これをどっから落とすか。必ず,ログインして Control Panel から落とすこと。「How to Install」のページにリンクがあるんだが,ここからはちゃんとした PEM ファイルが落とせなかった。

 これで証明書関係の必要なファイルがそろった, server.crt, server.key および sub.class1.server.ca.pem。
 
 さて, httpd-ssl.conf を再編集しよう。あっ,忘れるところだったが,うちの場合は,すでに, httpd.conf に Listen 443 は追加してある。 2013/6 から SSL を使ってたからね。 httpd-ssl.conf についてのオリジナルからの変更点は,下記の通り。

  1. SSLCipherSuite AESGCM:HIGH:MEDIUM:!MD5:!RC4
    SSLProxyCipherSuite AESGCM:HIGH:MEDIUM:!MD5:!RC4
    Suite に AESGCM を追加した。初めはデフォルト(=HIGH:MEDIUM:!MD5:!RC4)のままでやったんだけど, HTTP/2 にしたら, Google Chrome v46 から「ERR_SPDY_INADEQUATE_TRANSPORT_SECURITY」というエラーをいただいた。 TLS 1.2 Cipher Suite Black List のせいらしい。実のところ,モダンブラウザは GCM モードを要求して来るんだが,デフォルトでも,ちゃんとこんなふうに GCM モードは含んでいる。しかし,順番を見ると,最初のふたつだけで,あとは違うモードが来るし,初めのふたつは hash が SHA384 だ。経験から言うと, Google Chrome は SHA384 を受け入れない。さらに,うちのサーバは当然ながら, SSLv3 不可になっている。ブラウザはリストの順に cipher を試していって, SSLv3 レベルが出てきたらあきらめてしまうんだろう。 AESGCM(=AESGCM:HIGH:MEDIUM:!MD5:!RC4)を加えると,リスト内の並び順が,こんなふうに変わる。 AESGCM だけにすると,こんなことになるが, SSL LABS’s SSL Server Test の結果を見ると,現時点の最新のブラウザだけしかサポートしてないみたいだ。
  2. SSLSessionCache "shmcb:x:/Apache24/logs/ssl_scache(512000)"
    shmcb:x:/Apache24 のところを自分の ServerRoot と揃えよう。
  3. SSLUseStapling On
    SSLStaplingCache "shmcb:x:/Apache24/logs/ssl_stapling(32768)"
    SSLStaplingStandardCacheTimeout 3600
    SSLStaplingErrorCacheTimeout 600
    以上は CRL の代わりに OCSP Stapling を使うための設定。
  4. 下記の VirtualHost は o6asan.com:443 に対するアクセスだけを処理する。それ以外は, _default_ vhosts にやらせる格好にした。
    <VirtualHost o6asan.com:443>
    DocumentRoot [My DocumentRoot]
    ServerName o6asan.com
    ServerAdmin [My email address]
    ServerAlias www.o6asan.com
     
    <Directory [My DocumentRoot]>
        Options FollowSymLinks
        AllowOverride FileInfo AuthConfig Indexes Limit Options=Indexes
        Require all granted
    </Directory>
    FileInfo は rewrite を, AuthConfig は require を, Indexes は DirectoryIndex を, Limit は Allow Deny Order を,そして Options=Indexes は Options -Indexes を .htaccess で使うのに必要なんだよね。
  5. <Files "wp-login.php">
        <RequireAny>
            Require ip [Lan IP の範囲]
            <RequireAll>
                AuthType Basic
                AuthName "エリア名"
                AuthUserFile "Password ファイルの絶対パス"
                Require user ユーザ名
     
                Require [モバイルホスト名]
            </RequireAll>
        </RequireAny>
    </Files>
    <"wp-admin ディレクトリの絶対パス">
        <RequireAny>
            Require ip [Lan IP の範囲]
            <RequireAll>
                AuthType Basic
                AuthName "エリア名"
                AuthUserFile "Password ファイルの絶対パス"
                Require user ユーザ名
     
                Require [モバイルホスト名]
            </RequireAll>
        </RequireAny>
        </RequireAny>
        <Files "admin-ajax.php">
            Require all granted
        </Files>
    </Directory>
    上記は, WordPress のアドミンエリアのための設定。ユーザは私だけである。当然ながら password ファイルを作った。「認証、承認、アクセス制御」参照。
    >htpasswd -c [Password ファイルの絶対パス] ユーザ名
    Password ファイルは,サーバ内のネットからアクセスできない場所に置くこと。
  6. SSLCertificateFile "x:/Apache24/conf/server.crt"
    SSLCertificateKeyFile "x:/Apache24/conf/server.key
    Apache2.4.8 から「SSLCertificateChainFile is deprecated」となっているので, nginx スタイルの server.crt を使う。 server.crt と sub.class1.server.ca.pem は PEM なので,テキストエディタで繋いでひとつにしてやる。順番を間違えないようにね。下記の通り。
       -------------------
          —–BEGIN CERTIFICATE—–
             server.crt
          —–END CERTIFICATE—–
          —–BEGIN CERTIFICATE—–
           sub.class1.server.ca.pem
          —–END CERTIFICATE—–
       -------------------
    server.key のパスフレーズが Apache の自動起動の妨げになる場合は, ここを参照して,解決を!!
     
    ネット上で SSLCACertificate をセットしなさいという記事をいくつか見たが,クライアント認証を使わないなら,その必要はないはず。
  7. <Directory [cgi-bin ディレクトリの絶対パス]>
  8. 以下が _default_ vhosts。 ここで 80 ポートからのアクセスその他を処理する。
    <VirtualHost _default_:*>
    DocumentRoot [2 番目の DocumentRoot]
    <Directory [2 番目の DocumentRoot]>
        Options FollowSymLinks
        AllowOverride FileInfo
        Require all granted
    </Directory>
    </VirtualHost>
    [2 番目の DocumentRoot] 内には index.html と .htaccess を入れてある。
    .htaccess の中は以下の通り。
    RewriteBase /
     
    RewriteEngine on
    RewriteCond %{SERVER_PORT} !^443$ [OR]
    RewriteCond %{HTTPS} off
    RewriteRule ^(.*)$ https://o6asan.com/$1 [R=301,L]

 2 枚の証明書をサーバの適切な場所にアップロード。では, Apache を再起動。おっと! WordPress が済んでないな。その話は,次の記事に書くことにしよう。ああ,疲れた。

追記(11/2):
 access_log を <VirtualHost></VirtualHost> 内に移すのを忘れていた。なんで気づいたかってぇと,久しぶりに AWStats を見たら, HTTP から HTTPS へ移動後が空っぽだった。 Log ディレクティブを <VirtualHost></VirtualHost> 内に書き込んだ。今は前通りレポートが見れる。ホッ。

Chrome warning
Chrome warning
追記2(11/6):

 NJ2100 上の Windows10 において, HTTPS 移行後も Google Chrome が右のようなページアイコンを https://o6asan.com の前に表示する。つまり,鍵アイコンが出ない。一方, CF-J10 上の Windows10においては, Chrome は緑の鍵アイコンを表示している。なんでよと思っていたのだが,昨日,理屈が分かった。これって,サーバのせいではなく,ブラウザのキッシュのせいだった。 Chrome がサーバから送られた SHA2 の中間証明書を使わずに, IE 組み込みの証明書を使うという仕様になっているのだ。同じようなことが Firefox でも起こっていて,火狐の場合は, NJ2100 上では,緑の鍵アイコンを, CF-J10 上では灰色の鍵アイコンを表示していた。で,少し詳しく調べてみたのだが,その結果が次表だ。

 NJ2100 上の Chrome ページアイコン表示
NJ2100 上の Chrome ページアイコン表示
CF-J10 上の Chrome 緑の鍵アイコン表示
CF-J10 上の Chrome 緑の鍵アイコン表示
NJ2100 上の Firefox 緑の鍵アイコン表示
NJ2100 上の Firefox 緑の鍵アイコン表示
CF-J10 上の Firefox 灰色の鍵アイコン表示
CF-J10 上の Firefox 灰色の鍵アイコン表示

 というわけで,NJ2100 のほうでは, Chrome のトラストストアから, SHA1 の sub.class1.server.ca.pem をデリートして, Chrome を再起動したら,緑の鍵アイコンがアドレスバーに表示されるようになった。

 CF-J10 のほうでも, Firefox に同じことをやったのだが,相変わらず, SHA1 のほうが使われる。で,もっときっちりとということで,キャッシュを全部クリアし,トラストストアからすべての StartCom Class 1 Primary Intermediate Server CA を削除したのち, Windows10 を再起動して,改めて https://o6asan.com にアクセスしたら,やっとこ, SHA2 の中間証明書を使ってくれるようになった。

 上記のことは,クライアントの環境によっておこるものだが,アップデートをちゃんとやっていない場合とかは,起こりやすいと思う。しかし,私は,パソコンのアップデートを怠ったことはないので,今回のことは私のせいじゃないよね。
 Google みたいに,ブラウザベンダーのほうで,サイトの HTTPS 化を推し進めるなら,この辺のことについては,一般の人が困らないように,しっかりやってもらわないとね。ユーザがベンダーから要請された証明書のアップデートをしっかりやっているにもかかわらず,最新のブラウザが古いもののほうを使うようじゃ困るよ。

 ところで, StartCom Certification Authority については, Firefox は SHA2 に移行しているが, Chrome (IE もということだ) は未だに SHA1 のほうを使っている。 SSLLABS によると,「Weak or insecure signature, but no impact on root certificate」なんだそうだ。去年の 9 月時点での Ivan Ristić の見解はこんな感じになっていた。

追記3(2017/6/20):

「本家のお世話-#117。(HTTP/2 対応のための HTTPS 化)」への6件の返信

おはようございます。
今回だけでも大分ながいですね?

一気にhttpsからhttp/2を詳しくかいてますからやることがおおくなって大変でしょう。今後の記事もがんばってください。
俺の方はサーバーにipエイリアスを使い二つ以上のipで運用できるか実験中です。
うまくいけば片方でapache、片方でnginxなんてできるのかもしれませんね?
随分トリッキーと思いつつついでに挑戦してみるつもりです。

くりくりさん,おはようございます。

> 今回だけでも大分ながいですね?
> 今後の記事もがんばってください。
はい,書くことに挫折しそうです。 HTTPS 化については,もともとローカルでいろいろ試していたので,実際の作業は,くりくりさんが「あれ、いつのまにhttpsしかもh2になってますね。」とお書きになったように,合間合間でやってる内に到達したレベルだったんですが―もちろんそれでも,やることは満載でしたが―それをまとめて書こうとしたら,最近の根気のなさのせいか,へたりました。でも,頑張ります 💪 。

> ipエイリアス
実は,ここの VirtualHost の件で使えないかと,「Windows で IP エイリアスを実現する」を参考にやってみたことがあるのですが, WordPress は IP 依存ではなくて, Host で解決してるせいか,ダメでした。今回の HTTPS 化では,結局, StartSSL の無料証明書を使いつつの自前証明書でのクライアント認証はあきらめてますが,まだ,完全に投げてはいませんです。

> うまくいけば片方でapache、片方でnginxなんてできるのかもしれませんね?
それは,面白そうですね。

おはようございます。
apacheのipエイリアスはうまくいきました。
ロードバランサー的にnginxを試してみたんですが
どうも2枚の証明書を使うのはむりぽいです。
設定が複雑すぎてあれとかなってしまいます。
http://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_ssl_verify
ここら辺を使えばうまくいくかもしれませんが、
ギブアップw
ちょっとはお役に立てれば幸いです。

くりくりさん,こんばんは。

本当に,いろいろありがとうございました。

しかし,ロードバランサ―というものは,そんな使い方もできるんですか?
バランサーで内部のサーバのどれにつながるかは,バランサーが負荷の状況で勝手に決めるんだと思っていました。
でも,
> 設定が複雑すぎてあれとかなってしまいます。
ということは,「あれ」ということになっても,できるのはできるということですね。本来のバランサーの目的からすると想定外の使い方でしょうから,複雑怪奇な設定になるのかもしれませんが,できるんだということだけで,ビックリです。

proxy_ssl_verify
リンク先,見てみましたが,読んでも,まだよくわかりません。もう少し,プロキシに関して勉強してから,チャレンジしてみます。今のリアルの状況ではいつになるかわかりませんが……

こんばんは

>本当に,いろいろありがとうございました。

自分が試してみたくてやっていますから
お気になさらず。

>ロードバランサ―というものは,そんな使い方もできるんですか?

リバースプロキシーですね。

>できるんだということだけで,ビックリです。

あれから色々想定してみたんですが、どうしてもポートの問題がからんでくるで
80と443ポート以外だめとなると難しいです。
ソケット通信で回避できるかなとおもったら、
linuxはあるみたいですけどwindowsはないみたいだし。apacheで定義できるみたいですがポートが絡んでくるみたいです。

何か方法を思いついたら試してみたいと思います。

くりくりさん,こんにちは。

> >ロードバランサ―というものは,そんな使い方もできるんですか?
> リバースプロキシーですね。
> >できるんだということだけで,ビックリです。
ああ,そういう意味ですか。初めから,リバースプロキシとして構成したほうが,頭の中がこんがらがらなくていいかもですね。

私は,当記事の続きを書いているのですが,時間が細切れでなかなかはかどりません。

o6asan へ返信する コメントをキャンセル

メールアドレスが公開されることはありません。 が付いている欄は必須項目です