LoginSignup
0
1

More than 5 years have passed since last update.

nginx と acme-client の組合せで SNI 証明書を複数発行し運用する方法

Last updated at Posted at 2018-11-15

前程として、対象鯖は dns で正引きが出来る事。
今回は例題として以下のホスト名を用いる。
example.jp
example.com
example.org
xn--w22as22a.example.jp
以上4ホスト名
OS は FreeBSD 11.2-RELEASE を前提として記述しているが、ディレクトリや軽微なコマンドを読み替える事で他の unix 系 OS 等にも対応できると思われる。
また本記事は FreeBSD 経験者を対象に書いているので、事細かい配慮はされていません。

www/nginx 導入

web server の nginx をインスコして OS 再起動後でも自動起動の設定をする

cd /usr/ports/www/nginx
make install
sysrc nginx_enable="YES"

nginx の設定

/usr/local/etc/nginx/nginx.conf
http {
    server {
        listen  [::]:80;
        listen  80;
        server_name  example.jp;
        location ^~ /.well-known/acme-challenge/ {
            alias /usr/local/www/acme/;
        }
        location / {
            return  301 https://$host$request_uri;
        }
    }
    server {
        listen  [::]:80;
        listen  80;
        server_name  example.com;
        location ^~ /.well-known/acme-challenge/ {
            alias /usr/local/www/acme/;
        }
        location / {
            return  301 https://$host$request_uri;
        }
    }
    server {
        listen  [::]:80;
        listen  80;
        server_name  example.org;
        location ^~ /.well-known/acme-challenge/ {
            alias /usr/local/www/acme/;
        }
        location / {
            return  301 https://$host$request_uri;
        }
    }
    server {
        listen  [::]:80;
        listen  80;
        server_name  xn--w22as22a.example.jp;
        location ^~ /.well-known/acme-challenge/ {
            alias /usr/local/www/acme/;
        }
        location / {
            return  301 https://$host$request_uri;
        }
    }
}

nginx の設定確認

nginx -t

ここで「test is successful」が表示しなければ nginx.conf の記述ミスか、個別環境の差異を吸収し切れていないので、再度確認する。

nginx 起動

service nginx start

acme-client の設定下準備

touch /usr/local/www/acme/hogehoge
fetch -qo- http://example.jp/.well-known/acme-challenge/hogehoge

ここでエラーが出れば、dns 含めた記述ミスなので、再度確認。
問題が無ければ他のホスト名も確認しておく。

fetch -qo- http://example.jp/.well-known/acme-challenge/hogehoge
fetch -qo- http://example.com/.well-known/acme-challenge/hogehoge
fetch -qo- http://example.org/.well-known/acme-challenge/hogehoge
fetch -qo- http://xn--w22as22a.example.jp/.well-known/acme-challenge/hogehoge

エラーが無ければ、テストファイルを削除しておく。

unlink /usr/local/www/acme/hogehoge

security/acme-client 導入

cd /usr/ports/security/acme-client
make install

acme-client の設定

/etc/periodic.conf
### security/acme-client
weekly_acme_client_enable="YES"
weekly_acme_client_domains="example.jp example.com example.org xn--w22as22a.example.jp"

証明書の発行手続き

acme-client -vnN example.jp example.com example.org xn--w22as22a.example.jp

実行すると以下のようなログが流れていく

