Let's EncryptとMyDNSでワイルドカードでマルチドメイン(含サブドメイン)な証明書を発行して自動更新する。apacheも。
はじめに
Let's Encryptを初めて使ってみました。
CNをホスト名にしてSANだけだと、とある場所で「CNが一致しません!」となってしまったので、その対策が必要でした。
1枚で使いまわし証明書が発行できたので、記録します。
このエントリを読むとできること
- CentOS7のapacheで使うための
- Let's Encryptの証明書を
- MyDNSを使って
- ワイルドカード かつ マルチドメインで発行して
- 自動的に更新する
ことが、できる。はず。
環境など
対象機器および環境
- CentOS7(7.7.1908)
- certbot(1.0.0)
- php(5.4.16)
こんな証明書が欲しいことがあったとしたら
私は example.com
というドメインで検証環境を構築しています。
その配下に sub.example.com
というサブドメインがあります。
その環境のサーバたちで、1枚の証明書を使いまわしたいと思いました。
なので、こんな証明書が欲しい、ということになります。
項目 | 値 |
---|---|
CN | *.example.com |
SAN | *.example.com |
SAN | *.sub.example.com |
SAN | example.com |
MyDNSのアカウント情報
ドメイン | 値 |
---|---|
ドメイン名 | example.com |
マスターID | mydns123456 |
パスワード | mydnspassword |
サブドメイン | 値 |
---|---|
サブドメイン名 | sub.example.com |
マスターID | mydns654321 |
パスワード | subdompassword |
実装
フック用のスクリプト
MyDNSの https://github.com/disco-v8/DirectEdit があるのですが、サブドメインも含めては管理できないので、
これを参考にして、以下のものを作成しました。これを使って説明します。
Let's Encrypt MyDNS Hook Script
準備
yum -y install epel-release
yum -y update
yum -y install php php-mbstring certbot python2-certbot-apache mod_ssl
cd /root/
git clone https://github.com/bashaway/le_mydns_hook
./le_mydns_hook/accounts.conf にMyDNSのアカウント情報を記載します。
vi ./le_mydns_hook/accounts.conf
----------8<-----(snip)-----8<----------
$MYDNS_ID['ドメイン名'] = 'マスターID';
$MYDNS_PWD['ドメイン名'] = 'パスワード';
----------8<-----(snip)-----8<----------
例えば、上記の例の場合 accounts.confは以下のように修正します。
----------8<-----(snip)-----8<----------
$MYDNS_ID['example.com'] = 'mydns123456';
$MYDNS_PWD['example.com'] = 'mydnspassword';
$MYDNS_ID['sub.example.com'] = 'mydns654321';
$MYDNS_PWD['sub.example.com'] = 'subdompassword';
----------8<-----(snip)-----8<----------
証明書発行
一度作業すると、certbot renwe で引数が引き継がれるぽいので、自前フックはフルパスで指定しておく。
certbot certonly --manual \
--server https://acme-v02.api.letsencrypt.org/directory \
--preferred-challenges dns-01 \
--agree-tos --no-eff-email \
--manual-public-ip-logging-ok \
--manual-auth-hook /root/le_mydns_hook/regist.php \
--manual-cleanup-hook /root/le_mydns_hook/delete.php \
-m [email protected] \
-d *.example.com \
-d *.sub.example.com \
-d example.com
確認してみます(下はステージングで発行したので、IssuerがFakeになっています)
# openssl x509 -in /etc/letsencrypt/archive/example.com/cert1.pem -text | egrep "CN|DNS"
Issuer: C=US, O=Let's Encrypt, CN=Let's Encrypt Authority X3
Subject: CN=*.example.com
DNS:*.sub.example.com, DNS:*.example.com, DNS:example.com
apacheの設定
firewallの設定
firewall-cmd --add-service https --zone=public --permanent
firewall-cmd --reload
既存で設定されている箇所は、Let's Encryptで発行された証明書におきかえます。
#SSLCertificateFile /etc/pki/tls/certs/localhost.crt
SSLCertificateFile /etc/letsencrypt/live/example.com/cert.pem
#SSLCertificateKeyFile /etc/pki/tls/private/localhost.key
SSLCertificateKeyFile /etc/letsencrypt/live/example.com/privkey.pem
#SSLCertificateChainFile /etc/pki/tls/certs/server-chain.crt
SSLCertificateChainFile /etc/letsencrypt/live/example.com/chain.pem
httpdに設定を読み込ませます。
systemctrl reload httpd
自動更新のチェック
チェックのために、--force-renewalをつけてみます。
certbot certonly --manual \
--server https://acme-v02.api.letsencrypt.org/directory \
--preferred-challenges dns-01 \
--agree-tos --no-eff-email \
--manual-public-ip-logging-ok \
--manual-auth-hook /root//le_mydns_hook/regist.php \
--manual-cleanup-hook /root/le_mydns_hook/delete.php \
-m [email protected] \
-d *.example.com \
-d *.sub.example.com \
-d example.com \
--webroot-path /var/www/html/ \
--post-hook "systemctl reload httpd" \
--force-renewal
おそらく、以下のように更新後のものが発行されていると思います。
$ ls -1 /etc/letsencrypt/archive/example.com/cert*
/etc/letsencrypt/archive/example.com/cert1.pem <--- 最初に発行したもの
/etc/letsencrypt/archive/example.com/cert2.pem <--- force-renewalしたもの
cronによる自動更新
確認のため、短めで --force-renewal する。
0/10 * * * * root /bin/certbot renew --webroot-path /var/www/html/ --post-hook "systemctl reload httpd" --force-renewal
$ ls -1 /etc/letsencrypt/archive/example.com/cert*
/etc/letsencrypt/archive/example.com/cert1.pem <--- 最初に発行したもの
/etc/letsencrypt/archive/example.com/cert2.pem <--- 手動でforce-renewalしたもの
/etc/letsencrypt/archive/example.com/cert3.pem <--- cronでforce-renewalしたもの
問題なく更新されていたら、週に一度確認するように。
修正しないとレートリミットに引っかかっちゃうので。
0 1 * * 1 root /bin/certbot renew --webroot-path /var/www/html/ --post-hook "systemctl reload httpd"
さいごに
スクリプト
githubに置いているスクリプトです。
registでTXTレコードの追加、delete.phpでTXTレコードの削除をしています。
ふたつのスクリプトの違いは、 $CERTBOT_ENV['EDIT_CMD'] = 'REGIST';
か$CERTBOT_ENV['EDIT_CMD'] = 'DELETE';
だけです。
#!/usr/bin/php
<?php
// set environment
include(__DIR__.'/accounts.conf');
date_default_timezone_set(@date_default_timezone_get());
mb_internal_encoding('UTF-8');
mb_http_output('UTF-8');
// set certbot env
$CERTBOT_ENV['CERTBOT_DOMAIN'] = getenv('CERTBOT_DOMAIN');
$CERTBOT_ENV['CERTBOT_VALIDATION'] = getenv('CERTBOT_VALIDATION');
// txt record
$CERTBOT_ENV['EDIT_CMD'] = 'REGIST';
// mydns account
$MYDNS_ACCOUNT=$MYDNS_ID[$CERTBOT_ENV['CERTBOT_DOMAIN']].':'.$MYDNS_PWD[$CERTBOT_ENV['CERTBOT_DOMAIN']];
$MYDNS_HEADERS = array('Content-Type: application/x-www-form-urlencoded',
'Authorization: Basic '. base64_encode($MYDNS_ACCOUNT),);
// コンテクストリソースを設定
$POST_OPTIONS = array( 'http' => array('method' => 'POST',
'header' => implode("\r\n", $MYDNS_HEADERS),
'content' => http_build_query($CERTBOT_ENV)));
// get contents
$MYDNS_CONTENTS = file_get_contents($MYDNS_URL, false, stream_context_create($POST_OPTIONS));
sleep(2);
?>
#!/usr/bin/php
<?php
// set environment
include(__DIR__.'/accounts.conf');
date_default_timezone_set(@date_default_timezone_get());
mb_internal_encoding('UTF-8');
mb_http_output('UTF-8');
// set certbot env
$CERTBOT_ENV['CERTBOT_DOMAIN'] = getenv('CERTBOT_DOMAIN');
$CERTBOT_ENV['CERTBOT_VALIDATION'] = getenv('CERTBOT_VALIDATION');
// txt record
$CERTBOT_ENV['EDIT_CMD'] = 'DELETE';
// mydns account
$MYDNS_ACCOUNT=$MYDNS_ID[$CERTBOT_ENV['CERTBOT_DOMAIN']].':'.$MYDNS_PWD[$CERTBOT_ENV['CERTBOT_DOMAIN']];
$MYDNS_HEADERS = array('Content-Type: application/x-www-form-urlencoded',
'Authorization: Basic '. base64_encode($MYDNS_ACCOUNT),);
// コンテクストリソースを設定
$POST_OPTIONS = array( 'http' => array('method' => 'POST',
'header' => implode("\r\n", $MYDNS_HEADERS),
'content' => http_build_query($CERTBOT_ENV)));
// get contents
$MYDNS_CONTENTS = file_get_contents($MYDNS_URL, false, stream_context_create($POST_OPTIONS));
?>
出典
https://letsencrypt.org/ja/
https://github.com/disco-v8/DirectEdit
Author And Source
この問題について(Let's EncryptとMyDNSでワイルドカードでマルチドメイン(含サブドメイン)な証明書を発行して自動更新する。apacheも。), 我々は、より多くの情報をここで見つけました https://qiita.com/bashaway/items/42cc24be0995dff90d8f著者帰属:元の著者の情報は、元のURLに含まれています。著作権は原作者に属する。
Content is automatically searched and collected through network algorithms . If there is a violation . Please contact us . We will adjust (correct author information ,or delete content ) as soon as possible .