Apache HTTP Serverでの常時SSL/HTTPS化の設定
概要
Webサイト全体をHTTPSのページにすることを常時SSL化または常時HTTPS化と呼ぶらしい。
ここ何年かHTTPS推進の風潮を感じていた。しかし,あまり興味のない分野だったので詳しくは知らなかった。
簡単に流れを整理して,Apache HTTP Serverでの常時SSL/HTTPS化の設定方法も整理する。
発端
常時SSL/HTTPS化の動きは検索サービス最大手のGoogle社が発端となっている。なお,Google社の発表では常時SSL化という言葉は用いられていない。
日付 | 題名 | 説明 |
---|---|---|
2014-08-07 | HTTPS をランキング シグナルに使用します | 検索ランキングにHTTPSを考慮しだした。 |
2015-12-18 | HTTPS ページが優先的にインデックスに登録されるようになります | HTTPSページが優先的にインデックス化されだした。 |
2017-07-21 | Chrome の HTTP 接続におけるセキュリティ強化に向けて | Chrome 62からHTTPページでデータを入力した場合に警告表示。 |
2018-02-27 | 保護されたウェブの普及を目指して | Chrome 68から保護されていませんと表示される。 |
2018-07-27 | Chrome のセキュリティにとって大きな一歩: HTTP ページに「保護されていません」と表示されるようになります | Chrome 68から保護されていませんと表示される。 |
2019-10-03 | Google Online Security Blog: No More Mixed Messages About HTTPS | Chromeでサイト内の混合コンテントを段階的にブロックすると発表。 |
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へのアクセスに誘導する。
設定にあたっては以下の情報を参考にした。特に,2番目のIPAが推奨しているサーバーの設定が参考になった。
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.conf
でLoadModule
でmod_headers.so
とmod_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件のコメントがあります。