Windows
Apache
xampp
SSL
openssl

XAMPP for WindowsでSSLを有効にする

目標

  1. XAMPPで「https://localhost」を表示可能にします。
  2. 自作の証明書を認証して、警告を表示させないようにします。
    未認証: not-secure.png
    認証済: secure.png

環境

  • Windows 10
  • XAMPP 7.2.2

XAMPPの設定

PHPでOpenSSLを有効にする

通常は有効になっているはずです。
C:\xampp\php\php.iniの下記の行がコメントアウトされていないことを確認してください。

php.ini
- ;extension=php_openssl.dll
+ extension=php_openssl.dll

ApacheのSSL関連の設定を追加する

C:\xampp\apache\conf\extra\httpd-ssl.confの末尾に下記を追加します。

httpd-ssl.conf
<VirtualHost *:443>
    DocumentRoot "C:/xampp/htdocs"
    ServerName localhost
    SSLEngine on
    SSLCertificateFile "conf/ssl.crt/my-server.crt"
    SSLCertificateKeyFile "conf/ssl.key/my-server.key"
</VirtualHost>

my-server.crtmy-server.keyは後で作成します。
DocumentRoot,ServerNameは適宜読み替えてください。
なお、ServerNameをlocalhost以外、例えばwww.example.comなどにしたい場合は、別途バーチャルホストの設定とhostsファイルの修正が必要です。
:link: windows7のXAMPPでバーチャルホストの設定をする – YATのBLOG

動作確認

Apacheを再起動して、https://localhostへアクセスしてください。
下記のような警告が出るものの、強引に表示させることはできます。
次章では、この警告を表示させないようにします。

alert.png

証明書

(修正: 2017-05-02)
Chrome58以降は、以前の方法では認証できません。
非推奨とされてきた「Common Name (CN)」への対応がついに廃止されたので、「Subject Alternative Name (SAN)」という拡張領域が必要です。

:link: Chromeがコモンネームの設定を非推奨化、そのエラー対策としての自己署名証明書のCSRの作り方
:link: Support for commonName matching in Certificates - Chrome Platform Status

以降の手順は下記の記事に従っています。
:link: Fixing Chrome 58 – NET::ERR_CERT_AUTHORITY_INVALID error – Dev Notes

古い証明書を削除する

認証されなくなった古い証明書がある場合は削除します。

  1. Chromeの設定を開き、「証明書の管理」を検索してクリックします。
  2. 信頼されたルート証明機関からlocalhostを削除します。
    003.png

OpenSSL設定ファイルを編集する

  1. C:\xampp\apache\conf\openssl.cnfをコピーして、ファイル名をopenssl-san.cnfに変更します。
  2. 以下を末尾に追記します。
openssl-san.cnf
[ SAN ]
subjectAltName = @alt_names

[ alt_names ]
DNS.1 = localhost
DNS.2 = <他に認証したいドメインがあれば>
DNS.3 = <他に認証したいドメインがあれば>

SSLサーバ証明書を作成する

Windowsのコマンドプロンプトでopensslコマンドを実行するには、下記のように追加でインストール作業が必要です。
:link: Tech TIPS:WindowsにOpenSSLをインストールして証明書を取り扱う(基本編) - @IT

Git Bashならばそのままopensslコマンドを使えるので、お使いのPCにすでにGitをインストールしているのならGitBashを使うことをお勧めします。

GitBash
# C:\xampp\apache\conf へ移動
$ cd /c/xampp/apache/conf

# my-server.crt, my-server.key の2つのファイルを生成
$ openssl req \
    -newkey     rsa:4096 \
    -keyout     my-server.key \
    -x509 \
    -nodes \
    -out        my-server.crt \
    -subj       "//CN=localhost" \
    -reqexts    SAN \
    -extensions SAN \
    -config     openssl-san.cnf \
    -days       3650

-subjオプションでの書き方はGitBashのみで有効です。
GitBash以外の端末を使っている場合は-subj "/CN=localhost" \と、スラッシュをひとつ減らしてください。
:link: string - Running Openssl from a bash script on windows - Subject does not start with '/' - Stack Overflow

opensslコマンドのオプションについては下記をご覧ください。
:link: (日本語)OpenSSL Manual Translation - req(1)
:link: (英語)/docs/manmaster/man1/req.html

証明書を設置する

上のコマンドを実行して生成したmy-server.crtmy-server.keyを、それぞれ下記の場所に移動します。

ファイル 設置場所
my-server.crt C:\xampp\apache\conf\ssl.crt
my-server.key C:\xampp\apache\conf\ssl.key

証明書を認証する

my-server.crtをダブルクリックします。

001.png

002.png

「証明書ストア」は、必ず「信頼されたルート証明機関」を選んでください。

003.png

004.png

「はい」を選んでインストールします。

005.png

動作確認

Apacheブラウザを再起動して、https://localhostへアクセスしてください。
一般的なHTTPSのサイトと同じように問題なく表示されるはずです。
ChromeだけでなくIEやEdgeでも同様です。ただしFirefoxだけは違います。

未認証: not-secure.png
認証済: secure.png

Firefoxでは

Firefoxではどんな自己署名証明書も認証されないようです。
よって、「例外」という形にするほかありません。
:link: 安全なウェブサイトでのエラーコード "SEC_ERROR_UNKNOWN_ISSUER" の問題解決 | Firefox ヘルプ

例外に追加する

001.png

004.png

例外から削除する

逆に、もう例外扱いする必要がなくなった場合は、下記のように解除します。

005.png

006.png

HTTPSを強制する

(コメント欄で @oliverusselldev さんから助言をいただきました。)
http://へアクセスされてもhttps://へ自動でリダイレクトするように設定できます。
.htaccessに下記を追加してください。

.htaccess
# Redirect HTTP to HTTPS
RewriteEngine On
RewriteCond %{HTTPS} off
RewriteCond %{HTTP:X-Forwarded-Proto} !https
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]

:link: https://www.cloudways.com/blog/add-ssl-certificates-to-custom-php-sites/

参考記事

XAMPPの設定

証明書