SSL化を強制するのは当たり前。ついでにHSTSも対応しておこう

昨年Google先生がSSLを標準化したことを受けて、自前のサイトも預かっているサイトもすべてSSL化した。

レンタルサーバーなら最近は無料のSSLがついているケースがほとんどで、ついていないホスティングサービスは技術力がないから使わない方がいい。

これからは有料のSSLと無料のSSLの違いについても考えて選択をした方が吉なんでしょうね。

プロモーションサイトとか未だにSSL化されてないサイトとかもあるし、映画とかアニメのプロモーションから企業サイトだってSSL化されてないサイトが散見されるけど、そうしたサイトは大抵、保守もメンテナンスもしていないサイトなので見ない方がよろしい。

さて、SSL化の手順(WordPressだけどね)

HTMLの場合はコードを書いていく際にHTTPS化をしてあげる必要があるので単純にローカルでHTTPSに置換してあげて、WEBサイトをホスティングしているサーバーにSSLを適応してあげればよい。

自前の場合は、インフラに頼みましょう。Let’s EncryptとかでSSL化してくれるよ。

1.作業の手順 WordPressの設定からURLを変更

下の画像の2箇所をhttpからhttpsに変更する。

これでWordPressの設定としては問題ありません。

ただし、テーマによってはCSSなどやコードででFontなど外部CDNを読み込む先に

http://

となっている場合があります。

これをhttp:をなしにして
//から始まるように記述してあげる必要があります。

無料のテーマなどはこうしたことが起因としていてSSLが対応が完全に出来ない場合があります。

2.「.htaccess」に「http→https」301リダイレクトの設定をする

.htaccessにコードを追記します。

ネットを調べるとよく以下の2つのコードが出ている

コード例1

<IfModule mod_rewrite.c>
RewriteEngine on
RewriteCond %{HTTPS} !=on [NC]
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
</IfModule>

コード例2

<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
</IfModule>

コードをみればわかるとおり実質的な違いは用法の違いで差異はほとんどないけど、実際にはコード2を入れる例の方が正しいような気がする。

また、レンタルサーバーなどは上流にロードバランサーなども配置されているケースがほとんどだから、それも考慮してAWSELBでELB配下にWebサーバーを置いている場合は

<IfModule mod_rewrite.c>
RewriteEngine on
RewriteCond %{HTTP:X-Forwarded-Proto} !https
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
</IfModule>

の方が良いと思う。

これならSSLを強制してくれるしね。

次に既存記事内のコンテンツをSSL化

プラグインのSearch RegexやコードのSearch Regexで置換をしてあげる方が安全だけど、さらに追記をするとMySQLなどでDBこコンテンツ記述を一括して置換をしてあげる。

// SQLコマンド
UPDATE wp_options SET option_value = replace(option_value, 'http://ドメイン', 'https://ドメイン') WHERE option_name = 'home' OR option_name = 'siteurl';
UPDATE wp_posts SET guid = replace(guid, 'http://ドメイン','https://ドメイン');
UPDATE wp_posts SET post_content = replace(post_content, 'http://ドメイン', 'https://ドメイン');

DBをいじるのは知識がないと危険なので、Search Regexでやった方がいいけど、これでも出来るって意味で書いておく。

