Apache HTTP Serverでの常時SSL/HTTPS化の設定

概要

Webサイト全体をHTTPSのページにすることを常時SSL化または常時HTTPS化と呼ぶらしい。

ここ何年かHTTPS推進の風潮を感じていた。しかし,あまり興味のない分野だったので詳しくは知らなかった。

簡単に流れを整理して,Apache HTTP Serverでの常時SSL/HTTPS化の設定方法も整理する。

発端

常時SSL/HTTPS化の動きは検索サービス最大手のGoogle社が発端となっている。なお,Google社の発表では常時SSL化という言葉は用いられていない。

Googleウェブマスター向け公式ブログでの告知
日付題名説明
2014-08-07HTTPS をランキング シグナルに使用します検索ランキングにHTTPSを考慮しだした。
2015-12-18HTTPS ページが優先的にインデックスに登録されるようになりますHTTPSページが優先的にインデックス化されだした。
2017-07-21Chrome の HTTP 接続におけるセキュリティ強化に向けてChrome 62からHTTPページでデータを入力した場合に警告表示。
2018-02-27保護されたウェブの普及を目指してChrome 68から保護されていませんと表示される。
2018-07-27Chrome のセキュリティにとって大きな一歩: HTTP ページに「保護されていません」と表示されるようになります Chrome 68から保護されていませんと表示される。
2019-10-03Google Online Security Blog: No More Mixed Messages About HTTPSChromeでサイト内の混合コンテントを段階的にブロックすると発表。

2014-08-07にHTTPSを検索ランキングに考慮することを発表し,Google Chromeでの警告表示を強調するなど,徐々にHTTPSの推進を強くしてきたようだ。

検索サービスはGoogleの寡占状態である以上,対応するしかなさそうだ。

それとは別に,安全な通信を前提とすることで,Geolocation, Devicemotion, Service Workerや認証関係のWebブラウザーの新しい機能を使うことができるという利点もあるため,HTTPS化の対応をしたほうがよいようだ。

方針

まず,HTTPSを導入してベースのサイトをHTTPS化する。これは,過去に行った「CertbotによるLet’s Encryptの証明書の取得」と「Apache HTTP ServerでのHTTPSの設定方法」で対応できる。

ただ,これだけだとHTTPのページが残っており,古いリンクやURLの直接指定などでアクセスされる可能性がある。

そこで,以下の3点を施して,既存のHTTPへのアクセスを抑制し,HTTPSへのアクセスに誘導する。

Apacheでの常時SSL/HTTPS化の基本方針
  1. HTTPからHTTPSへのリダイレクト
  2. HSTSの対応
  3. プリロードHSTSへの登録

設定にあたっては以下の情報を参考にした。特に,2番目のIPAが推奨しているサーバーの設定が参考になった。

情報源
  1. HSTS (HTTP Strict Transport Security) の導入 – Qiita
  2. TLS暗号設定ガイドライン~安全なウェブサイトのために(暗号設定対策編)~:IPA 独立行政法人 情報処理推進機構: TLS暗号設定 サーバー設定編 p. 12 5.1 Apacheの場合
HTTPからHTTPSへのダイレクト

HTTPへのアクセスをHTTPSへのアクセスにリダイレクトする。以下の内容をhttpd.confに追加する。

LoadModule rewrite_module modules/mod_rewrite.so

<If "%{HTTPS} == 'off' && %{REQUEST_URI} !~ m#^/\.well-known#"> RewriteEngine On RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI}?%{QUERY_STRING} [L,R=301] </If>

Let’s Encryptによる証明書を使っている場合,証明書の更新時に.well-knownへのHTTPでのアクセスが必要になる。そのため,<If>指令で%{HTTPS}のチェックの後に,.well-knownへのアクセスのチェックをしている。

これでリダイレクトの設定は完了となる。

HTTP Strict Transport Security (HSTS)

HTTPのページにアクセスした場合にHTTPSのページにリダイレクトさせたとしても,リダイレクト前にHTTPのページにアクセスされることに変わりない。そのため,HTTPのページへのアクセス時に平文通信が発生し,中間攻撃を許してしまう。

