さくらインターネットでラピッドSSL提供開始記念キャンペーンが激安で提供されていたので、我がナカヤン.jpに導入してみることにした。 目標は完全SSL化、常時HTTPSで接続するサイトにすることだ。
そもそも、この完全SSL化(常時HTTPS)って何なのか?
SSLを使っているサイトは、URLの横に鍵マークが表示されている。 これはそのサイトとの通信が暗号化されているということを意味している。 誰かが途中で何かを書き換えたりしていない、サーバから出たデータが改ざんされること無く手元のブラウザまで届いているということだ。
もちろん、サーバが乗っ取られていたり、パソコンにマルウェアが入っていたりしたら意味が無いんだけれども、少なくとも通信そのものの安全性を高めることになる。 そうしたこともあって、Googleでは検索順位の評価軸に完全SSL化を加えると公式に発表している。 検索順位を高めるには、完全SSL化が必須の世界がやってきたということだ。
我が家の環境はさくらのVPS+CentOS6.7+Nginx(リバースプロキシ)なんだけど、SSL導入って思った以上に難しくてかなり試行錯誤した。
まだ一部の環境ではエラーが出るみたいだけど、 URLの横に鍵マークが輝く完全SSL対応ができたのでメモを残す。
ってか3年で1,836円って激安SSLにも程がある。 凄いよ、田中社長!
ラピッドSSLというのはドメイン認証型SSLと呼ばれるタイプだ。 そもそもSSLって何だよ、とか、SSLにも種類があるんだって人は、ASCII.jpの特別企画え、1年間無料!? ならば僕らもさくらでSSLを導入だ!がわかりやすいので、これを熟読してみて。
何はともあれ、まずSSLを使うためにはOpenSSLが必要だ。 と言うことで、下記コマンドでOpenSSLがインストールされているか確認する。
$ openssl version
コマンドが動作しなかったらOpenSSLをインストールする。
$ sudo yum -y install openssl
次にCSRという自分が何者であるかを記載した認証リクエストを生成する必要があるんだけど、サーバ上でコマンドで生成する方法と、SSLの発行元が提供しているCSR作成ツールを使って作る方法がある。 さくらのレンタルサーバだとこのあたりの手間は省けるけど、VPSの場合は自分でやんなきゃいけない。
コマンドでも別に何の問題も無いけど、楽だったからツールを使って作ってみた。
このツールで必要事項を入力すると、下記のようなコマンドが生成される。
openssl req -new -newkey rsa:2048 -nodes -out YOURDOMAIN.NAME.csr -keyout YOURDOMAIN.NAME.key -sha1 -subj "/C=JP/ST=YOURPREF/L=YOURCITY/O=YOURNAME/CN=YOURDOMAIN.NAME"
このコマンドを、NginXの設定ファイルを置いているディレクトリで実行する。 別にSSL関連のファイルを保管する専用のディレクトリを作っても良いね。
実行すると下記の2ファイルが生成されている。 どちらもとても重要なファイルなので、しっかりコピーを取るなり、ダウンロードして別メディアに保管するなりしておく。
YOURDOMAIN.NAME.csr(CSRファイル)
YOURDOMAIN.NAME.key(秘密鍵ファイル)
この.csrというファイルがCSRファイルで、中身は下記の2行の間に何やら文字列が並んでいる普通のテキストファイルだ。
—–BEGIN CERTIFICATE REQUEST—–
~何やら文字列がゴニョゴニョ~
—–END CERTIFICATE REQUEST—–
SSLを申し込む時に、この2行を含む全ての情報を貼り付けることになる。
では、さっそく申込の手順を確認しよう。 オレはさくらのVPS利用者なので、会員IDでログインする。 そうでない人は会員登録からどうぞ。
次にSSLのプランを選択する。 もちろんRapidSSLだ。
支払い方法はクレジットカードが早くて便利だけど、会社とかだと請求書になるのかな。
利用規約に同意して、次に進む。
次の画面でCSRを入力する必要があるので、下記コマンドで中身を表示させて、コピペする。
# cat YOURDOMAIN.NAME.csr
この左側に貼り付けると、右側にCSR生成時に入力した名前などの項目が表示されるので、間違いが無いことを確認して次へ進み、プランや金額を確認して申し込めば完了だ。
完了すると下記のメールが届く。
SSLサーバ証明書 認証ファイルのアップロードについて
当該ドメインが自分の管理下にあることを証明するために、メールに書いてある手順に従ってWebのトップディレクトリに認証用のHTMLファイルを設置すると、数分で下記のメールが届く。
SSLサーバ証明書発行のお知らせ
メールに従ってサーバ証明書をダウンロードすると、server.crtというファイルが落ちてくる。
このサーバ証明書ファイルを、サーバに置いたYOURDOMAIN.NAME.key(秘密鍵ファイル)と同じディレクトリに保存する。 この2つのファイルは同じ鍵で暗号化されているので、組合せは決して間違えちゃいけない。
初回導入の時は間違えようも無いとは思うけど、更新時とかを考慮してファイル名に契約年度とか入れておくと便利らしいのでそうしておこう。
さ、これで秘密鍵、サーバ証明書の2つが揃ったが、実際にSSLで通信を行うためには他にも中間CA証明書が必要で、ここが多くの人が混乱する(オレはした)ところじゃなかろうか。
2階層とか、3階層とか、クロスルート証明書とか、もう対象となるファイルが一つじゃないし、分かり難さが半端ない。
届いたメールはコレ。
? ▽STEP2
ジオトラスト SSLサーバ証明書をご利用の際、お使いの機器へ中間CA証明書
のインストールが必要となります。
下記URLより該当サービスの中間CA証明書を選択し、認証局のウェブサイト
にて中間証明書をコピーし、テキストエディタに貼り付けていただき、中間
CA証明書ファイルとして任意のファイル名で保存してください。・オンラインマニュアル
お探しのページは見つかりませんでした | さくらのサポート情報お探しのページは見つかりませんでした。さくらインターネットのサポート情報を掲載しています。answers/detail/a_id/2500#02 ▽STEP3
以下のマニュアルをご参考の上、ダウンロードした「SSLサーバ証明書」と
「中間CA証明書」をサーバにインストールしてください。・ジオトラスト SSLサーバ証明書のインストール
https://www.geotrust.co.jp/support/ssl/install/
こんなマニュアルでちゃんと設定できる人がどれだけいるってのか、素人向けじゃないにしても小一時間説教をしたいくらい不親切極まりない。
そもそも、この中間CA証明書は何のために必要なのか。
簡単に言えば、自分の身元保証をするために先祖に遡って調べるための家系図、という目的で使われる。
ブラウザには元々組み込まれている大手の認証局情報があるんだけど、全てのSSL利用者が大手から直接サーバ証明書を発行してもらってる訳じゃ無くて、下請け、孫請けのような会社から買っている人も多いと。 そうすると、その大手認証局と自分のサーバ証明書との間をつなぐ情報が無いと、誰が身元保証してくれたんだかわからない身元不明な状態になってしまうので、中間CA証明書を用意してその橋渡しをしてあげる必要が出てくるということらしい。
とりあえず、先のCSR設定ツールでもお世話になった、親切なDigiCert(デジサート)さんのNginx での サーバー証明書のインストール方法を参考に設定をする。 このくらい分かりやすく書くように見習って欲しい。
つまるところ、オレはWebサーバをNginxで運用しているので、SSL接続をするには下記の2つのファイルをNginxの設定ファイルディレクトリあたりに用意する。 好みによってssl関連のファイルだけをまとめたディレクトリにしても良いだろうし、設定ファイルの中で適切に場所を指定してあげればどこでもOKだ。
- 秘密鍵ファイル: 最初のCSR生成時に作られたファイル(*.key)
- 証明書ファイル: サーバ証明書+中間CA証明書(3階層目)の順で結合したファイル(*.crt)
中間CA証明書(3階層目)のダウンロード。
他にもクロスルート設定用証明書(2階層目)もあるが、古い携帯電話とか、旧型の端末でも表示させたいということでなければ不要だし、SSLチェックサイトでも脆弱性が指摘されるので、特段の事情が無ければ入れない方が良いだろう。
Nginxでは証明書ファイルは一つだけしか指定できないので、自分のサーバ証明書に中間証明書を連結したNginx用の証明書ファイル(*.crt)を用意する。 vim等のエディタで作業しているなら、下記のような構成になるように、順番にコピペしていけば良い。
—–BEGIN CERTIFICATE—–
自分のサーバ証明書
—–END CERTIFICATE—–—–BEGIN CERTIFICATE—–
中間CA証明書(3階層目)
—–END CERTIFICATE—–
次に、この鍵のやりとりの秘匿性を高める手順であるDH(ディフィー・ヘルマン)鍵交換に使用するパラメータファイルを作る。 これもnginxの設定ファイルがあるところに保存したけど、別にどこに置いても構わない。
$ sudo openssl dhparam 2048 -out /etc/nginx/dhparam.pem
さぁ、ここまで用意できたらNginxに設定をしよう。 以前のマルチドメイン用の設定ファイルに、ココとかを参考にしながら赤字部分を追加しただけ。
server { listen 80; server_name nakayan.jp; return 301 https://$host$request_uri; } server {listen 80;listen 443 default_server ssl; server_name nakayan.jp; access_log? /var/log/nginx/access.nky.log; error_log?? /var/log/nginx/error.nky.log; root?? /var/www/nky; index? index.php index.html index.htm; charset utf-8; ssl_certificate ?? /etc/nginx/nky2015.crt; ssl_certificate_key? /etc/nginx/nky2015.key; ssl_session_cache shared:SSL:1m; ssl_session_timeout? 5m; ssl_dhparam /etc/nginx/dhparam.pem ssl_protocols? TLSv1 TLSv1.1 TLSv1.2; ssl_ciphers 'kEECDH+ECDSA+AES128 kEECDH+ECDSA+AES256 kEECDH+AES128 kEECDH+AES256 kEDH+AES128 kEDH+AES256 DES-CBC3-SHA +SHA !aNULL !eNULL !LOW !kECDH !DSS !MD5 !EXP !PSK !SRP !CAMELLIA !SEED'; ssl_prefer_server_ciphers?? on; add_header Strict-Transport-Security max-age=31536000; rewrite /wp-admin$ $scheme://$host$uri/ permanent; ~以下、設定ファイルは前のまま。
次にWordPressのディレクトリに移って、wp-config.php に下記コードを追加する。
define('FORCE_SSL_ADMIN', true); if ($_SERVER['HTTP_X_FORWARDED_PROTO'] == 'https') $_SERVER['HTTPS']='on';
ここまでやったら、次はWordPressの設定を変更する。 下図の赤枠内を、http://~からhttps://~に書き換えればOKだが、必ず上記のコードを先に追記しておくこと。 これも間違えるとログインできなくなって泣きそうになる。 ってかオレは泣きそうになったが、回避策がちゃんとあって良かった。
もし間違えて管理者画面にログインできなくなった場合には、wp-config.php に下記コードを追加することで、書き換えたURLではない別のURLに戻すことができる。 但し、これを指定してしまうと、上記画面の赤枠内は変更できなくなってしまう。 抜本的に修正するにはDBを直接いじるしかないので、PhpMyAdmin等を使ってwp-optionsテーブルの中身を書き換えよう。 書き換えたら、下記のコードは削除してOKだ。
define('WP_HOME','http://example.com'); define('WP_SITEURL','http://example.com');
さて、SSL化すると必ず直面するのが混在コンテンツ問題だ。
https://~の暗号化されているサイトの中に、http://~の画像やCSS、その他の暗号化されていないコンテンツが含まれている場合、危険なサイトであるとブラウザが警告を表示してしまうのだ。
また、昔の記事とか画像とかがhttp://になっているので、それも書き換えないといけない。 ちなみに、Googleは下記を推奨している。
書き換えはサーバにログインしてmysqlで実行するか、phpMyAdminで実行して書き換えることになるが、ここではphpMyAdminを使う方法をメモしておく。
phpMyAdminにログインしたらデータベースを選択する。
次にSQLタブを選択するとコマンドが入力できるようになるので、ここにSQL文を入力して実行することで、データベースを強制的に書き換えることができる。
ちなみに、データベースを直接書き換えてしまうということは、失敗すると過去の記事が全滅しかねないという怖い作業でもあるので、必ず事前にDBのバックアップを取った方が良い。 Duplicateプラグインとか便利だよ。
まず、「同じ安全なドメイン上にあるリソースには相対 URL を使用します」への対応。
UPDATE wp_posts SET post_content=REPLACE(post_content,"https://nakayan.jp/","/"); UPDATE wp_posts SET guid=REPLACE(guid,"https://nakayan.jp/","/"); UPDATE wp_postmeta SET meta_value=REPLACE(meta_value,"https://nakayan.jp/","/");
次に「他のすべてのドメインにはプロトコル相対 URL を使用します」の対応。 ただし、ぶっちゃけコレは悩ましい。 大手のサイトならともかく、そうでないサイトはhttp://のアドレスに対してhttps://でアクセスすると、エラーになったり無応答だったりするからだ。 過去記事を大事にしたいなら、これはやらない方が良いかも。
結局、オレはURLを書き換えることにした。 他サイトへのリンク切れなんて一杯あるし、全部の記事をチェックするのも不可能だしね。 アフェリエイト等だけ書き換えるって手も、人によってはアリかも。
UPDATE wp_posts SET post_content=REPLACE(post_content,"http://","//"); UPDATE wp_posts SET guid=REPLACE(guid,"http://","//"); UPDATE wp_postmeta SET meta_value=REPLACE(meta_value,"http://","//");
SSLチェックサイトで確認すると、ばっちりA+の評価!! 個人サイトとしては十分な結果だね。
チェックサイトのトップページを見たら、最近のベストサイトの第1位になってる! なんか嬉しい(笑
念のためHTTPSでのアクセスをGtmetrixで確認すると、前よりも良好な結果が。
ただし、Twitterのウィジェットを表示すると少し下がってAとBになってしまう。 もっと頑張れよTwitterさん。 でも、ちょっとプラグインを手直しさえすれば、もっとスコアが上がるだろうな。
また、abコマンドで非SSLとSSLのアクセスを比較してみると、びっくりするくらい違う。
まずは非SSLの、通常のhttpによるアクセス。
$ ab -n 10000 -c 100 https://nakayan.jp/
Requests per second:??? 9557.52 [#/sec] (mean)
次はSSLを使ったhttpsでのアクセス。
$ ab -n 10000 -c 100 https://nakayan.jp/
Requests per second:??? 261.62 [#/sec] (mean)
SSL化するってこんなにも負荷の高い処理なんだね。 巨大サイトだと運用も大変だろうなぁ。 SSLアクセラレータが別ハードウェアとして売られているのがよくわかるわー。
とりあえず満足。