Dragon Arrow written by Tatsuya Nakaji, all rights reserved animated-dragon-image-0164

certbotで無料でHTTPS化

updated on 2020-01-09

イメージ

certbotで無料でHTTPS化



実行環境

  • Amazon Linux 2
  • nginx version: nginx/1.12.2


1.Let's Encryptとは?

今まで、サイトをSSL化するためには、1年単位でライセンスを購入し、その証明書を用いる必要がありました。

こいつがピンきりですが高いものはめちゃくちゃ高くて、年間数千円~十数万円の費用がかかるのが普通でした。

そこで、「インターネットを介した安全な通信を行う際の、経済面・技術面・教育面での障壁を減らすこと」を指名として活動している、非営利団体のISRG(Internet Security Research Group)が開発したのが、このLet's Encryptなのです。


これを使えば無料かつ、面倒な更新手続き・運用を自動化しながら、安全な通信を行うことが出来るようになります。


2.なぜcertbotを使うの?

こちらの記事を参考に見ていただくと、今回はパターン2になります。

https://recipe.kc-cloud.jp/archives/11067

AWSではAWS Certificate Manager (ACM) を使って無料で証明書を発行できますが、以下のサービスでしか配置ができません。

・Elastic Load Balancing.
・Amazon CloudFront.


◯主なメリット まとめ
・更新はAWSが自動で行なってくれる(最短で有効期限の60日前~)
・再起動などのダウンタイムを最小限にできる
・証明書をコンソールなどから一括で管理が出来る
・ワイルドカードも対応可能

◯利用する際の注意点 まとめ
・特定サービスのみの対応(ELB,Cloudfront)
・AWS環境以外で利用ができない
・最低限の証明となっている(SSL/TSL)
・アカウント単位で20個までという制限がある
・コード署名や E メールの暗号化に利用できない


結論: ACM自体には基本お金がかからないが、ELBやCloudFrontで結構お金がかかるので、完全無料のものを使いたいと思った結果、certbotにたどり着きました。


3.証明書を発行しよう!

3-1.certbotのインストール

certbotとはLet’s Encryptが提供する、クライアントソフトウェアで、これを使えばSSL証明書の取得・更新作業を自動化出来るようになっています。

今回はこれを使ってサイトのSSL化をしていくので、まずはcertbotをインストールします。


最初はGitHubからcertbotをcloneしてcertbotを実行できるようにしようと思っていたのですが、2019年5月現在、GitHubからcloneしてcertbot-autoを実行すると、次のエラーが発生します。

Requesting to rerun ./certbot-auto with root privileges...
Sorry, I don't know how to bootstrap Certbot on your operating system!

設定ファイルを書き換えて対応する方法もあるようなのですが、今回はyumでcertbotをインストールすることにします。


$ sudo yum -y install certbot


Nginx対応プラグインのインストール

Nginxを使用している場合は「certbot-nginx」をインストールします。

certbot実行時にnginxを指定することで、nginxの設定ファイルに証明書の設定を自動で追加してくれます。(めちゃくちゃ便利)

$ sudo yum -y install certbot-nginx


certbotを使ってSSL証明書を取得

Nginxを使用している場合は、オプションで「–nginx」を指定します。

「-d」オプションに続いてドメイン名を入力します。

certbot実行時に権限でエラーになる場合は、root権限で実行します。

$ certbot --nginx -d www.example.com
Saving debug log to /var/log/letsencrypt/letsencrypt.log
Plugins selected: Authenticator nginx, Installer nginx
Obtaining a new certificate
Performing the following challenges:
http-01 challenge for www.example.com
Waiting for verification...
Cleaning up challenges
Deploying Certificate to VirtualHost /etc/nginx/conf.d/froala-blog.conf

Please choose whether or not to redirect HTTP traffic to HTTPS, removing HTTP access.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1: No redirect - Make no further changes to the webserver configuration.
2: Redirect - Make all requests redirect to secure HTTPS access. Choose this for
new sites, or if you're confident your site works on HTTPS. You can undo this
change by editing your web server's configuration.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Select the appropriate number [1-2] then [enter] (press 'c' to cancel): 2
Redirecting all traffic on port 80 to ssl in /etc/nginx/conf.d/froala-blog.conf

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Congratulations! You have successfully enabled https://www.examle.com

You should test your configuration at:
https://www.ssllabs.com/ssltest/analyze.html?d=www.example.com
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

IMPORTANT NOTES:
- Congratulations! Your certificate and chain have been saved at:
/etc/letsencrypt/live/www.example.com/fullchain.pem
Your key file has been saved at:
/etc/letsencrypt/live/www.example.com/privkey.pem
Your cert will expire on 2019-10-03. To obtain a new or tweaked
version of this certificate in the future, simply run certbot again
with the "certonly" option. To non-interactively renew *all* of
your certificates, run "certbot renew"
- If you like Certbot, please consider supporting our work by:

Donating to ISRG / Let's Encrypt:   https://letsencrypt.org/donate
Donating to EFF:                    https://eff.org/donate-le