log
acme-client: /usr/local/etc/acme/privkey.pem: account key exists (not creating)
acme-client: /usr/local/etc/ssl/acme/private/privkey.pem: domain key exists (not creating)
acme-client: adding SAN: example.com
acme-client: adding SAN: example.org
acme-client: adding SAN: xn--w22as22a.example.jp
acme-client: https://acme-v01.api.letsencrypt.org/directory: directories
acme-client: acme-v01.api.letsencrypt.org: DNS: 2600:140b:1:181::3a8e
acme-client: acme-v01.api.letsencrypt.org: DNS: 2600:140b:1:185::3a8e
acme-client: acme-v01.api.letsencrypt.org: DNS: 23.42.210.228
acme-client: https://acme-v01.api.letsencrypt.org/acme/new-authz: req-auth: example.jp
acme-client: https://acme-v01.api.letsencrypt.org/acme/new-authz: req-auth: example.com
acme-client: https://acme-v01.api.letsencrypt.org/acme/new-authz: req-auth: example.org
acme-client: https://acme-v01.api.letsencrypt.org/acme/new-authz: req-auth: xn--w22as22a.example.jp
acme-client: /usr/local/www/acme/HhYYlbiFlhOtlp9x1aBPgZzURFWLObWBrc72k6SAxsU: created
acme-client: https://acme-v01.api.letsencrypt.org/acme/challenge/uW0ibZCGOH8TJzRmi6mkQwQ-WB5svZRW4omby4-kteE/5874344542: challenge
acme-client: /usr/local/www/acme/ldhbr5pVkPJcJd5vqWDzn8d8XA5T_yAjT6bmbCgxsCw: created
acme-client: https://acme-v01.api.letsencrypt.org/acme/challenge/kwiPqOzuQkZyGDIqJYH9hAJbQuyvzaUKOaJXafQ2-mw/6213869611: challenge
acme-client: /usr/local/www/acme/UDsdFCp0mIMsxu_uD8qwXxhJx9ePK_o19Z6P7zR2o7Y: created
acme-client: https://acme-v01.api.letsencrypt.org/acme/challenge/jIjdHQQxItemccxAVpRDQV4nfThYdlGHwjN5Yb3-hNM/6213910989: challenge
acme-client: /usr/local/www/acme/m2OoOOj_068FX5ADOuceiFmP-XMywS9Mf5_tCSq52dU: created
acme-client: https://acme-v01.api.letsencrypt.org/acme/challenge/Cynvst15YKcEe1melPpmykZd97TBHRpMAUV42eiW9k8/6213911979: challenge
acme-client: https://acme-v01.api.letsencrypt.org/acme/challenge/uW0ibZCGOH8TJzRmi6mkQwQ-WB5svZRW4omby4-kteE/5874344542: status
acme-client: https://acme-v01.api.letsencrypt.org/acme/challenge/kwiPqOzuQkZyGDIqJYH9hAJbQuyvzaUKOaJXafQ2-mw/6213869611: status
acme-client: https://acme-v01.api.letsencrypt.org/acme/challenge/jIjdHQQxItemccxAVpRDQV4nfThYdlGHwjN5Yb3-hNM/6213910989: status
acme-client: https://acme-v01.api.letsencrypt.org/acme/challenge/Cynvst15YKcEe1melPpmykZd97TBHRpMAUV42eiW9k8/6213911979: status
acme-client: https://acme-v01.api.letsencrypt.org/acme/new-cert: certificate
acme-client: http://cert.int-x3.letsencrypt.org/: full chain
acme-client: cert.int-x3.letsencrypt.org: DNS: 2600:140b:1:18b::ce0
acme-client: cert.int-x3.letsencrypt.org: DNS: 2600:140b:1:193::ce0
acme-client: cert.int-x3.letsencrypt.org: DNS: 23.42.221.179
acme-client: /usr/local/etc/ssl/acme/chain.pem: created
acme-client: /usr/local/etc/ssl/acme/cert.pem: created
acme-client: /usr/local/etc/ssl/acme/fullchain.pem: created
/var/log/nginx/access.log
2600:3000:1511:200::1d - - [14/Nov/2018:13:25:04 +0900] "GET /.well-known/acme-challenge/HhYYlbiFlhOtlp9x1aBPgZzURFWLObWBrc72k6SAxsU HTTP/1.1" 200 87 "-" "Mozilla/5.0 (compatible; Let's Encrypt validation server; +https://www.letsencrypt.org)"
2600:3000:1511:200::1d - - [14/Nov/2018:13:25:07 +0900] "GET /.well-known/acme-challenge/ldhbr5pVkPJcJd5vqWDzn8d8XA5T_yAjT6bmbCgxsCw HTTP/1.1" 200 87 "-" "Mozilla/5.0 (compatible; Let's Encrypt validation server; +https://www.letsencrypt.org)"
2600:3000:1511:200::1d - - [14/Nov/2018:13:25:09 +0900] "GET /.well-known/acme-challenge/UDsdFCp0mIMsxu_uD8qwXxhJx9ePK_o19Z6P7zR2o7Y HTTP/1.1" 200 87 "-" "Mozilla/5.0 (compatible; Let's Encrypt validation server; +https://www.letsencrypt.org)"
2600:3000:1511:200::1d - - [14/Nov/2018:13:25:12 +0900] "GET /.well-known/acme-challenge/m2OoOOj_068FX5ADOuceiFmP-XMywS9Mf5_tCSq52dU HTTP/1.1" 200 87 "-" "Mozilla/5.0 (compatible; Let's Encrypt validation server; +https://www.letsencrypt.org)"

ここで、エラーになると厄介。
ひとまず

/usr/local/etc/ssl/acme

このディレクトリを一旦移動させて、再度 acme-client コマンドを叩くのが楽であるが、短期間に繰り返し実行すると、再認証制限引っかかるので要注意。(30回/日)
丸々最初から証明書を作り直すと幸せになれます。

nginx の SSL 設定

冒頭の設定ファイル最後の一行との間に追記する事。
インデントに注意!