UPDATE wp_options SET option_value = replace(option_value, ‘http://ドメイン’, ‘https://ドメイン’) WHERE option_name = ‘home’ OR option_name = ‘siteurl’;

この部分で上記の対応で言うと画像部分のURLを変更するという手順を踏んでいるわけだ

これでホームとサイトURLの置換をしているということ。

次に

UPDATE wp_posts SET guid = replace(guid, ‘http://ドメイン’,’https://ドメイン’);

UPDATE wp_posts SET post_content = replace(post_content, ‘http://ドメイン’, ‘https://ドメイン’);

はDBのwp_postsにあるhttp://ドメインをhttps://ドメインに置換している。

これでコンテンツの置換は完了。

昔は特に、このSQLをいじる方法だとWordPressくんが正しく置換してくれないのか、動かなくなるケースがあったけど今はサイト移転や移行プロセスでSQLをいじるケースがあるので、そうした対応をするときのために対策をされたのか、動作しないと言う事はなくなっている。

4.HSTSの設定

HTTP Strict Transport Security(しばしば HSTS と略されます)は、HTTP の代わりに HTTPS を用いて通信を行うよう、Web サイトからブラウザにに伝達するためのセキュリティ機能です。

例えばユーザが http://www.foo.com/ または単に foo.com と入力すると、Web サイトが HTTP で受け付けたコネクションを HTTPS へリダイレクトする場合、リダイレクトされるまでユーザは暗号化されない接続を行うことになるでしょう。

この方法には、リダイレクトによりユーザを元のサイトの安全なバージョンではなく悪意のあるサイトへ誘導するという、中間者攻撃のおそれがあります。

HTTP Strict Transport Security 機能により、Web サイトはブラウザに対して、そのサイトでは HTTP を使用せず、代わりに HTTPS へ置き換えてアクセスすることを試みるように伝達することが可能になります。

MDNより

というわけで、

.htaccessに以下のコードを追記

<IfModule mod_headers.c>
Header set Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"
</IfModule>

これをリライトコードとしてWordPressの記述(# BEGIN WordPress)以前に書いてあげる。

これで対応。

始めに対応したときには

max-age=10886400は、max-ageとしていたけど短いよ~と警告がでたのでmax-age=31536000にしてあげた。

まあ、長い分にはサイト自体が古い場合は有効性があるので、良いことだろう。

情報

このフォームは、ChromeのHTTP Strict Transport Security(HSTS)プリロードリストに含めるドメインを送信するために使用されます。これは、HTTPSのみとしてChromeにハードコードされているサイトのリストです。

ほとんどの主要なブラウザ(Chrome、Firefox、Opera、Safari、IE 11およびEdge)には、Chromeリストに基づいてHSTSプリロードリストがあります。(HSTS互換性マトリックスを参照してください。)

提出要件

サイトがpreloadディレクティブをHSTSヘッダーで送信する場合、プレロードリストに含めることを要求していると見なされ、このサイトのフォームを介して送信することができます。

このフォームを使用してHSTSプリロードリストに承認されるには、サイトが次の要件を満たしている必要があります。

有効な証明書を提供する。
ポート80でリッスンしている場合は、同じホスト上のHTTPからHTTPSにリダイレクトします。
HTTPS経由ですべてのサブドメインにサービスを提供する
特に、wwwサブドメインのDNSレコードが存在する場合は、サブドメインのHTTPSをサポートする必要があります。
サーブHSTSヘッダを HTTPS要求のための基本ドメインに:
max-age以上でなければなりません31536000秒(1年)。
includeSubDomainsディレクティブは、指定しなければなりません。
preloadディレクティブは、指定しなければなりません。
HTTPSサイトから追加のリダイレクトを配信する場合、そのリダイレクトにはリダイレクト先のページではなく、HSTSヘッダーが必要です。
HSTSの詳細については、RFC 6797を参照してください。次に、有効なHSTSヘッダーの例を示します。

Strict-Transport-Security: max-age=63072000; includeSubDomains; preload

上記のフォームにドメイン名を再度入力してリクエストのステータスを確認するかchrome://net-internals/#hsts、ブラウザにアクセスして現在のChromeプレロードリストに問い合わせてください。新しいエントリはChromeのソースコードにハードコードされており、安定版に達するまでに数か月かかることに注意してください。

てな感じです。

HTSTプリロード
HTSTプリロード

このサイトでHTSTのチェックと送信が出来るのでやっておくと吉。

以上で対応完了ってね。

Xサーバーで入れているhtaccessで書いておく

<IfModule mod_headers.c>
Header set Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"
</IfModule>
# Enable Keep-Alive を設定
<IfModule mod_headers.c>
    Header set Connection keep-alive
</IfModule>
# MIME Type 追加
<IfModule mime_module>
    AddType image/x-icon .ico
    AddType image/svg+xml .svg
    AddType application/x-font-ttf .ttf
    AddType application/x-font-woff .woff
    AddType application/x-font-woff2 .woff2
    AddType application/x-font-opentype .otf
    AddType application/vnd.ms-fontobject .eot
</IfModule>
# BEGIN Cache-Control Headers
<ifModule mod_headers.c>
    <filesMatch "\.(ico|jpe?g|png|gif|swf)$">
        Header set Cache-Control "max-age=604800, public"
    </filesMatch>
    <filesMatch "\.(css)$">
        Header set Cache-Control "public"
    </filesMatch>
    <filesMatch "\.(js)$">
        Header set Cache-Control "private"
    </filesMatch>
    <filesMatch "\.(x?html?|php)$">
        Header set Cache-Control "private, must-revalidate"
    </filesMatch>
</ifModule>
# END Cache-Control Headers wwwなしに設定
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{HTTP_HOST} ^www.ドメイン [NC]
RewriteRule ^(.*)$ https\:\/\/ドメイン\.com\/$1 [R=301,L]
</IfModule>
<IfModule pagespeed_module>
    ModPagespeed on
    # using commands,filters etc
</IfModule>
# BEGIN rlrssslReallySimpleSSL rsssl_version[2.5.22]
<IfModule mod_rewrite.c>
RewriteEngine on
RewriteCond %{HTTP:X-Forwarded-Proto} !https
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
</IfModule>
# END rlrssslReallySimpleSSL
RewriteEngine on
RewriteCond %{HTTP:Accept-Encoding} gzip
RewriteCond %{REQUEST_FILENAME}\.gz -s
RewriteRule .+ %{REQUEST_URI}.gz
#Style sheet (.css)
<FilesMatch "\.css\.gz$">
	ForceType text/css
	AddEncoding x-gzip .gz
</FilesMatch>
#Javascript (.js)
<FilesMatch "\.js\.gz$">
	ForceType application/x-javascript
	AddEncoding x-gzip .gz
</FilesMatch>
#HTML (.html)
<FilesMatch "\.html\.gz$">
	ForceType   text/html
	AddEncoding x-gzip .gz
</FilesMatch>
# BEGIN GzipWpFastestCache
<IfModule mod_deflate.c>
AddType x-font/woff .woff
AddOutputFilterByType DEFLATE image/svg+xml
AddOutputFilterByType DEFLATE text/plain
AddOutputFilterByType DEFLATE text/html
AddOutputFilterByType DEFLATE text/xml
AddOutputFilterByType DEFLATE text/css
AddOutputFilterByType DEFLATE text/javascript
AddOutputFilterByType DEFLATE application/xml
AddOutputFilterByType DEFLATE application/xhtml+xml
AddOutputFilterByType DEFLATE application/rss+xml
AddOutputFilterByType DEFLATE application/javascript
AddOutputFilterByType DEFLATE application/x-javascript
AddOutputFilterByType DEFLATE application/x-font-ttf
AddOutputFilterByType DEFLATE application/vnd.ms-fontobject
AddOutputFilterByType DEFLATE font/opentype font/ttf font/eot font/otf
</IfModule>
# END GzipWpFastestCache
# BEGIN LBCWpFastestCache
<FilesMatch "\.(ico|pdf|flv|jpg|jpeg|png|gif|webp|js|css|swf|x-html|css|xml|js|woff|woff2|ttf|svg|eot)(\.gz)?$">
<IfModule mod_expires.c>
AddType application/font-woff2 .woff2
ExpiresActive On
ExpiresDefault A0
ExpiresByType image/webp A2592000
ExpiresByType image/gif A2592000
ExpiresByType image/png A2592000
ExpiresByType image/jpg A2592000
ExpiresByType image/jpeg A2592000
ExpiresByType image/ico A2592000
ExpiresByType image/svg+xml A2592000
ExpiresByType text/css A2592000
ExpiresByType text/javascript A2592000
ExpiresByType application/javascript A2592000
ExpiresByType application/x-javascript A2592000
ExpiresByType application/font-woff2 A2592000
</IfModule>
<IfModule mod_headers.c>
Header set Expires "max-age=2592000, public"
Header unset ETag
Header set Connection keep-alive
FileETag None
</IfModule>
</FilesMatch>
# END LBCWpFastestCache
# BEGIN WordPress
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>
# END WordPress
ModPagespeed On
#AddHandler fcgid-script .php .phps
#FCGIWrapper "/home/spegasus/s-pegasus.com/xserver_php/php-cgi" .php
#FCGIWrapper "/home/spegasus/s-pegasus.com/xserver_php/php-cgi" .phps

ModPagespeed On
#AddHandler fcgid-script .php .phps
#FCGIWrapper “/home/spegasus/s-pegasus.com/xserver_php/php-cgi” .php
#FCGIWrapper “/home/spegasus/s-pegasus.com/xserver_php/php-cgi” .phps

ここはXサーバーの記述でModPagespeed Onがないと白くなるのよね。

あと、SSL化細かいことめんどくさいなら以下のプラグインでも対応可能