奇特なブログ

「殊勝に値する行いや心掛け」を意味する、奇特な人になる為のブログです

Let's Encryptを導入したりHTTP2に対応したりIPv6に対応したりなど

acme-challengeやIPv6とか、ちょっと怪しい箇所がありますけどね。

以下、設定した内容の羅列です。

OS:CentOS6.3


1.IPv6の有効化

## 以下のさくらVPSの設定方法の通り

https://help.sakura.ad.jp/hc/ja/articles/115000070782

## 上記が成功したら、各レジストラなどのDNS設定で、AAAAレコードに上記のIPv6アドレスを登録する


2.OpenSSLの導入

既に、1.1.0bを導入済みの為、省略


3.Nginxの最新化

$ sudo yum install gcc-c++

$ cd ~/src

$ curl -O ftp://ftp.csx.cam.ac.uk/pub/software/programming/pcre/pcre-8.42.tar.gz

$ tar zxvf pcre-8.42.tar.gz

$ cd pcre-8.42

$ ./configure

$ make

$ sudo make install

$ cd ~/src

$ curl -O http://nginx.org/download/nginx-1.15.3.tar.gz

$ tar zvxf nginx-1.15.3.tar.gz

$ cd nginx-1.15.3

## OpenSSLのパスは、インストールしたバイナリの方ではなく、ダウンロードしたソースの方を指定する
## また、「openssl version」で表示されるバージョンと同じになっているかも確認
$ echo './configure --prefix=/opt/nginx1.15.3 --sbin-path=/opt/nginx1.15.3/sbin/nginx --pid-path=/opt/nginx1.15.3/logs/nginx.pid --lock-path=/opt/nginx1.15.3/logs/nginx.lock --error-log-path=/opt/nginx1.15.3/logs/error.log --http-log-path=/opt/nginx1.15.3/logs/access.log --with-openssl={OpenSSLのダウンロード先}/openssl-1.1.0b --user=nginx --group=nginx --with-http_v2_module --with-http_ssl_module --with-http_realip_module' > nginx_ccc

$ sh ./nginx_ccc

$ make

$ sudo make install

$ echo '/usr/local/lib' | sudo tee -a /etc/ld.so.conf.d/pcre.conf

$ sudo ldconfig

$ sudo rm -rf /opt/nginx

$ sudo ln -s /opt/nginx1.15.3 /opt/nginx

$ sudo vim /etc/profile

## 変更前
export PATH=$PATH:/opt/php/bin:/opt/git/bin:/opt/openssl/bin:/opt/vim/bin

## 変更後
export PATH=$PATH:/opt/php/bin:/opt/git/bin:/opt/openssl/bin:/opt/vim/bin:/opt/nginx/sbin

$ . /etc/profile

$ sudo vim /opt/nginx/conf/nginx.conf

## 変更前:

#user  nobody;
worker_processes  1;

#error_log  logs/error.log;

#pid        logs/nginx.pid;

#access_log  logs/access.log  main;

server_name  localhost;

location / {
    root   html;
    index  index.html index.htm;
}

## 変更後:

user  nginx;
worker_processes  2;

error_log  logs/error.log;

pid        logs/nginx.pid;

access_log  logs/access.log;

server_name  {ホスト名};

location / {
    root   {ドキュメントルートのディレクトリ};
    index  index.html index.htm;
}

## 以下をhttpディレクティブ内に追加
server_tokens off;

$ sudo mkdir -p {ドキュメントルートのディレクトリ}/.well-known/acme-challenge

$ sudo chmod -R 777 {ドキュメントルートのディレクトリ}/.well-known

$ sudo service nginx restart


3.証明書取得ツールを導入

$ sudo su -

# curl https://dl.eff.org/certbot-auto -o /usr/local/bin/certbot-auto

# chmod 700 /usr/local/bin/certbot-auto


4.root権限のあるユーザーで証明書取得ツールを実行して証明書を取得

## テスト実行
# certbot-auto certonly --webroot -w {ドキュメントルート} -d {ドメインFQDN)} --email {連絡先メールアドレス} --agree-tos -n --test-cert

## 本番実行
# certbot-auto certonly --webroot -w {ドキュメントルート} -d {ドメインFQDN)} --email {連絡先メールアドレス} --agree-tos -n --force-renewal


5.PFSのためのDHパラメータの生成

# mkdir -p /opt/nginx/ssl

# openssl dhparam 2048 > /opt/nginx/ssl/dh2048.pem


6.取得した証明書をWebサーバーに適切に設定する

# vim /etc/sysconfig/iptables

## 以下を追加

:HTTPS - [0:0]

-A HTTPS -m hashlimit --hashlimit 1/m --hashlimit-burst 10 --hashlimit-name httpscon --hashlimit-mode srcip --hashlimit-htable-expire 120000 -j RETURN
-A HTTPS -j LOG --log-level info --log-prefix "[ HTTPS attack ]: "
-A HTTPS -j DROP

-A SERVICE -p tcp --dport 443 -j HTTPS

-A SERVICE -p tcp --dport 443 -j ACCEPT

# vim /etc/sysconfig/ip6tables

## 基本iptablesと同じだが、ICMP関連(以下の他にもある)に注意