これを防ぐために,RFC 6797で規定されているHTTP Strict Transport Security (HSTS) が存在する。

WebサーバーのHTTPS応答に以下のHTTP応答ヘッダーを含めることで,次回以降,HTTPでアクセスせずに,HTTPSでアクセスするようにWebブラウザーに指示できる。

Strict-Transport-Security:max-age=有効期間秒数;includeSubDomains

これにより,HTTPへのアクセス自体を回避できる。

Apacheでの設定 (httpd.conf) は以下の通りとなる。

LoadModule headers_module modules/mod_headers.so

<If "%{HTTPS} == 'on'"> Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" </If>

この設定では,サブドメインも含めて365日が有効期間となる。なお,後述するプリロードHSTSの設定 (preload) も便宜上ここでは記している。

.htaccessでの設定

ここまでのリダイレクトとHSTSの設定をまとめると,以下のhttpd.confとなる。GitHubでも念のため公開している。

LoadModule headers_module modules/mod_headers.so
LoadModule rewrite_module modules/mod_rewrite.so

<If "%{HTTPS} == 'on'">
    Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"
</If>
<ElseIf "%{REQUEST_URI} !~ m#^/\.well-known#">
    RewriteEngine On
    RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI}?%{QUERY_STRING} [L,R=301]
</ElseIf>

設定はLoadModule指令以外は.htaccessでも通用するものとなっている。念のため,.htaccessでの設定例は以下となる。

## `httpd.conf` で以下の3指令を指定しておく。
# LoadModule headers_module modules/mod_headers.so # LoadModule rewrite_module modules/mod_rewrite.so # AllowOverride FileInfo <If "%{HTTPS} == 'on'"> Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" </If> <ElseIf "%{REQUEST_URI} !~ m#^/\.well-known#"> RewriteEngine On RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI}?%{QUERY_STRING} [L,R=301] </ElseIf>

.htaccessを使う場合,httpd.confLoadModulemod_headers.somod_rewrite.soを読み込む他,AllowOverride FileInfoを指定しておく必要がある。

IPAのサーバーの設定例は,<VirtualHost>指令を使ったもので,httpd.confでの設定しか考慮しておらず,.htaccessでの設定が考慮されていなかった。

そのため,どちらも共通で通用する設定を考えて今回記した。

設定の共通化に当たって特に工夫したところはRewriteRule指令だ。当初は以下のような後方参照を使ってやっていた。

RewriteRule ^/?(.*) https://%{SERVER_NAME}/$1 [L,R=301]

しかし,これだと.htaccessでは第1引数のパターンにファイルシステムパスがきてしまい,うまく対応できなかった。

そこで,以下のようにリダイレクト先を全てサーバー変数で指定することで,httpd.conf.htaccessの違いを吸収した。

RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI}?%{QUERY_STRING} [L,R=301]
プリロードHSTS (Preload HSTS)

HSTSにより次回以降のHTTPアクセスを回避できるが,どうしても初回のHTTPアクセスを回避できない。HSTSは,一度HTTPSのページにアクセスして,HSTSヘッダーを受け取ってから初めて機能するからだ。この初回のHTTPアクセスを回避するための仕組みとして,プリロードHSTS (Preload HSTS) が存在する。

思っていたより文量が多くなったので,別の記事「プリロードHSTS (Preload HSTS) の登録方法」に分離したので,こちらを参照する。

結論

Apache HTTP Serverでの常時HTTPS化の設定方法を記した。

常時HTTPS化にあたっては,ドメインの設定,Let’s Encryptでの証明書の発行,HTTPSの設定,リダイレクト,HSTS,プリロードHSTSと設定項目がいくつもあり,7月半ばに取り組み始めて8月9日に完了するまで2-3週間もかかってしまった。

Apacheの設定に自信がなく,そこを勉強し直したので時間がかかった。ようやく世間のHTTPS化の流れに追いつけてよかった。

AWSなどに自前のWebアプリケーションを展開する際には,今回の手順を元に手早く常時HTTPS化を実現したい。

Apache HTTP Serverでの常時SSL/HTTPS化の設定” に対して1件のコメントがあります。

コメントを残す

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