Linux工具-certbot
参考文献
- https://certbot.eff.org/instructions?ws=nginx&os=ubuntufocal
- https://eff-certbot.readthedocs.io/en/stable/using.html
- ssl 证书;certbot+nginx+docker
- docker部署certbot与nginx来获取ssl证书添加https及自动更新
- letsencrypt证书-管理工具certbot
certbot
1 | # certbot --help |
申请证书
1 | certbot certonly -d 要申请的域名 |
查看申请的证书信息
1 | # certbot certificates |
手动续期
1 | # certbot renew |
certbot
插件
Plugin |
Auth |
Inst |
Notes |
Challenge Types (及端口) |
---|---|---|---|---|
apache |
是 | 是 | 自动获取并安装证书 | tls-sni-01 (443) |
webroot |
是 | 否 | 已有运行的服务,通过验证 webroot 目录获取证书 | http-01 (80) |
nginx |
是 | 是 | 使用 nginx 自动获取和安装证书 | tls-sni-01 (443) |
standalone |
是 | 否 | 建立一个独立的 Web 服务,需要可用的 80 或 443 端口,适用于没有类似 nginx 和 apache 的服务环境 | http-01 (80) 或 tls-sni-01 (443) |
DNS plugins |
是 | 否 | 通过修改 DNS 服务器的 TXT记录来获取证书,支持通配符证书,仅可通过此方式获取 | dns-01 (53) |
manual |
是 | 否 | 通过手动操作来获取证书,支持添加定制脚本完成任务 | http-01 (80), dns-01 (53), 或 tls-sni-01 (443) |
- 使用
standalone
插件,那么需要使用80
和443
端口,因为要建一个监听这些端口的服务,注意端口占用问题 - 使用
webroot
方式,如果你使用了nginx
,那么你需要更改一些nginx配置,确保能验证你对该域名的所有权限
webroot
1 | certbot certonly --webroot |
-
certonly
: 只获取证书,不安装 -
--webroot
: 定义使用的插件方法是webroot
-
--webroot-path
: 简写为-w
表示目录位置 -
通过
webroot
的方式运行后,会在两个地方产生文件:-
一个是在命令行配置的
--webroot-path
指定目录下产生临时文件,用于http验证。 -
一个是验证成功会产生存放证书的文件,默认是在
/etc/letsencrypt/live/你的域名
目录下,需要注意的是这些证书是个软链接,对应着../archive
下,所以我们在做volume
映射时不要只映射到live
这个目录,而是要映射/etc/letsencrypt
这个目录,否则无法找到相关的证书文件。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17# ll /etc/letsencrypt/
total 56
drwxr-xr-x 9 root root 4096 Sep 26 14:43 ./
drwxr-xr-x 97 root root 4096 Sep 25 15:02 ../
drwx------ 4 root root 4096 Sep 26 11:29 accounts/
drwx------ 3 root root 4096 Sep 25 15:13 archive/
-rw-r--r-- 1 root root 121 Feb 11 2019 cli.ini
drwxr-xr-x 2 root root 4096 Sep 26 13:25 csr/
drwx------ 2 root root 4096 Sep 26 13:25 keys/
drwx------ 3 root root 4096 Sep 25 15:13 live/
-rw-r--r-- 1 root root 1143 Sep 25 15:02 options-ssl-nginx.conf
drwxr-xr-x 2 root root 4096 Sep 25 15:13 renewal/
drwxr-xr-x 5 root root 4096 Sep 7 14:02 renewal-hooks/
-rw-r--r-- 1 root root 424 Sep 25 15:02 ssl-dhparams.pem
-rw-r--r-- 1 root root 64 Sep 25 15:02 .updated-options-ssl-nginx-conf-digest.txt
-rw-r--r-- 1 root root 64 Sep 25 15:02 .updated-ssl-dhparams-pem-digest.txt1
2
3
4
5
6
7
8
9
10
11# ll /etc/letsencrypt/live/xxx.com/
total 16
drwxr-xr-x 3 root root 4096 Sep 26 13:07 ./
drwx------ 3 root root 4096 Sep 25 15:13 ../
lrwxrwxrwx 1 root root 34 Sep 25 15:13 cert.pem -> ../../archive/xxx.com/cert1.pem
lrwxrwxrwx 1 root root 35 Sep 25 15:13 chain.pem -> ../../archive/xxx.com/chain1.pem
lrwxrwxrwx 1 root root 39 Sep 25 15:13 fullchain.pem -> ../../archive/xxx.com/fullchain1.pem
drwxr-xr-x 2 root root 4096 Sep 26 13:07 private.pem/
lrwxrwxrwx 1 root root 37 Sep 25 15:13 privkey.pem -> ../../archive/xxx.com/privkey1.pem
-rw-r--r-- 1 root root 682 Sep 25 15:13 README
-
具体验证机制
-
验证的时候会自动向
${webroot-path}/.well-known/acme-challenge
目录下写一个临时文件,然后会发送一个请求,去验证是否可以正常访问,访问的请求类似下面1
222.64.78.214 - - [26/Sep/2023:02:43:56 +0000] "GET /.well-known/acme-challenge/FHGV2yVHs0q5dJFXBGjWkwOcIqXlP9oNyy5srR4zGR8 HTTP/1.1" 304 0 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.0.0 Safari/537.36" "-"
-
使用
Nginx
方式配置如下:1
2
3
4
5
6
7
8
9
10
11
12server {
listen 80;
server_name test.com;
location ^~ /.well-known/acme-challenge/ {
alias /var/www/challenges/;
try_files $uri = 404;
}
location / {
return 301 https://$host$request_uri;
}
}
-
standalone
-
该插件会启动一个web服务器,使用
--preferred-challenges http
参数的话,对应使用80端口,使用--preferred-challenges tls-sni
参数对应使用443端口.1
sudo certbot certonly --standalone -d example.com -d www.example.com
DNS plugins
manual
-
该方法允许你通过交互的方式获取证书,可以在其它服务器上运行,可以选择
http
,dns
和tls-sni
方式中的任意一种。 -
比如使用
DNS
的方式,会要求你在验证过程中手动填写TXT DNS
的记录,然后继续,验证成功后会获取证书。1
certonly -d *.test.cn -d test.cn --manual --preferred-challenges dns --server https://acme-v02.api.letsencrypt.org/directory
-
上面是手动的方式申请,中间需要人工干预,去DNS服务商填写
TXT
记录。还可以使用脚本帮助你完成一些验证,可以使用--manual-auth-hook
和--manual-cleanup-hook
参数
Challenge Types
HTTP-01 challenge
-
通过
http-01
请求验证,会向http://你的域名/.well-known/acme-challenge/
发送一条请求- 使用
Nginx
方式,配置如下:
1
2
3
4
5
6
7
8
9
10
11server {
listen 80;
server_name test.com;
location ^~ /.well-known/acme-challenge/ {
root /var/www/challenges/;
}
location / {
return 301 https://$host$request_uri;
}
}/usr/local/www
目录下则存放对应的Token
文件,如http://test.com/.well-known/acme-challenge/o9d5Q0lWljlO9ENwmuKwaukg9al1AQymWdW_Ww3gSng
- 使用
-
执行命令
1
certbot certonly --webroot --webroot-path /var/www/challenges -d test.com
-
HTTP-01
验证最多接受 10 次重定向.只接受目标为http:
或https:
且端口为 80 或 443 的重定向.不目标为 IP 地址的重定向.当被重定向到 HTTPS 链接时,不会验证证书是否有效(因为验证的目的是申请有效证书,所以它可能会遇到自签名或过期的证书)。 -
HTTP-01
验证只能使用 80 端口.因为允许客户端指定任意端口会降低安全性,所以 ACME 标准已禁止此行为。
DNS-01 challenge
-
通过
dns-01
解析,需要在域名解析中增加一条_acme-challenge.你的域名
的TXT
记录用于验证 -
执行命令
1
certbot certonly --preferred-challenges dns --manual -d *.holelin.cn --server https://acme-v02.api.letsencrypt.org/directory
示例
使用docker+nginx+certbot
方式配置证书
-
docker-compose.yaml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27version: '3.1'
services:
nginx:
image: nginx
container_name: nginx
ports:
- 80:80
- 443:443
restart: always
volumes:
# Nginx配置文件
- /root/nginx/conf.d:/etc/nginx/conf.d/:ro
# Nginx日志文件
- /root/nginx/logs:/usr/local/logs
# http验证目录,可设置为只读(ro)
- /root/nginx/www:/usr/local/www:ro
# certbot生成的证书位置
- /root/nginx/ssl:/etc/nginx/ssl:ro
certbot:
image: certbot/certbot:latest
container_name: certbot
volumes:
# http验证目录,可设置rw可写,与nginx容器对应的宿主机目录时一致的
- /root/nginx/www:/var/www/certbot:rw
# 证书位置,同上,注意不要只映射到live,而是它的上一级
- /root/nginx/ssl:/etc/letsencrypt/:rw -
nginx
的配置xxx.com.conf
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30server {
listen 80;
server_name xxxx.com;
#配置http验证可访问
location ^~ /.well-known/acme-challenge/ {
#此目录都是nginx容器内的目录,对应宿主机volumes中的http验证目录,而宿主机的又与certbot容器中命令--webroot-path指定目录一致,从而就整个串起来了,解决了http验证问题
root /usr/local/www;
}
location / {
return 301 https://$host$request_uri;
}
}
server {
listen 443 ssl;
server_name xxx.com;
error_log /usr/local/logs/error.log;
access_log /usr/local/logs/access.log main;
ssl_certificate /etc/nginx/ssl/live/xxx.com/fullchain.pem;
ssl_certificate_key /etc/nginx/ssl/live/xxx.com/privkey.pem;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:HIGH:!aNULL:!MD5:!RC4:!DHE;
ssl_prefer_server_ciphers on;
location / {
root /usr/local/xxx/test;
index index.html;
}
}-
映射关系
目录 certbot
宿主机 nginx
http
验证目录/var/www/certbot
/root/nginx/www
/usr/local/www
证书目录 /etc/letsencrypt
/root/nginx/ssl
/etc/nginx/ssl
-
-
操作步骤
-
编写好
docker-compose.yaml
文件 -
执行
1
docker-compose -f docker-compose.yaml run --rm certbot certonly --webroot --webroot-path /var/www/certbot -d xxx.com
-
执行完成后,
certbot
生成证书的目录下live
目录下就会有对应域名文件夹,文件夹中就有域名证书文件1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19# ll
total 28
drwxr-xr-x 7 root root 4096 Sep 26 14:21 ./
drwxr-xr-x 8 root root 4096 Sep 26 14:12 ../
drwx------ 3 root root 4096 Sep 26 14:12 accounts/
drwx------ 3 root root 4096 Sep 26 14:13 archive/
drwx------ 3 root root 4096 Sep 26 14:13 live/
drwxr-xr-x 2 root root 4096 Sep 26 14:13 renewal/
drwxr-xr-x 5 root root 4096 Sep 26 13:56 renewal-hooks/
# ll live/xxx.com/
total 12
drwxr-xr-x 2 root root 4096 Sep 26 14:13 ./
drwx------ 3 root root 4096 Sep 26 14:13 ../
lrwxrwxrwx 1 root root 34 Sep 26 14:13 cert.pem -> ../../archive/xxx.com/cert1.pem
lrwxrwxrwx 1 root root 35 Sep 26 14:13 chain.pem -> ../../archive/xxx.com/chain1.pem
lrwxrwxrwx 1 root root 39 Sep 26 14:13 fullchain.pem -> ../../archive/xxx.com/fullchain1.pem
lrwxrwxrwx 1 root root 37 Sep 26 14:13 privkey.pem -> ../../archive/xxx.com/privkey1.pem
-rw-r--r-- 1 root root 692 Sep 26 14:13 README -
修改配置
Nginx
文件 -
检查Nginx配置,重载配置
1
2
3
4# 检测配置nginx文件是否有问题
docker-compose exec nginx nginx -t
# 重载配置
docker-compose exec nginx nginx -s reload -
添加定时任务
1
2# 1、切换到docker-compose.yml所在目录;2、然后更新证书,只有距离过期时间30天内才会真正成功;3、然后重载nginx使新证书生效
0 0 1,15 * * /usr/local/bin/docker-compose -f /home/xxxx/script/docker-compose.yaml run --rm certbot renew && /usr/local/bin/docker-compose exec nginx nginx -s reload
-