HTTPS化の検討

このサイト(Drupal)のHTTPS化についての記事です。

昨年の「」がきっかけです。


ベストプラクティスが公開されていますので、できるだけそれに沿うようすることを目標にしています。

それでは、Drupalのサイトでは何をすればよいのか?

これについては、Enabling HTTP Secure (HTTPS)が参考になると思います。


これまで当サイトでは、訪問者が意識して「https://」で始まるURLを指定しない限りは「https」で接続することはありませんでした。

そのため、自作認証局を開設し、その認証局でサーバ証明書を発行すれば、とりあえず、サイト管理者自身が、サイトのログインページや管理用ページなど特定のペー ジのみ「https://」で始まるURLでアクセスすることで、リモート端末とWEBサーバ間の通信を暗号化することが可能でした。
さらに、リモート端末のIPアドレスのみアクセス許可するように設定しておけば不正アクセス対策が可能でした。

しかし、Googleの検索結果からサイトにアクセスする場合、訪問者の意志に関係なく「https://」で始まるURLが使われサイトのページへアクセスされる可能性が発生するようになりました。

この影響で、訪問者がサイトへアクセスすると、まず最初に「危険なサイト」と表示されてしまいます。

(例1)IE11(Windows8.1)


(例2)Firefox34



検索サイトの検索結果一覧のリンクからアクセスする訪問者がこの表示を見た時に、そのままアクセスを許可するでしょうか?

仮に、サイトで「https://」を「http://」にリダイレクトしていたとしても、「危険なサイト」の表示を回避することはできません。
ただし、アクセスを許可したあとに表示されるページは「http://」のURLになるため、それ以降のページアクセスでは特に問題はありません。

「危険なサイト」の表示を抑止

まず、サイトへのアクセス増加を考えるなら、訪問者を不安にさせる「危険なサイト」の表示をさせない方法を考えなければなりません。
それには、自作認証局で発行したサーバ証明書ではなく、信頼された認証局で発行したサーバ証明書を利用する以外にはないと思います。
さらに付け加えると、訪問者が使用しているWEBブラウザに事前に登録されている信頼された認証局の証明書(ルート証明書)のサーバ証明書でなければ意味がありません。
そうでなければ、自作認証局が発行したサーバ証明書と同じ扱いになってしまいます。

SSL/TLSを無料・簡単に、Web全体の暗号化を目指す「Let's Encrypt」発表」という記事にもあるように、無償でサーバ証明書(電子証明書)を利用できるようになるみたいですし、すでに無償のStarSSLというサービスもあるようですので、以前ほど敷居は高くないようです。
※StarSSLについてはこちらとかこちらが参考になると思います。
 

「安全でないコンテンツのブロック」とは

信頼された認証局からサーバ証明書を発行してもらい、それをWEBサーバで使用して「危険なサイト」の表示がでなくなったあと、次に当サイトで発生するのが「安全でないコンテンツのブロック」です。
これは、表示しようとしたページに「http://」から始まるURLが使われているため発生します。

(例)IE11(Windows8.1)


(例)FireFox


今すぐ保護を無効にするにした場合


(例)Chrome


Load unsafe scriptにした場合


たとえば、Drupalを標準インストールした場合、サイトのURLは「http://」から始まるように設定されます。
そのため、コアおよび寄贈モジュールがダイナミックに生成するURIはすべて「http://」から始まります。

その影響で、まず、head部のmetaタグやLinkタグ、CSSやjavascriptのパス表記がすべて「http://」から始まるURIで生成されるため、テーマのCSSやjavascriptなどによる効果が一切表示できず、ページはソースコードをplaintaxtで記述されたかのようにレイアウトが崩れた状態の表示になってしまいます。
そして、body部の中でもdrupalによってダイナミックに生成されるページはすべて「http://」から始まるURIになってしまいます。
もちろん、記事本文やブロック部を自作しHTMLソースコードを記述する際や動画などの埋め込みコードを記述する際に自サイトや他サイトのURLに「http://」から始まるURLを記述していると、その箇所のパーツはHTTPSによる保護範囲外になるため「安全でないコンテンツ」として扱われ、通常はブロックされてしまいます。

「安全でないコンテンツのブロック」を回避

この「安全でないコンテンツのブロック」に対応する手段としては、ベストプラクティスの「検索エンジンに安全なサイトとみなされるようにする」に記載されている事項が参考になります。

