从 HTTP-01 到 DNS-01:我的 ACME 挑战实践之路

HTTP-01

前提:

点击展开:安装 certbot 命令
1
2
3
4
sudo apt update
sudo apt install snapd
sudo snap install --classic certbot
sudo ln -s /snap/bin/certbot /usr/bin/certbot
点击展开:安装 Nginx 命令
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 安装必备软件包
sudo apt update
sudo apt install -y curl gnupg2 ca-certificates lsb-release ubuntu-keyring
# 导入 Nginx 签名密钥
curl https://nginx.org/keys/nginx_signing.key | gpg --dearmor | sudo tee /usr/share/keyrings/nginx-archive-keyring.gpg >/dev/null
# 验证密钥指纹(确认输出中包含 573BFD6B3D8FBC641079A6ABABF5BD827BD9BF62)
gpg --dry-run --quiet --no-keyring --import --import-options import-show /usr/share/keyrings/nginx-archive-keyring.gpg
# 添加稳定版软件源
echo "deb [signed-by=/usr/share/keyrings/nginx-archive-keyring.gpg] http://nginx.org/packages/ubuntu $(lsb_release -cs) nginx" | sudo tee /etc/apt/sources.list.d/nginx.list
# 设置软件源优先级
echo -e "Package: *\nPin: origin nginx.org\nPin: release o=nginx\nPin-Priority: 900" | sudo tee /etc/apt/preferences.d/99nginx
# 更新软件包并安装 Nginx
sudo apt update
sudo apt install -y nginx
# 启用并启动 Nginx 服务
sudo systemctl enable nginx
sudo systemctl start nginx
# 查看 Nginx 状态和版本
sudo systemctl status nginx
sudo nginx -v

域名配置

在 DNS 提供商处(如: 阿里云)添加一条 A 记录, 将你的域名指向服务器的 IPv4 地址。

Nginx 配置示例

sudo vim /etc/nginx/conf.d/default.conf, 写入以下内容, 修改Your-domain为你的域名

1
2
3
4
5
6
7
8
9
10
11
12
13
14
server {
listen 80;
server_name Your-domain;

location / {
root /usr/share/nginx/html;
index index.html index.htm;
}

error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
}

保存后, 测试配置并重载 Nginx:

1
sudo nginx -t && sudo systemctl reload nginx

获取 SSL 证书

1
sudo certbot --nginx # 自动配置nginx

直接访问 https://Your-domain 即可

注: 请确保防火墙开放 80 和 443 端口。

DNS-01(阿里云为例)

前提:

点击展开:安装 acme.sh 命令
1
2
3
4
5
curl https://get.acme.sh | sh -s email=my@example.com
# 如果你的安装服务器位于中国大陆境内, 访问 github 可能会不成功, 使用下面的
git clone https://gitee.com/neilpang/acme.sh.git
cd acme.sh
./acme.sh --install -m my@example.com

域名配置

在 DNS 提供商处(如: 阿里云)添加一条 A 记录, 将你的域名指向服务器的 IPv4 地址。

DNS API 使用说明

参考文档:DNS API 支持列表

使用阿里云 DNS API 自动签发证书

获取 RAM API 密钥

登录阿里云控制台,进入 RAM 子用户管理页面,创建或选择已有子用户,并为其授予 AliyunDNSFullAccess 权限。获取该用户的 AccessKey IDAccessKey Secret

设置环境变量:

1
2
export Ali_Key="your-access-key-id"
export Ali_Secret="your-access-key-secret"

把 example.com 换为你的域名

获取证书

1
acme.sh --issue --dns dns_ali -d example.com -d *.example.com --server letsencrypt # --server 指定CA

复制证书到 nginx 目录(解决 acme.sh 无权限问题)

  1. 创建用户 SSL 目录并安装证书
1
2
3
4
5
6
7
8
# 创建用户 SSL 目录
mkdir -p ~/ssl

# 使用 acme.sh 安装证书到用户目录
acme.sh --install-cert -d example.com \
--key-file ~/ssl/example.com.key \
--fullchain-file ~/ssl/example.com.crt \
--reloadcmd "sudo systemctl reload nginx"
  1. 创建系统 SSL 目录并设置软链接
1
2
3
4
5
6
7
8
9
# 创建系统 SSL 目录(需要 sudo)
sudo mkdir -p /etc/nginx/ssl

# 设置用户目录权限
chmod 755 ~/ssl
chmod 644 ~/ssl/*

# 创建软链接(需要 sudo)
sudo ln -sf ~/ssl/* /etc/nginx/ssl/
  1. 配置 sudo 免密码重启 nginx
1
2
# 编辑 sudoers 配置
sudo visudo -f /etc/sudoers.d/nginx-reload

在文件中添加以下内容:

1
2
# 允许当前用户无需密码重启 nginx
username ALL=(root) NOPASSWD: /bin/systemctl reload nginx

注意:将 username 替换为您的实际用户名。

  1. 重新运行
1
2
3
4
acme.sh --install-cert -d example.com \
--key-file ~/ssl/example.com.key \
--fullchain-file ~/ssl/example.com.crt \
--reloadcmd "sudo systemctl reload nginx"

Nginx 配置示例

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
30
server {
server_name example.com *.example.com;

location / {
root /usr/share/nginx/html;
index index.html index.htm;
}

error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}

listen 443 ssl; # managed by Certbot
ssl_certificate /etc/nginx/ssl/example.com.cert.pem;
ssl_certificate_key /etc/nginx/ssl/example.com.key.pem;
ssl_session_cache shared:le_nginx_SSL:10m;
ssl_session_timeout 1440m;
ssl_session_tickets off;

ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers off;

ssl_ciphers "ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384";
}
server {
listen 80;
server_name example.com *.example.com;
return 301 https://$server_name$request_uri;
}

acme.sh 默认会在证书到期前 30 天自动尝试续签。

测试

SSL Labs

测试结果在 A 就 🆗 了