フリーで90日有効のSSL証明書を取得できる「Let’s Encrypt」
90日毎に更新する必要があるため、プログラムを実行して証明書の取得ができるようになっている。
公式のプログラム(クライアント)は「https://github.com/certbot/certbot」にあるが、CentOS6以降やUbuntu向けに作られており、古いPythonの環境であるCentOS5では動作させるのが大変である。
公式以外のクライアントを探すと、「List of Client Implementations」に互換クライアント一覧がある。
いろいろある中で、2016年1月時点では唯一のbash環境用のスクリプトだった「Shell script client: dehydrated (旧名letsencrypt.sh) 」を選択。(なお、2017年2月現在では他にも3つ出ている。)
dehydratedは、「opensslコマンド」「curlコマンド」「sedコマンド」「grepコマンド」があれば動作する。
— 2018/07/20 追記開始 —
CentOS7環境で公式のcertbotを使って運用しようとしたのですが、alias FQDNを増やす際に別の設定が作られてしまうとか、管理性があまりよろしくなかったので、CentOS7環境でも制御しやすいdehydratedを使ってます。
— 2018/07/20 追記終わり —
(1) 「git clone https://github.com/lukas2511/dehydrated.git」でプログラム取得
(2) SSL証明書発行時に使用する一時ディレクトリの設定
SSL証明書発行時、Let’s Encryptサーバから「http://ドメイン名/.well-known/acme-challenge/~」というアクセスが行われる。その際のファイルを置く場所を用意する。
ここでは/var/www/dehydratedディレクトリに置くことにする。
1. /var/www/dehydratedディレクトリ作成
2. Aapacheの設定で「/etc/httpd/conf.d/dehydrated.conf」を作成
Alias /.well-known/acme-challenge /var/www/dehydrated
<Directory /var/www/dehydrated/>
</Directory>
3. Aapacheの再起動
(3) configを作成
docs/examples/config を元にconfigを作成する。
基本的には初期状態のままで良いが、2で/var/www/dehydrated以外を指定した場合に下記の記述を変更する
WELLKNOWN="/var/www/dehydrated/"
(4) domains.txtを作成
SSL証明書を発行したいドメインをスペース区切りで列挙する。
blog.osakana.net blog2.osakana.net
(5) dehydratedを実行して、まずはアカウント登録
# ./dehydrated --config /~/dehydrated/config --register --accept-terms
# INFO: Using main config file ./config
+ Generating account key...
+ Registering account key with ACME server...
+ Done!
#
実行すると下記の様にaccountsディレクトリが作成される。
# ls -F
CHANGELOG README.md config docs/ test.sh*
LICENSE accounts/ dehydrated* domains.txt
# ls -F accounts/
~~~/
#
(6) もう一度、dehydratedを実行してSSL証明書を発行
# ./dehydrated --config ./config --cron
# INFO: Using main config file ./config
Processing ~ ~ ~
+ Signing domains...
+ Creating new directory ./certs/blog.osakana.net ...
+ Generating private key...
+ Generating signing request...
+ Requesting challenge for ~...
+ Requesting challenge for ~...
<略>
+ Responding to challenge for ~...
+ Challenge is valid!
+ Responding to challenge for ~...
+ Challenge is valid!
+ Requesting certificate...
+ Checking certificate...
+ Done!
+ Creating fullchain.pem...
+ Done!
#
下記の様にcertsディレクトリ以下にファイルが作成される。
# ls -F
CHANGELOG README.md certs/ dehydrated* domains.txt
LICENSE accounts/ config docs/ test.sh*
# ls -F certs/
~/
# ls -F certs/~/
cert-xxxxxxxxxx.csr chain-xxxxxxxxxx.pem privkey-xxxxxxxxxx.pem
cert-xxxxxxxxxx.pem chain.pem@ privkey.pem@
cert.csr@ fullchain-xxxxxxxxxx.pem
cert.pem@ fullchain.pem@
[root@niselog dehydrated]#
(7) Apache設定内のSSLファイルの指定では、作成されたファイルのうち、fullchain.pemとprivkey.pem,chain.pemを指定する。
SSLCertificateFile /~/certs/~/fullchain.pem
SSLCertificateKeyFile /~/certs/~/privkey.pem
SSLCertificateChainFile /~/certs/~/chain.pem
なお、最近は問題無いが、バージョンアップしていない古いブラウザでは、「SSLCertificateChainFile /~/certs/~/chain.pem」を抜いた2行で設定するとエラーが発生する場合があるので注意が必要。
(8) httpsアクセスをして問題無いことを確認
ブラウザからhttpsアクセスを行い、想定通りにアクセスできることを確認。
(9) crontabに、dehydratedを定期的に実行する設定を追加
毎月1日と15日に実行する処理
# crontab -l
0 3 1,15 * * /~/dehydrated/dehydrated --config /~/dehydrated/config --cron >> /tmp/ssl-update.log 2>&1
#
以下は旧バージョン
フリーで90日有効のSSL証明書を取得できる「Let’s Encrypt」
90日毎に更新する必要があるため、プログラムを実行して証明書の取得ができるようになっている。
公式のプログラム(クライアント)は「https://github.com/letsencrypt/letsencrypt」にあるが、CentOS6以降やUbuntu向けに作られており、古いPythonの環境であるCentOS5では動作させるのが大変である。
公式以外のクライアントを探すと、「List of Client Implementations」に互換クライアント一覧がある。
いろいろある中で、一番制約が薄そうな「Shell script (and a little Perl) client: https://github.com/lukas2511/letsencrypt.sh」を選択。
「opensslコマンド」「curlコマンド」「sedコマンド」があれば動作する。
perlはこの一覧が作られた当初は必要だったようだが、2016/01/04時点では不要。公式のletsencryptコマンドから移行する場合に使用するimport-account.plコマンドを使う時だけ必要なようだ。
1. 「git clone https://github.com/lukas2511/letsencrypt.sh」でプログラム取得
2. SSL証明書発行時に使用する一時ディレクトリの設定
SSL証明書発行時、Let’s Encryptサーバから「http://ドメイン名/.well-known/acme-challenge/~」という
アクセスが行われる。その際のファイルを置く場所を用意する。
ここでは/var/www/letsenryptディレクトリに置くことにする。
(1) /var/www/letsencryptディレクトリ作成
(2) Aapacheの設定で「/etc/httpd/conf.d/letsencrypt.conf」を作成
Alias /.well-known/acme-challenge /var/www/letsencrypt
<Directory /var/www/letsencrypt/>
</Directory>
(3) Aapacheの再起動
3. config.shを作成
config.sh.exampleを元にconfig.shを作成
といっても、下記の行を書くだけ
WELLKNOWN="/var/www/letsencrypt/"
4. domain.txtを作成
SSL証明書を発行したいドメインをスペース区切りで列挙する。
blog.osakana.net blog2.osakana.net
5. letsencrypt.shを実行
# ./letsencrypt.sh --config /~/letsencrypt.sh/config.sh --cron
Using config file /~/letsencrypt.sh/config.sh
Processing blog.osakana.net with SAN: blog2.osakana.net
+ Signing domains...
+ make directory /~/letsencrypt.sh/certs/blog.osakana.net ...
+ Generating private key...
+ Generating signing request...
+ Requesting challenge for blog.osakana.net...
+ Responding to challenge for blog.osakana.net...
+ Challenge is valid!
+ Requesting challenge for blog2.osakana.net...
+ Responding to challenge for blog2.osakana.net...
+ Challenge is valid!
+ Requesting certificate...
+ Checking certificate...
+ Creating fullchain.pem...
+ Done!
#
下記の様にcertsディレクトリ以下にファイルが作成される。
# ls -F
certs/ domains.txt import-certs.sh* private_key.pem
config.sh domains.txt.example letsencrypt.sh* README.md
config.sh.example import-account.pl* LICENSE test.sh*
# ls -F certs/
blog.osakana.net/
# ls -F certs/blog.osakana.net/
cert-xxxxxxxxxx.csr chain-xxxxxxxxxx.pem privkey-xxxxxxxxxx.pem
cert-xxxxxxxxxx.pem chain.pem@ privkey.pem@
cert.csr@ fullchain-xxxxxxxxxx.pem
cert.pem@ fullchain.pem@
#
Apache設定内のSSLファイルの指定では、作成されたファイルのうち、fullchain.pemとprivkey.pem,chain.pemを指定する。
SSLCertificateFile /~/certs/~/fullchain.pem
SSLCertificateKeyFile /~/certs/~/privkey.pem
SSLCertificateChainFile /~/certs/~/chain.pem
ちなみに、「SSLCertificateChainFile /~/certs/~/chain.pem」を抜いた2行で設定するとChromeやIEでは問題無いが、Firefoxでのみ「sec_error_unknown_issuer」のエラーがでる。
(なお、fullchain.pemとprivkey.pemを指定しているのは、標準のletsencryptを使った場合に生成されるapache用cocnfigファイルで使われていたから)
おまけ:CentOS4で使用する場合に必要になること
・curlの証明書問題
→ /usr/share/ssl/certs/ca-bundle.crt を更新する
→ OpenSSLが古いためにエラーが発生
「curl: (35) error:0D0890A1:asn1 encoding routines:ASN1_verify:unknown message digest algorithm」
・OpenSSLが古い
→ /usr/local/openssl1とかに新しいバージョンをインストールして回避
letsencrypt.shの冒頭に、PATHとLD_LIBRARY_PATHを定義して、こちらを優先するように設定
→ こっちのOpenSSLを使うcurlをコンパイル
・trコマンドが古い
letsencrypt.shを実行すると「tr: オプションが違います — _」というエラー
→ 新しいバージョンのtrが含まれるcoreutilsを/usr/localにインストール
・bashコマンドが古い
環境変数操作で「SAN+=~」ということをやってるがCentOS4のBASHでは非対応
letsencrypt.shを修正して、CentOS4でも使える操作に変更
「SAN+=”DNS:${altname}, “」→「SAN=”${SAN}DNS:${altname}, “」
・下記のエラーでうまく行かない
# ./letsencrypt.sh --cron --config /~/letsencrypt.sh/config.sh
Using config file /~/letsencrypt.sh/config.sh
Processing xxxxxx with SAN: xxxxx
+ Signing domains...
+ Generating private key...
+ Generating signing request...
+ Requesting challenge for xxxxxx...
+ ERROR: An error occurred while sending post-request to https://acme-v01.api.letsencrypt.org/acme/new-authz (Status 403)
Details:
{"type":"urn:acme:error:unauthorized","detail":"No registration exists matching provided key","status":403} + Error: Can't retrieve challenges ()
#
→ 失敗した時のcertが悪さをしていた
certsディレクトリの中身とprivate_key.pemを削除して再実行したところ成功