WEBの通信をhttps暗号化3 (非暗号通信から暗号通信へ転送)

前回までに、WordPressをインストールして、それっぽいトップページを作成できました。また、お名前.comレンタルサーバーをLet’s EncryptのSSL証明書を利用してWEBサーバーは暗号化通信が可能状態にできました。これで、WEBブラウザーがhttps://nishy-software.com/ のようにhttpsを使ってWEBサイトにアクセスしてくれれば、暗号化通信となります。しかし、http://nishy-software.com/ でアクセスすると相変わらず非暗号通信となります。これも暗号化通信になるようにします。暗号化通信化の挑戦3です。

さて、どうすればよいのでしょうか?

まずは、契約したお名前.comレンタルサーバーの共用サーバーSDで使用されているWEBサーバーソフトウェアを確認します。

ここ(【共用サーバーSD】サーバーのスペックを教えてください)に情報がありました。2018年1月29時点のスナップショットは以下の通りです。

OS SUN Solaris 10 (SunOS 5.10) / 64bit
Web Apache 2.2.34
Mail Postfix
Perl 5.8.4
PHP 5.6.32 / 7.0.25 / 7.1.11
Ruby 1.8.7
Python 2.5.5
MySQL 5.6.14

WEBサーバーはApacheでした。Apatcheの設定ファイルといえば .htaccess ファイルです。レンタルサーバーによっては、.htaccessファイルが使えないことがあります。そこで共用サーバーSDで .htaccess ファイルが使えるかどうか確認します。

ここ(【共用サーバーSD】.htaccessを使ってアクセス制御はできますか?)に情報がありました。2018年1月29時点の情報ですが .htaccess ファイルは使えるとのこと。

なので、.htaccessファイルを使って、非暗号化通信(http)アクセスがあったらあ暗号化通信(https)アクセスに転送するようにWEBサーバーの設定(.htaccessファイル)に追加します。

さて、設定すべき .htaccessファイル はどこにあるのでしょうか?
お名前.comレンタルサーバーの共用サーバーSDの場合、サーバーのディレクトリ構造は以下のようになっています。

/export/sd123/www/jp/r/e/gmoserver/2/0/sd123456/nishy-software.com

太字のところが、各契約ユーザーに与えられたストレージへのパスです(数字だけは架空のものに置き換えています)。その下にドメイン名のフォルダーが存在します。.htaccess ファイルは、ドメイン名のフォルダーに置くことにより、そのドメイン名のWEBアクセスに対して有効化されます。なので、ここにある .htaccess ファイルを編集します。.htaccessファイルがなかったら新規作成します。

私の場合、

# BEGIN WordPress
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /wp/
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /wp/index.php [L]
</IfModule>

# END WordPress

のような、WordPressのインストール時に作成された.htaccessファイルがありました。そのため、そのファイルの先頭に新たな<IfModule mod_rewrite.c>~</IfModule>ブロックを作成してその中に設定しました。新たなブロックを作成して追加したのは、今後、WordPressによる自動編集のときに値を上書きされないようにするためです。

結果として .htaccessファイルには、以下の設定しました。

<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
 
RewriteCond %{HTTPS} off
RewriteCond %{HTTP:X-Forwarded-Proto} !=https
RewriteCond %{HTTP:CloudFront-Forwarded-Proto} !=https
RewriteCond %{REQUEST_URI} !^.*\.(js|css|gif|jpg|png|ico|svg)$
RewriteRule ^.*$ https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
</IfModule>

# BEGIN WordPress
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /wp/
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /wp/index.php [L]
</IfModule>

# END WordPress

太字のところが、非暗号化通信→暗号化通信の転送のために追加した設定です。具体的には転送設定(RewriteRule)とその条件(RewriteCond)となります。

まず、転送設定(RewriteRule)の説明です。

RewriteRule ^.*$ https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]

は、^.*$ は正規表現でのパターンマッチングです。^がURLの先頭を表し、$がURLの最後を表します。その中の .* は、. が任意の一文字に一致することを表し、* は、直前のもの(今回は任意の一文字)が0回以上一致することを表します。結果として、URLはなんでも一致しますよという記述です。