サーバー側の 301 HTTP リダイレクトを使って HTTPS ページまたはリソースにユーザーと検索エンジンをリダイレクトします。
同じ安全なドメイン上にあるリソースには相対 URL を使用します
たとえば、サイト example.com 上のページを参照するには、<a href="https://example.com/about/ourCompany.php"> ではなく、<a href="/about/ourCompany.php"> を使用します。このように指定すると、リンクやリソースに常に HTTPS が使用されます。さらに、ローカルでの開発では、画像、ページ、またはその他のリソースが、本番環境ではなくローカル開発環境から読み込まれるので、誤り が起こりにくくなるという副次的な利点もあります。
他のすべてのドメインにプロトコル相対 URL を使用(例: //petstore.example.com/dogs/biscuits.php)するか、HTTPS リソースに直接リンクするようにサイトリンクを更新サイトリンクを更新します。
HTTP Strict Transport Security(HSTS)をサポートするウェブサーバーを使用し、HSTS を必ず有効にします。
これは、自動的に HTTPS を使用してページをリクエストするようにブラウザに指示する仕組みで、ユーザーがブラウザのアドレスバーに http を入力した場合でも HTTPS が使用されます。検索結果に安全な URL を提供するように Google も指示されます。これらはすべて、保護されていないコンテンツをユーザーに提供するリスクを最小限に抑えるものです。

以上から、サイトページ内では、相対URL表記やプロトコル相対URLを使用すればよいということです。

それでは、Drupalのサイトでは具体的にどうすればよいのか?についてですが、それについては、先に紹介したEnabling HTTP Secure (HTTPS)を参考に以下の項目を試してみました。
 

「sites/default/settings.php」で対応

Drupalの基本的な事項を設定するファイルがこの「sites/default/settings.php」になります。
標準インストールの場合は、データーベースへのアクセスに必要な情報とSQLインジェクション対策強化用のハッシュが保存されている状態だと思います。
それ以外はほとんどがコメントになっています。
 

$base_urlによる制御

「sites/default/settings.php」にある「$base_url」に注目してください。
この変数で設定したURLがDrupalのコアまたは寄贈モジュールに反映されます。

$basu_url="https://Drupalドメイン名"」とした場合は、head部やbody部などダイナミックに生成するURLの先頭が「https://Drupalドメイン名」に変換されて出力されました。


次にリクエストに応じて切り替える方法です。(HTTPSのみの場合は不要です)
PHPの変数$_SERVERの値によって「http://」か「https://」かを切り替える方法が考えられます。
 

SERVER_PORTの値で切り替え(443:SSL)

 

$base_url = $_SERVER['SERVER_PORT'] == 443 ? 'https://' : 'http://';
$base_url .= 'www.example.com';

 

HTTP_X_FORWARDED_PROTとHTTPSの値で切り替え

リバースプロキシーを経由している場合は、リバースプロキシーとWEBサーバは443番ポートでは接続できませんので、上記の方法では切り替えができません。
この場合、SERVER_PORT以外のパラメータの値で判別する方法です。

ここでは、HTTP_X_FORWARDED_PROTOとHTTPSを使っています。

if (isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] == 'https']){
  $_SERVER['HTTPS'] = 'on';
}
$base_url = isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on' ? 'https://' : 'http://';
$base_url .= 'www.example.com';

以下のようにシンプルにしても動くかもしれません。

HTTP_X_FORWARDED_PROTOの値で切り替え

$base_url = isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] == 'https' ? 'https://' : 'http://';
$base_url .= 'www.example.com';


必ず上記のパラメータが設定されるわけではありませんので、念のためリバースプロキシー(nginx)にproxy_set_headerを追記してあります。

server {
  listen  443 ssl;
 省略
 proxy_set_header X-Forwarded-Proto $scheme;
}

以上でDrupalコアおよび寄贈モジュールからダイナミックに生成されるURLは「https://」もしくは「http://」に制御可能であることが確認できました。

しかし、$base_urlを設定しても、まだ、「安全でないコンテンツのブロック」の状態になります。

Drupal寄贈モジュールの中には、$base_urlの影響を受けないモジュールもあります。
私が使用しているモジュールでは、Video Filterモジュールです。


その他には、サイドバーにある外部ブログパーツです。

ブログパーツを利用する方法は一般的に提供サイトでiframeやjavascripte用の埋め込みコードを生成して、表示したい箇所にそのコードを貼り付けます。
そのため、その生成したコード内に「http://」から始まるURLがあると、「安全でないコンテンツのブロック」によってブロックされます。
これは、URLリンクボタンでも同じです。

それでは、「http://」を単純に「https://」に変更してもOKなのか?
まずは、そのブログパーツの利用規約に違反していないことが前提条件になります。
また、強制的に変更してもhttps://でアクセスできなければ(サービスが提供されていなければ)、そのブログパーツを正常に表示することはできません。

よって、「安全でないコンテンツのブロック」を完全に回避するには、サイト内でhttp://から始まるURLを使用しないようにしなければならないため、場合によってはブログパーツの使用をやめるなど厳しい制限が発生してしまいます。

完全なHTTPS化は非常に難しいと感じましたが、部分的なHTTPS化は十分可能であると思います。
たとえば、管理画面のみに限定する場合です。

そういった一部のページのみに制限したい場合は、「Secure Pages」モジュールや「Secure Login」モジュールを使用すると便利そうです。
これらモジュールを使用するときには「sites/default/settings.php」に「$config['HTTPS']=TRUE;」を追記する必要があるそうです。

また、HTTPSのみを使用する場合は、「HTTP Strict Transport Security」モジュールを使用するのも検討してみてください。
ただし、このモジュールを使用する場合は、「$config['HTTPS']=TRUE;」になっていたり、他のモジュールと干渉するためか、無限にREWRITEルールが適用されページが表示できなくなったりしますので注意してください。
最悪は、管理ページにアクセスできなくなってどうしようもなくなります。
実際にそういう状況になってしまい、drushコマンドで対応しました。

 

Drupalバージョン

Drupal 7.x

カテゴリ

セキュリティー

モジュール

securepages Secure Login HSTS