29と30のリビジョン間の差分
2016-12-25 15:54:54時点のリビジョン29
サイズ: 19090
コメント:
2016-12-26 00:07:07時点のリビジョン30
サイズ: 20009
コメント:
削除された箇所はこのように表示されます。 追加された箇所はこのように表示されます。
行 9: 行 9:
<<TableOfContents(2)>> == 対象環境 ==
 * 対象OSは FreeBSD とする。
 * その他のOSでは以下の点に相違がある。
   * インストール方法
   * インストールされるディレクトリ
   * 自動更新のための手続き(設定)
 * 逆に以下の点は参考にできる。
   * 設定パラメータとその意味
   * 運用事例
行 12: 行 20:
 * 本解説では「[[https://github.com/lukas2511/dehydrated|dehydrated]]」を採用する。  * Let's Encrypt からのSSL証明書発行するためのツールとして「[[https://github.com/lukas2511/dehydrated|dehydrated]]」を採用する。
行 16: 行 24:
   * dehydrated はまだ少ない([[https://curl.haxx.se/|cURL]] のせいで増えてるが)。
   * わけわかんなくなっても、シェルなのでソースコード読んで理解できる。
   * dehydrated はまだ依存が少ない([[https://curl.haxx.se/|cURL]] のせいで増えてるが)。
   * わけわかんなくなっても、シェルなのでソースコード読んで理解できる。また長いコードではない。

<<TableOfContents(2)>>
行 54: 行 64:
 * 例えば Apache(2.4)では以下のように指定することになる。  * 例えば Apache(2.4.8以上)では以下のように指定することになる。
行 59: 行 69:
 * 古い Apache(2.2)だと以下のパターンで指定する。  * 古い Apache(2.4.8未満)だと以下のパターンで指定する。
行 64: 行 74:

}}}
 * cert.pem(署名済みSSL証明書公開鍵)+chain.pem(中間証明書)=fullchain.pem(両者を足したモノ) の使い分けは使用時確認すること。
 * なお、通常中間証明書をブラウザが持っていることは期待しない方がよい。限定的には持っているブラウザもあるが、広く世間で使おうと思ったら、持ってない前提でいるのがよい
}}}
 * cert.pem(署名済みSSL証明書公開鍵)+chain.pem(中間証明書)=fullchain.pem(両者を足したモノ) の使い分けはサーバーの仕様従うこと。
 * なお、Let's Encrypt の中間証明書(chain.pem)をブラウザが持っていることは期待しない方がよい。限定的には持っているブラウザもあるが、広く世間で使おうと思ったら、持ってない前提で運用すべき
行 93: 行 102:
 * 特に前者は Certbot で言うところの /usr/local/etc/letsencrypt/accounts/acme-v01.api.letsencrypt.org/directory/アカウント/private_key.json と同じものである。
行 95: 行 103:
 * これら設定は「ACCOUNT_KEY_JSON」と「ACCOUNT_KEY」設定で指定が可能である。  * これら設定は「ACCOUNT_KEY_JSON」(.json)と「ACCOUNT_KEY」(.pem)設定で指定が可能である。
行 111: 行 119:
   * 有効期限残日数を指定する。今日を基準に有効期限が指定日数未満になったら更新を行う。
   * なお FreeBSD では、更新頻度そのものは毎週行われる(periodic の weekly 指定)。
   * 有効期限残日数を指定する。今日を基準に有効期限が指定日数(秒換算)未満になったら更新を行う。
   * なお FreeBSD では、更新そのものは毎週行われる(periodic の weekly 指定、つまり7日単位に丸められる)。
行 133: 行 141:
WELLKNOWN="/usr/local/etc/dehydrated/.acme-challenges" #デフォルト設定
ACCOUNT_KEY="/usr/local/etc/dehydrated/private_key.pem" #デフォルト設定
ACCOUNT_KEY_JSON="/usr/local/etc/dehydrated/private_key.json" #デフォルト設定
#CA="https://acme-staging.api.letsencrypt.org/directory" # テスト発行したい場合
行 148: 行 154:
 * 他にも、以下のルールで処理される。
   * 大文字は小文字に変換される。
   * 複数の空白類(スペース、タブなど)で区切り、1個の空白として処理される。
   * 行頭が # や空行は無視。
行 151: 行 161:
 * {{{-c}}} オプションは {{{--cron}}} と同じ意味である。  * {{{-c}}} オプションは {{{--cron}}} と同じ意味である(だからどうした!:-)
行 167: 行 177:
 * 更新した後、サーバーへの反映を行うスクリプトを weekly_dehydrated_deployscript で指定できる。  * 全ての更新が完了した後、サーバーへの反映を行うスクリプトを weekly_dehydrated_deployscript で指定できる。
行 189: 行 199:
単純なサーバー構成(jail だの docker だの無し)で、そう複雑で無いSSL証明書の運用を行うなら、
python 依存が無い ports/security/dehydrated を使うのがシンプルと思われ。

【要検証】もう一つ、ports/security/dehydrated にメリットがあるとすれば、現状(py-letsencrypt は 0.5.0)では ECDSA で証明書を作成・更新するのが手間である点くらい(最新の py-certbot 0.8.1 では未検証)。
certbot は Let' Encrypt 推奨ACMEクライアントで、
証明書の失効(revoke)までできるので、
フルスペックの機能使うなら…というところでしょうね。

ACMEクライアントは、certbot、dehydrated だけでなく、他にもあるので、チェックしてみるといいかもしれない。
行 206: 行 217:

== Q. Webサービス立ち上げてないサーバーでSSL証明書使いたいです! ==
A. そんなあなたにDNS認証(dns-01)。続きはWebで。
行 318: 行 332:
 * [[https://certbot.eff.org/|Certbot]]
行 319: 行 334:
 * [[https://certbot.eff.org/|Certbot]]  * [[https://letsencrypt.jp/docs/using.html|Let's Encrypt ユーザーガイド]]
 * [[https://letsencrypt.org/docs/rate-limits/|取得数制限]
 * [[https://letsencrypt.org/docs/staging-environment/|ステージング環境]]
 * [[https://letsencrypt.org/docs/client-options/|ACMEクライアント実装]]

Let's EncryptでSSL証明書の新規作成と自動更新(http-01編)

  • Lets' EncryptによるSSL証明書の自動取得・自動更新に関するメモを残す。

  • Let's Encrypt とその周辺ツールはどんどん変わっていて、今後の改善によっては本記述が間に合わないことがある。
  • Let's Encrypt 公式ツールであるところの certbot については特に記載しない。使わなくなってしばらく経過していること、やはりどんどん変わっていて、参考にならないからである。
  • 本記述に関して何か差違があると感じた場合は、本家のドキュメントを確認して欲しい。
  • また運用環境が極端に違うことから、FreeBSD環境での解説のみとし、CentOS環境での解説は行わない。
  • 将来もう少し、環境差違が無くなってからCentOS環境での解説を行うつもりである。

対象環境

  • 対象OSは FreeBSD とする。
  • その他のOSでは以下の点に相違がある。
    • インストール方法
    • インストールされるディレクトリ
    • 自動更新のための手続き(設定)
  • 逆に以下の点は参考にできる。
    • 設定パラメータとその意味
    • 運用事例

certbot と dehydrated

  • Let's Encrypt からのSSL証明書発行するためのツールとして「dehydrated」を採用する。

  • これは以下の点から、採用した。
    • bash/zsh 依存スクリプトであるため、特別な言語環境(Python)を必要としない。
    • certbotの場合、Python に依存すするくらいならまだ良いが、依存する Python モジュールが大量にあるため。

    • dehydrated はまだ依存が少ない(cURL のせいで増えてるが)。

    • わけわかんなくなっても、シェルなのでソースコード読んで理解できる。また長いコードではない。

インストール

  • ports ないしは packages から、以下の ports をインストールする。
  • また、定期実行が設定ファイルに1行記述するだけで制御できるレベルで簡単である。
  • ただ、この事情は ports メンテナの功績によるものなので:-)、他の(OS)環境でそうであるかは不明である。

準備

  • いくつかのディレクトリの作成および設置ルールを決める。

証明書の設置場所

  • ports/security/dehydrated では /usr/local/etc/dehydrated/certs/コモンネーム/ 以下のファイルが設置される。
    • /usr/local/etc/dehydrated/certs/コモンネーム/cert-UNIXタイムスタンプ.csr
    • /usr/local/etc/dehydrated/certs/コモンネーム/cert-UNIXタイムスタンプ.pem
    • /usr/local/etc/dehydrated/certs/コモンネーム/chain-UNIXタイムスタンプ.pem
    • /usr/local/etc/dehydrated/certs/コモンネーム/fullchain-UNIXタイムスタンプ.pem
    • /usr/local/etc/dehydrated/certs/コモンネーム/privkey-UNIXタイムスタンプ.pem
  • 設置場所についてはプログラム中に直接記載されているため、変更は不可能である。
  • その代わり、シンボリックリンクで誘導することは可能。
  • また、最新(現在)の証明書に対してシンボリックリンクが張られる。

# cd /usr/local/etc/dehydrated/certs/コモンネーム
# ls -alF
total 122
-rw-------  1 root  wheel   436 May 29 06:02 cert-1464469337.csr
-rw-------  1 root  wheel  1533 May 29 06:02 cert-1464469337.pem
lrwx------  1 root  wheel    19 May 29 06:02 cert.csr@ -> cert-1464469337.csr
lrwx------  1 root  wheel    19 May 29 06:02 cert.pem@ -> cert-1464469337.pem
-rw-------  1 root  wheel  1647 May 29 06:02 chain-1464469337.pem
lrwx------  1 root  wheel    20 May 29 06:02 chain.pem@ -> chain-1464469337.pem
-rw-------  1 root  wheel  3180 May 29 06:02 fullchain-1464469337.pem
lrwx------  1 root  wheel    24 May 29 06:02 fullchain.pem@ -> fullchain-1464469337.pem
-rw-------  1 root  wheel   302 May 29 06:02 privkey-1464469337.pem
lrwx------  1 root  wheel    22 May 29 06:02 privkey.pem@ -> privkey-1464469337.pem
  • 例えば Apache(2.4.8以上)では以下のように指定することになる。

  SSLCertificateFile    /usr/local/etc/dehydrated/certs/コモンネーム/fullchain.pem
  SSLCertificateKeyFile /usr/local/etc/dehydrated/certs/コモンネーム/privkey.pem
  • 古い Apache(2.4.8未満)だと以下のパターンで指定する。

  SSLCertificateFile      /usr/local/etc/dehydrated/certs/コモンネーム/cert.pem
  SSLCertificateChainFile /usr/local/etc/dehydrated/certs/コモンネーム/chain.pem
  SSLCertificateKeyFile   /usr/local/etc/dehydrated/certs/コモンネーム/privkey.pem
  • cert.pem(署名済みSSL証明書公開鍵)+chain.pem(中間証明書)=fullchain.pem(両者を足したモノ) の使い分けはサーバーの仕様に従うこと。
  • なお、Let's Encrypt の中間証明書(chain.pem)をブラウザが持っていることは期待しない方がよい。限定的には持っているブラウザもあるが、広く世間で使おうと思ったら、持っていない前提で運用すべき。

ドメイン所有者確認トークンディレクトリの指定

  • ドメイン所有者確認トークンの設置場所(ディレクトリ)を決める。
    • 「ドメイン所有者確認トークン」はドメインの所有者であること確認するための「トークン」(一時発行キー)である。
  • これはWebサーバー側の設定とも連動する話なので、その前提で決定する。
  • 以下はアクセスログ(例)である。

66.133.109.36 - - [29/May/2016:06:02:21 +0900] "GET /.well-known/acme-challenge/チャレンジトークン HTTP/1.1" 200 87 "-" "Mozilla/5.0 (compatible; Let's Encrypt validation server; +https://www.letsencrypt.org)"
  • デフォルトで /usr/local/etc/dehydrated/.acme-challenges となっている。
  • またこの設定は「WELLKNOWN」変数で変更可能である。
  • このディレクトリはインストール時に設定されるので、例えば Apache(2.4)の場合、以下のように設定する。

Alias /.well-known/acme-challenge/ /usr/local/etc/dehydrated/.acme-challenges/

<Directory /usr/local/etc/dehydrated/.acme-challenges>
  Options       None
  AllowOverride None
  Require       all granted
  Header        add Content-Type text/plain
</Directory>

アカウントキーの保存ディレクトリの指定

  • アカウントキーと呼ばれるJSONとRSA秘密鍵の保存ディレクトリを指定する。
  • デフォルトで /usr/local/etc/dehydrated/private_key.{json,pem} となる。
  • これら設定は「ACCOUNT_KEY_JSON」(.json)と「ACCOUNT_KEY」(.pem)設定で指定が可能である。

設定ファイル

  • 上記準備と合わせて、設定ファイルに記載する。いわゆるシェルスクリプトなので、その記法はそれに準じる。
  • 設定ファイルは /usr/local/etc/dehydrated/config である(シェル文法で記述)。
  • ports の場合、config.example が同じディレクトリにインストールされるので、合わせて参照して欲しいところ。
  • 色々と設定する項目はあるが、下記の設定のみ使用する。
    • WELLKNOWN
    • ACCOUNT_KEY
    • ACCOUNT_KEY_JSON
    • RENEW_DAYS
    • PRIVATE_KEY_RENEW
    • KEY_ALGO / KEYSIZE
    • CONTACT_EMAIL
  • WELLKNOWN, ACCOUNT_KEY, ACCOUNT_KEY_JSONについてはすでに解説済みなので、残りについて説明する。
  • RENEW_DAYS
    • 有効期限残日数を指定する。今日を基準に有効期限が指定日数(秒換算)未満になったら更新を行う。
    • なお FreeBSD では、更新そのものは毎週行われる(periodic の weekly 指定、つまり7日単位に丸められる)。
  • PRIVATE_KEY_RENEW
    • 更新する毎に秘密鍵を作り直すか否かを指定する。
    • デフォルトで「yes」である(毎回作り直す)。
    • 指定可能な値は「yes」か「それ以外」かしか無いので、「Yes」と書いてもNoと解釈される。
    • また「作り直さない」選択にメリットも無ければ推奨でもないので、ごく極めて例外的な何かが無ければ「yes」を選択すること。
  • KEY_ALGO / KEYSIZE
    • SSL証明書の鍵アルゴリズム(KEY_ALGO)と鍵サイズ(KEYSIZE)を指定する。
    • KEY_ALGO での選択可能な識別子は「rsa」「prime256v1」「secp384r1」。
    • KEY_ALGO が「rsa」の時に限って KEYSIZE を指定する(2048, 3072, 4096)。
  • CONTACT_EMAIL
    • Let's Encrypt では連絡用メールアドレスの指定が必要となるので、メールアドレスを指定する。

設定ファイル例

   1 alias openssl="/usr/bin/openssl"
   2 
   3 RENEW_DAYS="30"
   4 KEY_ALGO="prime256v1"
   5 #KEY_ALGO="rsa" KEYSIZE="2048"
   6 CONTACT_EMAIL="メールアドレス"
   7 #CA="https://acme-staging.api.letsencrypt.org/directory" # テスト発行したい場合
   8 

コモンネームファイル

  • 発行するSSL証明書のコモンネームを列挙したファイルを作成する。
  • このファイル名は /usr/local/etc/dehydrated/domains.txt で指定される。
  • 1行1証明書で、1カラム目はコモンネームとなり、2カラム目以降は SANs(Subject Alternative Names)を指定する。
  • 以下のサンプルでは example.org, example.com の2枚の証明書を作成/更新する。

example.org www.example.org
example.com www.example.com wiki.example.com
  • また、「example.org」のSANとして「www.example.org」が、「example.com」のSANとして「www.example.com」と「wiki.example.com」が合わせて設定される。
  • 他にも、以下のルールで処理される。
    • 大文字は小文字に変換される。
    • 複数の空白類(スペース、タブなど)で区切り、1個の空白として処理される。
    • 行頭が # や空行は無視。

初回実行ないしは手動更新の仕方

  • 以上の設定が完了したら、コマンドを root で実行する。
  • -c オプションは --cron と同じ意味である(だからどうした!:-)。

dehydrated -c
  • とりあえずプログラムを読んだ限りでは環境変数汚染依存はなさそう。
  • 正直、LANG、LC_* くらいはケアして欲しいところだけど。

自動更新

  • ports/security/dehydrated では定期実行に periodic(8) を採用している。

  • よって定期実行は /etc/periodic.conf ないしは /etc/periodic.conf.local ファイルにて設定を行う。

weekly_dehydrated_enable="YES"
weekly_dehydrated_deployscript="/usr/local/etc/dehydrated/deploy.sh"
  • 単純に更新するだけなら、weekly_dehydrated_enable="YES" と設定するだけで良い。

  • 全ての更新が完了した後、サーバーへの反映を行うスクリプトを weekly_dehydrated_deployscript で指定できる。
  • 指定されたファイルは、実行権限(chmod +x)も必要。
  • ただし、証明書の更新が無くても実行されるので、厳密には証明書が更新されたか確認した方がいい。
  • とは言え、現地時間で毎週土曜日04時05分(/etc/crontab の periodic weekly 行参照のこと)に実行されるので、そのあたりはテキトーでもいいかもしれない。
  • dehydrated -gc は古い証明書の削除(クリーンナップ)を行う。

  • わざと残しておくのであれば実行は不要である。

/usr/local/etc/dehydrated/deploy.sh 例

#/bin/sh
/usr/sbin/service apache24 restart && /usr/local/bin/dehydrated -gc

よくある質問とその答え

Q. ECDSA 対応は必須?

A. 提供必須というほど、対応しているブラウザは普及してないですね。ごく最新の有名どころブラウザはともかく、四方山ブラウザを考慮するとまだまだ。 サーバー側でRSAとECDSAの両方を提案してブラウザが受け入れられる方を…という解決策も無くもないですが(使えるか知らないし興味ない)、結局RSAの鍵も作らないと行けないことには変わりないので、当面、RSA2048で行くのが正解かと。

Q. ports/security/dehydrated と ports/security/py-certbot とどっちがいいですか?

A. 目標が違うのでどっちとも言えない。 certbot は Let' Encrypt 推奨ACMEクライアントで、 証明書の失効(revoke)までできるので、 フルスペックの機能使うなら…というところでしょうね。

ACMEクライアントは、certbot、dehydrated だけでなく、他にもあるので、チェックしてみるといいかもしれない。

Q. 下記のように所有者確認アクセスに失敗、証明書が更新されません!

66.133.109.36 - - [29/May/2016:04:45:29 +0900] "GET /.well-known/acme-challenge/チャレンジトークン HTTP/1.1" 404 268 "-" "Mozilla/5.0 (compatible; Let's Encrypt validation server; +https://www.letsencrypt.org)"

A. Webサーバーの設定ミスの可能性があります! 自分は Alias /.well-known/acme-challenge/ /usr/local/etc/dehydrated/.acme-challengesと最後に「/」を入れ忘れていました! このケースでは Alias の第一、第二引数ともに最後に「/」を含める必要がある。

他にも良くありそうなのが、設定した後にサーバー再起動(ないしは再読み込み)を忘れていたなどが考えられる。

あとリカバリとして、更新に失敗して残ってるCSRや秘密鍵を削除するのに dehydrated -gc を実施すること。

Q. Webサービス立ち上げてないサーバーでSSL証明書使いたいです!

A. そんなあなたにDNS認証(dns-01)。続きはWebで。

letsencrypt.sh から dehydrated への移行

商標上の理由で、letsencrypt.sh から dehydrated へ名前変更が実施された。 合わせてディレクトリから設定まで色々変更になったので対応についてメモっておく。

ディレクトリ名の変更

/usr/local/etc/letsencrypt.sh から /usr/local/etc/dehydrated へ変更になったわけであるが、更新後は新しいディレクトリが作成されていることもあり、こまめに手を入れる必要がある。

/usr/local/etc/letsencrypt.sh/config.sh

mv /usr/local/etc/letsencrypt.sh/config.sh /usr/local/etc/dehydrated/config

※config.sh から config に変更になったので合わせて変更を実施する。

/usr/local/etc/letsencrypt.sh/deploy.sh

mv /usr/local/etc/letsencrypt.sh/deploy.sh /usr/local/etc/dehydrated/

/usr/local/etc/letsencrypt.sh/domains.txt

mv /usr/local/etc/letsencrypt.sh/domains.txt /usr/local/etc/dehydrated/

/usr/local/etc/letsencrypt.sh/hook.sh

mv /usr/local/etc/letsencrypt.sh/hook.sh /usr/local/etc/dehydrated/

/usr/local/etc/letsencrypt.sh/certs/

mv /usr/local/etc/letsencrypt.sh/certs /usr/local/etc/dehydrated/
  • certs ディレクトリはインストール時には作成されない。
  • SSL証明書取得時にコモンネームと合わせて作成される。
  • 既に /usr/local/etc/dehydrated/certs ディレクトリが作成されている場合は、子ディレクトリ(コモンネーム)を個別にリネーム(移動)すること。

/usr/local/etc/letsencrypt.sh/archive/

mv /usr/local/etc/letsencrypt.sh/archive /usr/local/etc/dehydrated/
  • archive ディレクトリはインストール時には作成されない。
  • SSL証明書クリーンナップ(-gc オプション指定)時にコモンネームと合わせて作成される。
  • 既に /usr/local/etc/dehydrated/archive ディレクトリが作成されている場合は、子ディレクトリ(コモンネーム)を個別にリネーム(移動)すること。

後始末

rmdir /usr/local/etc/letsencrypt.sh

※全ての移動が完了すれば、ディレクトリもファイルも残ってないはずなので削除する。

設定ファイルの変更

リネームによる影響で変更になるファイルは以下の3ファイルである。 ディレクトリ名およびコマンド名に letsencrypt.sh というキーワードが無いか確認し、dehydrated に置き換えること。

  • /usr/local/etc/dehydrated/config
  • /usr/local/etc/dehydrated/deploy.sh
  • /usr/local/etc/dehydrated/hook.sh

SSL証明書利用アプリケーションの設定変更

本例では Apache(2.4)を例に説明した。 当該箇所のディレクトリ名変更を新しいディレクトリ名に変更する。

SSL証明書の旧指定例

  SSLCertificateFile    /usr/local/etc/letsencrypt.sh/certs/コモンネーム/fullchain.pem
  SSLCertificateKeyFile /usr/local/etc/letsencrypt.sh/certs/コモンネーム/privkey.pem

トークンディレクトリの旧指定例

Alias /.well-known/acme-challenge/ /usr/local/etc/letsencrypt.sh/.acme-challenges/

<Directory /usr/local/etc/letsencrypt.sh/.acme-challenges>
  Options       None
  AllowOverride None
  Require       all granted
  Header        add Content-Type text/plain
</Directory>

起動設定(periodic)の変更

/etc/periodic.conf あるいは /etc/periodic.conf.local のどちらかの設定で定期更新を実施しているわけだが、変数名が変更になっている。

本例では以下のような設定を実施しているが、

weekly_letsencrypt_enable="YES"
weekly_letsencrypt_deployscript="/usr/local/etc/letsencrypt.sh/deploy.sh"

下記のように変更する。

weekly_dehydrated_enable="YES"
weekly_dehydrated_deployscript="/usr/local/etc/dehydrated/deploy.sh"

単純に letsencrypt や letsencrypt.sh を dehydrated に置き換えるだけである。

参考文献

certificate/レッツエンクリプトでSSL証明書の新規取得と自動更新(http-01編) (最終更新日時 2019-05-08 17:20:04 更新者 NorikatsuShigemura)