Let’sEncryptでWordPressのHTTPS対応

HTTPS対応とは

大きな違いとしてURLが変わります。「http://」ではなく「https://」になります。 ブラウザのURLバーが緑になったりセキュアなサイトだと一目で分かるようになります。 また、検索エンジンにも影響を与えるとgoogleの公式アナウンスが出ています。

https://webmaster-ja.googleblog.com/2014/08/https-as-ranking-signal.html

少し前までは証明書は年額で購入する必要があり導入しているサイト管理者も少なかったのですが、今では無償でも証明書を取得できるようになり導入しているサイトも増えてきています。 無償だからセキュリティが弱いということはありません。今回は無償の証明書で最も導入されているであろうLet’s Encryptで導入していきます。

Let’sEncryptのインストール

yum -y install epel-release
yum -y install certbot

#「example.jp」 (サブドメイン無し) のみに対応する証明書を取得する場合
certbot certonly --webroot -w /var/www/wordpress -d example.jp

#「example.jp」 と 「www.example.jp」 に対応する証明書を取得する場合
certbot certonly --webroot -w /var/www/wordpress -d example.jp -d www.example.jp

あとは表示される利用規約に問題がなければ、同意(Agree)をしてインストール完了です。

証明書と秘密鍵が保存される場所と設定する値

