最後更新: 2019-11-07
目錄
介紹
Let’s Encrypt CA issues short lived certificates (90 days).
Make sure you renew the certificates at least once in 3 months.
Homepage: https://letsencrypt.org/
Source: https://github.com/letsencrypt/letsencrypt
Automatic Certificate Management Environment (ACME)
The protocol, based on passing JSON-formatted messages over HTTPS ( RFC 8555 )
automatically obtain a browser-trusted certificate, without any human intervention
This is accomplished by running a certificate management agent on the web server.
Let’s Encrypt identifies the server administrator by public key.
The first time the agent software interacts with Let’s Encrypt,
it generates a new key pair and proves to the Let’s Encrypt CA that the server controls one or more domains.
# Challenges & validation:
A) Agent 建立用來與 Let’s Encrypt CA 溝通的 key pair
1. The agent asks the Let’s Encrypt CA what it needs to do in order to prove that it controls
2. The Let’s Encrypt CA also provides a nonce that the agent must sign with its private key pair
(to prove that it controls the key pair)
3. Agent creates a file on a specified path on the site.
4. Agent notifies the CA that it’s ready to complete validation
(Let’s Encrypt call the URL)
5. If the signature over the nonce is valid, and the challenges check out,
then the agent identified by the public key is authorized to do certificate management for example.com.
B) requesting, renewing, and revoking certificates
Agent send certificate management messages and sign them with the authorized key pair
(asks the Let’s Encrypt CA to issue a certificate for example.com with a specified public key.)
The agent signs the whole CSR with the authorized key for example.com
FAQ
What IP addresses does Let's Encrypt use to validate my web server?
We don't publish a list of IP addresses we use to validate,
because they may change at any time. In the future we may validate from multiple IP addresses at once.
安裝
Let's Encrypt 是透過 ACME 去認證 Website
certbot 是並中一個 ACME Client
https://certbot.eff.org/
Install on Centos7
- yum install python36 augeas-libs
- python3 -m venv /opt/certbot/
- /opt/certbot/bin/pip install --upgrade pip
- /opt/certbot/bin/pip install certbot
- ln -s /opt/certbot/bin/certbot /usr/bin/certbot
Check Version
certbot --version
certbot 1.20.0
Help
certbot --help
Key 的位置
All generated keys and issued certificates can be found in /etc/letsencrypt/live/$domain/
i.e.
ll /etc/letsencrypt/live/datahunter.org/
lrwxrwxrwx 1 root root 38 May 14 22:01 cert.pem -> ../../archive/datahunter.org/cert5.pem lrwxrwxrwx 1 root root 39 May 14 22:01 chain.pem -> ../../archive/datahunter.org/chain5.pem lrwxrwxrwx 1 root root 43 May 14 22:01 fullchain.pem -> ../../archive/datahunter.org/fullchain5.pem lrwxrwxrwx 1 root root 41 May 14 22:01 privkey.pem -> ../../archive/datahunter.org/privkey5.pem
* /etc/letsencrypt/live symlinks to the latest versions
* /etc/letsencrypt/archive and /etc/letsencrypt/keys contain all previous keys and certificates,
letsencrypt-auto(舊版)
Syntax:
letsencrypt-auto [SUBCOMMAND] [options] [-d domain] [-d domain] ...
SUBCOMMAND:
- run (default) # Obtain & install
- certonly # Obtain cert, but do not install it
- install
- revoke
- rollback
- config_changes
# Sign a single domain
letsencrypt-auto certonly --test-cert --dry-run --standalone \
-d datahunter.org -d www.datahunter.org
* --standalone # runs its own simple webserver to prove you control a domain)
* --certonly # 不用 automatic installation
* --dry-run # Test "renew" or "certonly" without saving any certificates to disk
* --test-cert # This will get certificates from staging server. (They won’t be valid in browsers)
建立 multiple domains cert.
certbot-auto -d www.datahunter.org -d datahunter.org
# Renewing
letsencrypt renew --cert-path example-cert.pem
i.e.
service nginx stop # 必須要放返 port 80 出黍先 renew 到
letsencrypt-auto renew --standalone --cert-path /etc/letsencrypt/live/datahunter.org/cert.pem
Auto renew script
/root/scripts/letsencrypt/cron_renew.sh
#!/bin/bash # for nginx web server LOGFILE="/var/log/letsencrypt/renew.log" certbot="/usr/sbin/certbot-auto" $certbot renew > $LOGFILE 2>&1
crontab -e
1 1 1 */2 * /root/scripts/letsencrypt/cron_renew.sh > /dev/null
Notes
由於 renew 時會使用 /etc/letsencrypt/renewal/datahunter.org.conf 內的 settings, 所以不用加
--pre-hook "service nginx stop" \ --post-hook "service nginx start" \ --standalone --preferred-challenges http \ --cert-path $CERT \
# For testing
--force-renewal # that will force a renewal even if your cert isn’t close to expiry.
--dry-run # will fetch a certificate from staging server.
P.S.
它會根據 /etc/letsencrypt/renewal/datahunter.org.conf 去 renew
# renew_before_expiry = 30 days cert = /etc/letsencrypt/live/datahunter.org/cert.pem privkey = /etc/letsencrypt/live/datahunter.org/privkey.pem chain = /etc/letsencrypt/live/datahunter.org/chain.pem fullchain = /etc/letsencrypt/live/datahunter.org/fullchain.pem version = 0.8.1 # Options and defaults used in the renewal process [renewalparams] installer = None authenticator = standalone account = ???
# Revoking a Certificate
# menu of all your managed certificates
letsencrypt revoke
# You may also revoke a particular certificate
letsencrypt revoke --cert-path example-cert.pem
# revoke all certificates with a particular key.
letsencrypt revoke --key-path example-key.pem
cli.ini
/etc/letsencrypt/cli.ini
letsencrypt-auto --config cli.ini
# Use a 4096 bit RSA key instead of 2048
rsa-key-size = 4096
# Uncomment and update to register with the specified e-mail address
# email = [email protected]
log file
/var/log/letsencrypt/letsencrypt.log
nginx ssl configure
server { listen 443 ssl http2; ssi on; ssl_certificate /etc/letsencrypt/live/datahunter.org/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/datahunter.org/privkey.pem; ssl_protocols TLSv1.1 TLSv1.2; ssl_prefer_server_ciphers on; ssl_session_cache shared:SSL:10m; ssl_session_timeout 15m; ... }
Certbot
新版由 letsencrypt command 改成了 certbot command
Help
certbot-auto --help
certbot-auto --help all
Plugins Type (一共有兩類)
certonly - obtain a cert
install - install a cert (modify your webserver’s configuration)
Usage: renew
renew
attempts to renew any previously-obtained certificates that expire in less than 30 days.
它會 read /etc/letsencrypt/renewal/*.conf 內的設定再去 renew domain
--cert-path CERT_PATH # Path to where cert is saved (with auth --csr), installed from, or revoked.
(default: None)
--standalone # To obtain a cert using a “standalone” webserver
--preferred-challenges http/tls-sni # Port 80 / 443
--force-renewal # msg: "The following certs are not due for renewal yet:"
# If a certificate already exists for the requested domains,
# renew it now, regardless of whether it is near expiry.
i.e.
certbot-auto renew
hook
The renew command includes hooks for running commands or scripts before or after a certificate is renewed.
certbot renew --pre-hook "service nginx stop" --post-hook "service nginx start"
--pre-hook
only be called if a certificate is actually to be obtained/renewed.
--post-hook
to restart any servers that were stopped by --pre-hook.
* the certonly command attempts to renew that specific(-d) certificate.
* certbot renew exit status will only be 1 if a renewal attempt failed.
Checking
# view a list of the certificates Certbot knows
certbot-auto certificates
Found the following certs: Certificate Name: datahunter.org Domains: datahunter.org mail.datahunter.org Expiry Date: 2017-07-02 04:21:00+00:00 (VALID: 87 days) Certificate Path: /etc/letsencrypt/live/datahunter.org/fullchain.pem Private Key Path: /etc/letsencrypt/live/datahunter.org/privkey.pem
Toubleshoot
T1: “Error: couldn’t get currently installed version for letsencrypt”
S1: mv /root/.local/share /root/.local/share.bak
Scripts
create cert (certonly)
create-cert.sh
#!/bin/sh certbot="/usr/sbin/certbot-auto" $certbot certonly --pre-hook "service nginx stop" \ --post-hook "service nginx start" \ --standalone --preferred-challenges http \ -d datahunter.org \ -d www.datahunter.org
renew by cron job
cron_renew.sh
#!/bin/sh LOGFILE="/var/log/letsencrypt/renew.log" certbot="/usr/sbin/certbot-auto" CERT="/etc/letsencrypt/live/datahunter.org/cert.pem" $certbot renew --pre-hook "service nginx stop" \ --post-hook "service nginx start" \ --standalone --preferred-challenges http \ --cert-path $CERT > $LOGFILE 2>&1
# cron job
1 1 1 * * /root/scripts/letsencrypt/cron_renew.sh
P.S.
重新建立 Certificate
Step1: backup 以下 Folder 內的 Folder
- archive
- live
- renewal
Verify
certbot-auto certificates
沒有 output 再重新申請
certbot example(簡易)
# certonly: make the changes to your Apache configuration by hand
# --apache: Apache plugin
# (get a certificate for you and edit your Apache configuration automatically to serve it)
certbot-auto certonly --apache -d datahunter.org
會 renew 以下 file
/etc/letsencrypt/live/datahunter.org/cert.pem /etc/letsencrypt/live/datahunter.org/chain.pem /etc/letsencrypt/live/datahunter.org/privkey.pem /etc/letsencrypt/live/datahunter.org/fullchain.pem
設定 renew cron jobs
# 測試 renew
certbot-auto renew --dry-run
# cron jobs
# Monthly 1 1 1 * * certbot-auto renew &> /dev/null
Letsencrypt validate server IP
letsencrypt don't publish a list of IP addresses we use to validate, because they may change at any time.
outbound1.letsencrypt.org 66.133.109.36
outbound2.letsencrypt.org 64.78.149.164
Wildcard SSL Certificate
申請
1. 執行 CLi
certbot-auto certonly --manual \
--preferred-challenges=dns \
-d "datahunter.org" -d "*.datahunter.org"
2. 填資料
然後跟著指示輸入電郵及回答一些問題.
3. 建立 txt record
最後會 Certbot 會顯示一個 TXT Record
i.e.
Please deploy a DNS TXT record under the name _acme-challenge.datahunter.org with the following value: nbjrc1zj8gXXLgmbw-zc-7mD-iRXghlodenJ_dx00bo Before continuing, verify the record is deployed.
dig -t txt _acme-challenge.datahunter.org
Remark
Only the dns-01 challenge is accepted for wildcard certificates
(webroot and standalone authenticators don't support this method)
Windows acme client
Tools: win-acme (https://pkisharp.github.io/win-acme/)
功能
- A very simple text interface to create
- DNS, HTTP and TLS validation
- Completely unattended operation from the command line
Package
if you want to download or develop extra plugins,
you should get the pluggable version instead of the trimmed one.
Validation
The validation request is always made to port 80, that cannot be changed.
The ACME server does follow 301/302 redirects.
The client has to make sure that when the ACME server makes a request to
http://sub.example.com/.well-known/acme-challenge/x
the content of the HTTP response will be y with some specific headers set as well.
Config
Apache
Alias /.well-known/ "C:/vhosts/ssl/.well-known/" <Directory "C:/vhosts/ssl/"> Options -FollowSymlinks -Includes -ExecCGI Order allow,deny Allow from all DirectoryIndex index.php index.html index.htm </Directory>
Win-acme.exe
Question
Enter the path we created in step 4. In my case: C:\xampp\htdocs
Note
actual root and not the path to "/.well-known/acme-challenge".
Win-acme is assuming you haven't got this far and will attempt to create these folders if they don't exist.
Command line arguments
--renew # Renew any certificates that are due.
--force # Force renewal on all scheduled certificates when used together with --renew.
--list # List all created renewals in unattended mode.
Path For Verify(Nginx)
.well-known/pki-validation/
location ^~ "/.well-known/pki-validation" { alias C:/nginx/root/well-known/pki-validation/; default_type "text/plain"; allow all; }
Manual get Cert
# obtain a certificate running certbot on a machine other than your target webserver
certbot-auto certonly --manual --preferred-challenges http -d datahunter.org
Verfiy By File(Nginx)
Plugin: webroot
Obtains a cert by writing to the webroot directory of an already running webserver.
The webroot plugin works by creating a temporary file for each of your requested domains in
${webroot-path}/.well-known/{acme-challenge}
“web root” = website top-level directory
設定
mkdir /var/www/letsencrypt/.well-known/acme-challenge -p
mkdir /etc/nginx/snippets; cd /etc/nginx/snippets
letsencrypt-acme-challenge.conf
location ^~ /.well-known/acme-challenge/ { default_type "text/plain"; root /var/www/letsencrypt; allow all; } # Hide /acme-challenge subdirectory and return 404 on all requests. # It is somewhat more secure than letting Nginx return 403. # Ending slash is important! location = /.well-known/acme-challenge/ { return 404; }
nginx.conf
server {
listen 80;
# Include location directive for Let's Encrypt ACME Challenge
include snippets/letsencrypt-acme-challenge.conf;
...
}
nginx -s reload
測試
touch /var/www/letsencrypt/.well-known/acme-challenge/test.txt
curl -I http://URL/.well-known/acme-challenge/test.txt
certbot-auto renew --test-cert --dry-run --webroot -w /var/www/letsencrypt
Renew Certificate without Config
certbot-auto certonly \ --webroot -w /var/www/letsencrypt nginx -s reload