Nginxの再起動

Nginxのコンフィグをテストし、問題なければNginxを再起動します。

$ nginx -t
$ sudo service nginx restart


以上でhttpsでアクセスできます。




SSL/TLS証明書を失効・削除したいとき

 Let’s Encrypt で発行した SSL/TLS 証明書を失効した上で削除します。 これは certbot revoke コマンドで行うことができます。 (certbot コマンドには delete オプションもありますが、これだと失効させられないので注意してください。) certbot revoke コマンドを実行する際に –cert-pat オプションで、失効させる証明書のパスを指定します。 コマンドを実行すると、次のような表示で完了することができます。

削除のみ

$ sudo certbot delete --cert-name www.example.com

削除・失効

$ sudo certbot revoke --cert-path /etc/letsencrypt/live/www.example.com/cert.pem
Saving debug log to /var/log/letsencrypt/letsencrypt.log
Starting new HTTPS connection (1): acme-v01.api.letsencrypt.org

-------------------------------------------------------------------------------
Would you like to delete the cert(s) you just revoked?
-------------------------------------------------------------------------------
(Y)es (recommended)/(N)o: y

-------------------------------------------------------------------------------
Deleted all files relating to certificate www.example.com.
-------------------------------------------------------------------------------

-------------------------------------------------------------------------------
Congratulations! You have successfully revoked the certificate that was located
at /etc/letsencrypt/live/www.example.com/cert.pem

-------------------------------------------------------------------------------

これで、SSL/TLS証明書を失効させ、削除することができました。 ただし、Apache や Nginx などの各種ソフトウェアへ行った設定は残ったままですので、それらについては別途対応するようにしてください。

証明書を手動更新したいとき

以下は、証明書の期限がまだ十分にあるためリニューアルを実行しませんでしたという内容になっていますが、期限前にやると実行されます。

$ sudo certbot renew --post-hook "sudo service nginx restart"
Saving debug log to /var/log/letsencrypt/letsencrypt.log

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Processing /etc/letsencrypt/renewal/www.example.com
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Cert not yet due for renewal

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

The following certs are not due for renewal yet:
/etc/letsencrypt/live/www.example.com/fullchain.pem expires on 2019-10-06 (skipped)
No renewals were attempted.
No hooks were run.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -


証明書を自動更新したいとき

cronで自動更新の設定

$ sudo vi /etc/cron.d/letsencrypt

SSL証明書の有効期限が90日なので自動更新の設定をします。

#毎月1日の1時に強制的に更新をします
0 1 1 * * root certbot renew --force-renewal --deploy-hook "service httpd restart"

これで設定終了です。簡単なのでサクッとやってしまいましょう。


* --pre-hook, --post-hook, --deploy-hook について

ディレクトリ処理のトリガー
precertbotが全部の証明書更新の処理を始める前に証明書の更新の有無に関わらず必ず実行されます
postcertbotが全部の証明書更新の処理を終わった後で証明書の更新の有無に関わらず必ず実行されます
deploycertbotが個々の証明書更新の処理を終わった後で証明書の更新された場合にだけ実行されます


最後に

きになる人だけ。

--nginxオプションで自動で設定の書き込みを行なったが、自動で加わった内容をチェックする

ーなくなった部分 赤

+付け加えられた部分 緑

( /etc/nginx/conf.d/froala-blog.conf )

# log directory
error_log  /var/www/rails/froala-blog/log/nginx.error.log;
access_log /var/www/rails/froala-blog/log/nginx.access.log;
# max body size
client_max_body_size 2G;
upstream app_server {
  # for UNIX domain socket setups
  server unix:/var/www/rails/froala-blog/tmp/sockets/unicorn.sock fail_timeout=0;
}
server {
  - listen 80;
  server_name www.example.com [IP];
  # nginx so increasing this is generally safe...
  keepalive_timeout 5;
  # path for static files
  root /var/www/rails/froala-blog/public;
  # page cache loading
  try_files $uri/index.html $uri.html $uri @app;
  location @app {
    # HTTP headers
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto https; # ここは手動で追記する 追記しないと「リダイレクトが多すぎます」というエラーが出てアクセスできない
    proxy_set_header Host $http_host;
    proxy_redirect off;
    proxy_pass http://app_server;
  }
  # Rails error pages
  error_page 500 502 503 504 /500.html;
  location = /500.html {
    root /var/www/rails/froala-blog/public;
  }
    listen 443 ssl; # managed by Certbot
    ssl_certificate /etc/letsencrypt/live/www.exaple.com/fullchain.pem; # managed by Certbot
    ssl_certificate_key /etc/letsencrypt/live/www.exaple.com/privkey.pem; # managed by Certbot
    include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
}


server {
    if ($host = www.exaple.com) {
        return 301 https://$host$request_uri;
    } # managed by Certbot
  listen 80;
  server_name www.exaple.com [IP];
    return 404; # managed by Certbot
}