I tried Let's Encrypt for the first time. If CN was used as the host name and only SAN was used, "CN does not match!" Was displayed at a certain place, so countermeasures were necessary. I was able to issue a reusable certificate with one sheet, so I will record it.
be able to. Should be.
I'm building a validation environment with a domain called ʻexample.com. Under that there is a subdomain called
sub.example.com`.
I wanted to reuse one certificate for the servers in that environment.
So, I want such a certificate.
item | value |
---|---|
CN | *.example.com |
SAN | *.example.com |
SAN | *.sub.example.com |
SAN | example.com |
domain | value |
---|---|
Domain name | example.com |
Master ID | mydns123456 |
password | mydnspassword |
sub domain | value |
---|---|
Subdomain name | sub.example.com |
Master ID | mydns654321 |
password | subdompassword |
I have https://github.com/disco-v8/DirectEdit for MyDNS, but I can't manage it including subdomains, so With this as a reference, I created the following. I will explain using this. 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
Put your MyDNS account information in ./le_mydns_hook/accounts.conf.
vi ./le_mydns_hook/accounts.conf
----------8<-----(snip)-----8<----------
$MYDNS_ID['Domain name'] = 'Master ID';
$MYDNS_PWD['Domain name'] = 'password';
----------8<-----(snip)-----8<----------
For example, in the above example, modify accounts.conf as follows.
----------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<----------
Once you work, it seems that certbot renwe will take over the arguments, so specify your own hook with the full path.
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
Let's check (Issuer is Fake because it was issued by staging below)
# 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
firewall settings
firewall-cmd --add-service https --zone=public --permanent
firewall-cmd --reload
The existing settings will be replaced with the certificate issued by Let's Encrypt.
/etc/httpd/conf.d/ssl.conf
#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
Let httpd load the settings.
systemctrl reload httpd
For checking, I will add --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
Probably, the updated one is published as below.
$ ls -1 /etc/letsencrypt/archive/example.com/cert*
/etc/letsencrypt/archive/example.com/cert1.pem <---First issued
/etc/letsencrypt/archive/example.com/cert2.pem <--- force-renewal
Shortly --force-renewal for confirmation.
/etc/cron.d/letsencrypt
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 <---First issued
/etc/letsencrypt/archive/example.com/cert2.pem <---Manual force-renewal
/etc/letsencrypt/archive/example.com/cert3.pem <---force with cron-renewal
If it's updated without any problems, check it once a week. If you don't fix it, you'll get stuck in the rate limit.
/etc/cron.d/letsencrypt
0 1 * * 1 root /bin/certbot renew --webroot-path /var/www/html/ --post-hook "systemctl reload httpd"
This is a script on github.
I'm adding a TXT record with regist and deleting a TXT record with delete.php.
The only difference between the two scripts is $ CERTBOT_ENV ['EDIT_CMD'] ='REGIST';
or $ CERTBOT_ENV ['EDIT_CMD'] ='DELETE';
.
regist.php
#!/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),);
//Set context resources
$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);
?>
delete.php
#!/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),);
//Set context resources
$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