/usr/local/etc/nginx/nginx.conf
    server {
        listen       443 ssl http2;
        listen       [::]:443 ssl http2;

        server_name  example.jp;
        access_log   /var/log/nginx/access_SSL_example.jp.log;
        error_log    /var/log/nginx/error_SSL_example.jp.log;

        ssl_certificate         /usr/local/etc/ssl/acme/fullchain.pem;
        ssl_certificate_key     /usr/local/etc/ssl/acme/private/privkey.pem;
        ssl_session_timeout     5m;
        ssl_session_cache       shared:SSL:1m;
        ssl_session_tickets     on;
        ssl_dhparam             /etc/mail/certs/dh.param;
        ssl_protocols           TLSv1.2;
        ssl_ciphers ECDHE:ECDSA:!RC4:!NULL:!3DES:!CBC;
        ssl_prefer_server_ciphers on;
        add_header Strict-Transport-Security "max-age=15768000; includeSubDomains";
        ssl_stapling            on;
        ssl_stapling_verify     on;
        ssl_trusted_certificate /usr/local/etc/ssl/acme/fullchain.pem;
        ssl_session_ticket_key /usr/local/etc/ssl/ticket.key;

        location / {
            root   /usr/local/www/example.jp;
        }
    }
    server {
        listen       443 ssl http2;
        listen       [::]:443 ssl http2;

        server_name  example.com;
        access_log   /var/log/nginx/access_SSL_example.com.log;
        error_log    /var/log/nginx/error_SSL_example.com.log;

        ssl_certificate         /usr/local/etc/ssl/acme/fullchain.pem;
        ssl_certificate_key     /usr/local/etc/ssl/acme/private/privkey.pem;
        ssl_session_timeout     5m;
        ssl_session_cache       shared:SSL:1m;
        ssl_session_tickets     on;
        ssl_dhparam             /etc/mail/certs/dh.param;
        ssl_protocols           TLSv1.2;
        ssl_ciphers ECDHE:ECDSA:!RC4:!NULL:!3DES:!CBC;
        ssl_prefer_server_ciphers on;
        add_header Strict-Transport-Security "max-age=15768000; includeSubDomains";
        ssl_stapling            on;
        ssl_stapling_verify     on;
        ssl_trusted_certificate /usr/local/etc/ssl/acme/fullchain.pem;
        ssl_session_ticket_key /usr/local/etc/ssl/ticket.key;

        location / {
            root   /usr/local/www/example.com;
        }
    }
    server {
        listen       443 ssl http2;
        listen       [::]:443 ssl http2;

        server_name  example.org;
        access_log   /var/log/nginx/access_SSL_example.org.log;
        error_log    /var/log/nginx/error_SSL_example.org.log;

        ssl_certificate         /usr/local/etc/ssl/acme/fullchain.pem;
        ssl_certificate_key     /usr/local/etc/ssl/acme/private/privkey.pem;
        ssl_session_timeout     5m;
        ssl_session_cache       shared:SSL:1m;
        ssl_session_tickets     on;
        ssl_dhparam             /etc/mail/certs/dh.param;
        ssl_protocols           TLSv1.2;
        ssl_ciphers ECDHE:ECDSA:!RC4:!NULL:!3DES:!CBC;
        ssl_prefer_server_ciphers on;
        add_header Strict-Transport-Security "max-age=15768000; includeSubDomains";
        ssl_stapling            on;
        ssl_stapling_verify     on;
        ssl_trusted_certificate /usr/local/etc/ssl/acme/fullchain.pem;
        ssl_session_ticket_key /usr/local/etc/ssl/ticket.key;

        location / {
            root   /usr/local/www/example.org;
        }
    }
    server {
        listen       443 ssl http2;
        listen       [::]:443 ssl http2;

        server_name  xn--w22as22a.example.jp;
        access_log   /var/log/nginx/access_SSL_xn--w22as22a.example.jp.log;
        error_log    /var/log/nginx/error_SSL_xn--w22as22a.example.jp.log;

        ssl_certificate         /usr/local/etc/ssl/acme/fullchain.pem;
        ssl_certificate_key     /usr/local/etc/ssl/acme/private/privkey.pem;
        ssl_session_timeout     5m;
        ssl_session_cache       shared:SSL:1m;
        ssl_session_tickets     on;
        ssl_dhparam             /etc/mail/certs/dh.param;
        ssl_protocols           TLSv1.2;
        ssl_ciphers ECDHE:ECDSA:!RC4:!NULL:!3DES:!CBC;
        ssl_prefer_server_ciphers on;
        add_header Strict-Transport-Security "max-age=15768000; includeSubDomains";
        ssl_stapling            on;
        ssl_stapling_verify     on;
        ssl_trusted_certificate /usr/local/etc/ssl/acme/fullchain.pem;
        ssl_session_ticket_key /usr/local/etc/ssl/ticket.key;

        location / {
            root   /usr/local/www/xn--w22as22a.example.jp;
        }
    }

/etc/mail/certs/dh.param ファイルの作成

nginx の SSL 対応設定ファイルの中で ssl_dhparam で必要とされるファイルを作成しておく

openssl dhparam 3072 -out /etc/mail/certs/dh.param

<ぼそ>ディレクトリの配置場所は /usr/local/etc/ssl 辺りが好ましい</ぼそ>

nginx 設定ファイル再読み込み

nginx -k reload

おしまい😄

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1