ただしパターンマッチングが対象とするのは、URL全体ではなく、ホスト名部分を除いた部分です(RewriteBase が / の場合)。たとえばURLが http://nishy-software.com/xxx/ccc.html とした場合、パターンマッチングが対象とするのは太文字の xxx/ccc.html の部分です。転送先はというと、https://%{HTTP_HOST}%{REQUEST_URI} と指定しており、http:をhttps:に書き換えたURLとなっています。%{HTTP_HOST}はWEBにアクセスしてきたときのホスト名となります。%{REQUEST_URI}は、ホスト名以下の部分のRequest URIです。

[R=301,L]は、Rは転送(リダイレクト)を表し、301は恒久的な転送を意味します。302であったら一時的な転送を意味します。LはこのRewriteRuleが実行されたら、処理はここで終了する(この行以下のルールは処理しない)ことを意味します。http -> https の転送は一時的でなないので R=301 と指定しました。

RewriteRuleを実行する条件(RewirteCond) は、4つ設定しました。この4つはANDで評価されます。そのため、4つの条件がすべて成り立つときのみRewriteRuleが実行されます。続いて4つの条件の説明をします。

まず、

RewriteCond %{HTTPS} off

は、「WEBブラウザーからのWEBアクセスの暗号化通信がoffだったら」という条件です。今回の行いたいことの主条件となります。

次は、先に4つ目の条件を説明します。

RewriteCond %{REQUEST_URI} !^.*\.(js|css|gif|jpg|png|ico|svg)$

は、「Request URIが、.js, .css, .gif, .jpg, .png, .ico, .svg で終わらないもの」という条件です。先頭の!が否定の意味になります。jsファイル、cssファイル、画像ファイル(gif,jpg,png,ico,svg)のアクセスはWEBブラウザーの通信方法の主張を尊重しましょうぐらいの意味です。これらのファイルはユーザーがURLを直接指定してアクセスすることは少ないので、強制的に非暗号化通信から暗号化通信に転送しなくてもいいかなぁと思い、追加しました。

RewriteCond %{HTTP:X-Forwarded-Proto} !=https
RewriteCond %{HTTP:CloudFront-Forwarded-Proto} !=https

この2つ目、3つ目の条件は、今回の共用サーバーSDでは必要のない設定ですが、将来そのような環境に変更になっても問題ないように設定しておきました。処理の高速化や負荷分散のためにロードバランサーなどのSSLアクセラレーターがWEBブラウザーとWEBサーバーの間に入ってきたときに必要となる設定です。というのは、この場合、

WEBブラウザー → SSLアクセラレーター → WEBサーバー

という経路で通信します。このとき「WEBブラウザー → SSLアクセラレーター」が暗号化通信(https)であっても、「SSLアクセラレーター → WEBサーバー」は非暗号化通信(http)となります。WEBブラウザーは暗号化通信をしているにもかかわらず、WEBサーバーでは、「RewriteCond %{HTTPS} off」の条件が成り立ってしまいます。結果として、WEBサーバーでhttpsへの転送が発生し、永遠と転送が発生してしまうことになります。これを避けるための設定です。

経路の間にSSLアクセラレーターが入っている場合、ほとんどの場合、HTTPヘッダーに、その目印が追加されます。WEBサーバーではその目印を使って httpsへの転送をしないようにします。その目印の名前がX-Forwarded-Proto であったり、CloudFront-Forwarded-Protoであったりします。SSLアクセラレーターを経由した場合、これらのパラメータにhttpsという値が設定されます。

2つ目、3つ目の条件は、これらのパラメーターの値が https でなかったらという条件です。これで、経路にSSLアクセラレーターがあっても転送のループが避けられます。

設定が終わって、http://nishy-software.com/ にWEBブラウザーでアクセスしたら、無事 https://nishy-software.com/ に転送されることを確認できました。

これで、WEBサーバーの暗号化通信の設定は完了です。

次回へ続く

コメントを残す