ls -l /etc/letsencrypt/live/example.jp/*
lrwxrwxrwx 1 root root  32 Oct 25 17:14 /etc/letsencrypt/live/example.jp/cert.pem -> ../../archive/example.jp/cert2.pem
lrwxrwxrwx 1 root root  33 Oct 25 17:14 /etc/letsencrypt/live/example.jp/chain.pem -> ../../archive/example.jp/chain2.pem
lrwxrwxrwx 1 root root  37 Oct 25 17:14 /etc/letsencrypt/live/example.jp/fullchain.pem -> ../../archive/example.jp/fullchain2.pem
lrwxrwxrwx 1 root root  35 Oct 25 17:14 /etc/letsencrypt/live/example.jp/privkey.pem -> ../../archive/example.jp/privkey2.pem
-rw-r--r-- 1 root root 543 Oct 25 17:06 /etc/letsencrypt/live/example.jp/README

上記の出力から分かるようにシンボリックリンクが貼られており、実態のファイルは以下の場所にあります。

ls -l /etc/letsencrypt/archive/example.jp/*
-rw-r--r-- 1 root root 1777 Oct 25 17:06 /etc/letsencrypt/archive/example.jp/cert1.pem
-rw-r--r-- 1 root root 1777 Oct 25 17:14 /etc/letsencrypt/archive/example.jp/cert2.pem
-rw-r--r-- 1 root root 1647 Oct 25 17:06 /etc/letsencrypt/archive/example.jp/chain1.pem
-rw-r--r-- 1 root root 1647 Oct 25 17:14 /etc/letsencrypt/archive/example.jp/chain2.pem
-rw-r--r-- 1 root root 3424 Oct 25 17:06 /etc/letsencrypt/archive/example.jp/fullchain1.pem
-rw-r--r-- 1 root root 3424 Oct 25 17:14 /etc/letsencrypt/archive/example.jp/fullchain2.pem
-rw-r--r-- 1 root root 1704 Oct 25 17:06 /etc/letsencrypt/archive/example.jp/privkey1.pem
-rw-r--r-- 1 root root 1704 Oct 25 17:14 /etc/letsencrypt/archive/example.jp/privkey2.pem

実際にNginxに設定する値は「/etc/letsencrypt/live/example.jp/」のディレクトリに入っている証明書を設定します。

Diffie-Hellman鍵交換用パラメータファイルの準備

Diffie-Hellman鍵交換とはSSLで接続する際に鍵交換を行うのですが、その通信傍受に対する耐性を上げることができます。

mkdir /etc/nginx/ssl
openssl dhparam 2048 -out /etc/nginx/ssl/dhparam.pem

Nginxの設定

Nginxのコンフィグは前の記事のコンフィグを編集しています。

WordPress構築(CentOS7 Nginx MariaDB PHP7)

2段階に分けて設定をしていきます。 既存の80ポートの設定の下に追記します。ここではsslは適用していません。 ssl on;はコメントアウトしています。

sslディレクティブについて

ssl on;の設定は2018年12月時点の最新バージョンでは非推奨設定に変更されています。

vi /etc/nginx/conf.d/wordpress.conf

server {
    listen 80;
    server_name example.com; # 取得したドメインを指定してください
    root /var/www/wordpress; # WordPressのディレクトリを指定します。
    index index.php;

location / {
    if (!-e $request_filename) {
    rewrite ^.+?($/-.*) $1 last;
    rewrite ^.+?(/.*\.php)$ $1 last;
    rewrite ^ /index.php last;
    break;
  }
}
	
# wp-config.phpへのアクセスをすべて拒否します。
location ~* /wp-config.php {
    deny all;
    }

location ~ \.php$ {
    fastcgi_pass 127.0.0.1:9000;
    fastcgi_param SCRIPT_FILENAME /var/www/wordpress$fastcgi_script_name;
    fastcgi_param PATH_INFO $fastcgi_script_name;
    include fastcgi_params;
    }
}

#-----ここから追記-----------
server {
    listen 443;
    server_name example.com; # 取得したドメインを指定してください
    root /var/www/wordpress; # WordPressのディレクトリを指定します。
    index index.php;

    #ssl on;
    ssl_certificate      /etc/letsencrypt/live/example.com/fullchain.pem;
    ssl_certificate_key  /etc/letsencrypt/live/example.com/privkey.pem;
    # TLS1.0 1.1 1.2のみ有効
    ssl_protocols        TLSv1 TLSv1.1 TLSv1.2;
    # サーバが提示した暗号スイートを優先
    ssl_prefer_server_ciphers on;

    # 安全でない暗号化スイートはサポートしない
    ssl_ciphers 'kEECDH+ECDSA+AES128 kEECDH+ECDSA+AES256 kEECDH+AES128 kEECDH+AES256 kEDH+AES128 kEDH+AES256 +SHA !aNULL !eNULL !LOW !kECDH !DSS !MD5 !EXP !PSK !SRP !CAMELLIA !SEED';
    # SSLセッションキャッシュとサイズを指定
    ssl_session_cache    builtin:1000 shared:SSL:10m;
    # SSLセッションキャッシュのタイムアウトまでの時間
    ssl_session_timeout  10m;
    # OCSP応答をサーバー側にキャッシュ
    ssl_stapling on;
    #DH鍵交換パラメータファイル
    ssl_dhparam /etc/nginx/ssl/dhparam.pem;

    location / {
        if (!-e $request_filename) {
        rewrite ^.+?($/-.*) $1 last;
        rewrite ^.+?(/.*\.php)$ $1 last;
        rewrite ^ /index.php last;
        break;
        }
    }

# wp-config.phpへのアクセスをすべて拒否します。
    location ~* /wp-config.php {
        deny all;
    }

    location ~ \.php$ {
        fastcgi_pass 127.0.0.1:9000;
        fastcgi_param SCRIPT_FILENAME /var/www/wordpress$fastcgi_script_name;
        fastcgi_param PATH_INFO $fastcgi_script_name;
        include fastcgi_params;
    }
}

#-----ここまで追記-----------

コンフィグチェックをしてリロードします。

nginx -t
nginx -s reload

WordPressとFirewallの設定変更

WordPressのサイトURLをhttpsへ変更します。 WordPress > ダッシュボード > 設定 > 一般 >「WordPress アドレス (URL)」「サイトアドレス (URL)」 「http://example.com」 を 「https://example.com」 へ変更します。

FireWallの設定で443ポートを許可します。

firewall-cmd --permanent --add-service=https --zone=public
firewall-cmd --list-all

ブラウザからhttpsでアクセスして表示できることを確認します。

Nginxの最終設定

変更点

  1. 80番ポートの設定をhttpsへリダイレクトする設定に変更
  2. 443番ポートの設定にhttp2の設定
  3. 443番ポートのsslをオン
  4. HSTSの設定
server {
# ---変更点1------------
    listen 80;
    server_name loner.jp;
    return 301 https://$host$request_uri;
# ---変更点1------------
}

server {
# ---変更点2------------
    listen 443 ssl http2;
# ---変更点2------------
    server_name example.com; # 取得したドメインを指定してください
    root /var/www/wordpress; # WordPressのディレクトリを指定します。
    index index.php;

# ---変更点3------------
    ssl on; 
# ---変更点3------------

    ssl_certificate      /etc/letsencrypt/live/example.com/fullchain.pem;
    ssl_certificate_key  /etc/letsencrypt/live/example.com/privkey.pem;
    # TLS1.0 1.1 1.2のみ有効
    ssl_protocols        TLSv1 TLSv1.1 TLSv1.2;
    # サーバが提示した暗号スイートを優先
    ssl_prefer_server_ciphers on;

    # 安全でない暗号化スイートはサポートしない
    ssl_ciphers 'kEECDH+ECDSA+AES128 kEECDH+ECDSA+AES256 kEECDH+AES128 kEECDH+AES256 kEDH+AES128 kEDH+AES256 +SHA !aNULL !eNULL !LOW !kECDH !DSS !MD5 !EXP !PSK !SRP !CAMELLIA !SEED';
    # SSLセッションキャッシュとサイズを指定
    ssl_session_cache    builtin:1000 shared:SSL:10m;
    # SSLセッションキャッシュのタイムアウトまでの時間
    ssl_session_timeout  10m;
    # OCSP応答をサーバー側にキャッシュ
    ssl_stapling on;
    #DH鍵交換パラメータファイル
    ssl_dhparam /etc/nginx/ssl/dhparam.pem;

# ---変更点4------------
    #HTTP Strict Transport Security
    add_header Strict-Transport-Security 'max-age=31536000; includeSubDomains; preload';
# ---変更点4------------

    location / {
        if (!-e $request_filename) {
        rewrite ^.+?($/-.*) $1 last;
        rewrite ^.+?(/.*\.php)$ $1 last;
        rewrite ^ /index.php last;
        break;
        }
    }

# wp-config.phpへのアクセスをすべて拒否します。
    location ~* /wp-config.php {
        deny all;
    }

    location ~ \.php$ {
        fastcgi_pass 127.0.0.1:9000;
        fastcgi_param SCRIPT_FILENAME /var/www/wordpress$fastcgi_script_name;
        fastcgi_param PATH_INFO $fastcgi_script_name;
        include fastcgi_params;
    }
}

SSL化後にやること

証明書の自動更新

LetsEncryptの証明書は3ヶ月です。しかし、コマンドで証明書を更新することができるため自動化することができます。 crontabで1ヶ月ごとに以下のコマンドを実行する設定にします。

vi /etc/crontab
0 5 1 0 0 /usr/bin/systemctl stop nginx.service && /usr/bin/certbot renew --force-renew && /usr/bin/systemctl start nginx.service

cronのコマンドについて

コマンドが実行できるか必ず確認しておきましょう。 HSTSを設定しているため証明書の期限が切れた場合ブラウザからアクセスできなくなります。 上記コマンドは&&でつないでいるのでエラーが出るとコマンドがそこで止まります。

WordPressのURL置換

WordPressの場合、URLを変換しないといけないので、プラグインのSearch Regexで置換します。

セキュリティ強度の確認

また以下のサイトからサイトのセキュリティ強度を確認できます。

https://www.ssllabs.com/ssltest

無事A+判定にすることができました。