-A INPUT -p icmpv6 -j ACCEPT

# vim /opt/nginx/conf/nginx.conf

## 以下を追加

server {
  server_name {ドメイン名};
  # IPv4とIPv6の両方でHTTPリクエストを受け付ける。
  listen *:80;
  listen [::]:80;
  # HTTPからのアクセスをHTTPSへリダイレクトする。
  return 301 https://$host$request_uri;
}

server {
  listen 443 ssl http2 default_server;
  listen [::]:443 ssl http2 default_server;

  server_name {ドメイン名};

  ssl_certificate     /etc/letsencrypt/live/{ドメイン名}/fullchain.pem;
  ssl_certificate_key /etc/letsencrypt/live/{ドメイン名}/privkey.pem;

  ssl_dhparam /opt/nginx/ssl/dh2048.pem;

  ssl_protocols TLSv1 TLSv1.1 TLSv1.2;

  ssl_prefer_server_ciphers  on;
  ssl_ciphers  'EECDH+AESGCM+AES128 EECDH+AESGCM EECDH+AES128 EECDH+AES256 !aNULL !eNULL !SSLv2 !SSLv3';

  # OCSPステープリングを有効にする。
  ssl_stapling on;
  ssl_stapling_verify on;
  ssl_trusted_certificate /etc/letsencrypt/live/{ドメイン名}/chain.pem;

  ssl_session_cache   shared:ssl:10m;
  ssl_session_timeout 10m;

  # 31536000は365日
  add_header  Strict-Transport-Security "max-age=31536000; includeSubdomains";

  location ^~ '/.well-known/acme-challenge' {
    default_type "text/plain";
    root   {ドキュメントルートのディレクトリ};
  }

  ・・・その他
}


7.Nginxなどの再起動

## 以下のコマンドを実行する前に、上記を設定したターミナルを閉じずに、

## 別に1~3つターミナルを起動してから動作確認すること
# service iptables restart

# service ip6tables restart

## nginx.confのシンタックスを確認
# nginx -t

## 問題無ければ再起動
# service nginx restart


8.動作確認

## HTTPSのリクエストをテスト
# curl -I https://{ドメイン名}/

## HTTPのリクエストをテスト(HTTPSにリダイレクトされる)
# curl -I http://{ドメイン名}/

## HTTP/2のリクエストをテスト(curlのバージョンがHTTP2に未対応の為、失敗したので、最新のブラウザからアクセスし、アクセスログで確認)
# curl --http2 -I https://{ドメイン名}/

## OCSPステープリングのテスト
# openssl s_client -connect {ドメイン名}:443 -CAfile /etc/pki/tls/certs/ca-bundle.crt -status

  • CAfileを付けないと、以下のエラーが表示され、ちょっとハマった
verify error:num=20:unable to get local issuer certificate
Verification error: unable to get local issuer certificate
Verify return code: 20 (unable to get local issuer certificate)

## IPv6のテスト(以下コマンドで、「Trying {IPv6アドレス}... connected」となるのは確認)
# curl --verbose -I https://{ドメイン名}/


9.証明書更新用のスクリプトなどをcronなどに仕掛ける

# vim /etc/crontab

# 奇数日の3時に実行
00 03 1-31/2 * * root /usr/local/bin/certbot-auto renew -q --no-self-upgrade --deploy-hook "/sbin/service nginx restart"


以上です。

IPv6で、以下が上手くいかないんですけど、まだDNSが浸透(って言っちゃいかんのでしょうけどw)してないからですかね。
何日か待ってみますけど。

# curl --verbose -g 'https://[{IPv6アドレス}]/'

以下では、IPv6DNS(これは、レジストラ側が対応してないのか?)を除いて、上手くいったから大丈夫そうですがね。

IPv6 test - web site reachability

あと、以下のSSLのテストサイトなんですけど、
ファイアーウォールでガチガチにしていると、そもそもチェックの為の接続に失敗するという(笑)
接続出来ないのが一番堅いんじゃないの?(笑)(チェック観点が違うから、そんな事は無いと思いますが)

https://www.ssllabs.com/ssltest/

あと、以下は、公共性の高いサイトだと、
古いOSやブラウザにも対応しないといけなさそうで、結構悩ましいでしょうね。
僕のホームページは、まぁ良いだろう(笑)

ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers  'EECDH+AESGCM+AES128 EECDH+AESGCM EECDH+AES128 EECDH+AES256 !aNULL !eNULL !SSLv2 !SSLv3';

ただのHTTPS化だけで終わらそうと思ったら、意外と欲が出てしまった(笑)

参考:
Webサーバー nginx における SSL証明書設定の安全性向上 ~SSL Server Test で A+ 判定を目指して~ | SaintSouth.NET
[IPv6対応] nginxとLet's encryptでA+級のセキュアなWebサーバー構築
無償SSLサーバー証明書Let's Encryptの普及とHTTP/2および常時SSL化 | OSDN Magazine
じゃあ ssl_ciphers (SSLCipherSuite) は何を指定したらいいの!? って話 | おふろめ
Let's EncryptのSSL証明書更新時にサービスを再起動する
Nginx の location ブロックのパターン化
OpenSSLコマンドで証明書のチェック | Pistolfly
Use a SSL certificate