Let's Encrypt 证书
macOS
在 macOS 上可以直接使用 Homebrew 安装 Certbot,并按照以下步骤生成 Let's Encrypt 证书并配置到 Spring Boot 项目中。
1. 安装 Certbot
在 macOS 上使用 Homebrew 安装 Certbot:
bash
brew install certbot
2. 使用 Certbot 生成 SSL 证书
生成证书前,请确保 macOS 的防火墙允许 Certbot 的临时服务器监听 80 端口(Certbot 使用此端口验证域名归属)。运行以下命令生成证书:
bash
sudo certbot certonly --standalone -d yourdomain.com
Certbot 会自动生成证书并将其保存在 /etc/letsencrypt/live/yourdomain.com/
中,其中包含以下文件:
fullchain.pem
: 证书文件privkey.pem
: 私钥文件
3. 将 PEM 证书转换为 PKCS12 格式
Spring Boot 不能直接使用 PEM 文件格式,因此需要将它们转换为 PKCS12 格式:
bash
sudo openssl pkcs12 -export \
-in /etc/letsencrypt/live/yourdomain.com/fullchain.pem \
-inkey /etc/letsencrypt/live/yourdomain.com/privkey.pem \
-out /etc/letsencrypt/live/yourdomain.com/keystore.p12 \
-name tomcat \
-CAfile /etc/letsencrypt/live/yourdomain.com/chain.pem \
-caname root
在此过程中,系统会要求设置 PKCS12 文件的密码,这个密码会在 Spring Boot 配置中使用。
4. 配置 Spring Boot 使用 HTTPS
在 application.properties
或 application.yml
中配置 Spring Boot 使用生成的 keystore.p12
文件:
application.properties
properties
server.port=443
server.ssl.enabled=true
server.ssl.key-store=/etc/letsencrypt/live/yourdomain.com/keystore.p12
server.ssl.key-store-password=your_keystore_password # PKCS12 文件的密码
server.ssl.key-store-type=PKCS12
server.ssl.key-alias=tomcat
5. 设置 HTTP 到 HTTPS 的重定向(可选)
可以将 HTTP 请求重定向到 HTTPS,以确保所有流量使用加密通道。以下是配置 HTTP 到 HTTPS 重定向的示例代码:
java
import org.eclipse.jetty.server.ServerConnector;
import org.eclipse.jetty.util.ssl.SslContextFactory;
import org.springframework.boot.web.embedded.jetty.JettyServerCustomizer;
import org.springframework.boot.web.embedded.jetty.JettyServletWebServerFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class JettyHttpsRedirectConfig {
@Bean
public JettyServletWebServerFactory jettyServletWebServerFactory() {
JettyServletWebServerFactory factory = new JettyServletWebServerFactory();
factory.addServerCustomizers(server -> {
// 设置 HTTP 连接器
ServerConnector httpConnector = new ServerConnector(server);
httpConnector.setPort(80); // HTTP 端口
server.addConnector(httpConnector);
// 设置 HTTPS 连接器
SslContextFactory.Server sslContextFactory = new SslContextFactory.Server();
sslContextFactory.setKeyStorePath("/etc/letsencrypt/live/yourdomain.com/keystore.p12");
sslContextFactory.setKeyStorePassword("your_keystore_password");
ServerConnector httpsConnector = new ServerConnector(server, sslContextFactory);
httpsConnector.setPort(443); // HTTPS 端口
server.addConnector(httpsConnector);
});
return factory;
}
}
6. 自动续期
Let's Encrypt 证书有效期为 90 天,可以通过以下命令配置自动续期:
bash
sudo certbot renew --dry-run
将此命令添加到 crontab 中,定期自动续期:
bash
crontab -e
添加如下行(每天凌晨尝试续期一次):
bash
0 3 * * * /usr/local/bin/certbot renew --quiet
这样,每当证书临近到期,Certbot 会自动续订证书。
Centos
在 CentOS 8 上使用 Let's Encrypt 证书的流程通常包括以下步骤:
1. 安装 Certbot
Certbot 是用于获取 Let's Encrypt 证书的工具。
安装 Certbot:
- 更新系统包:
bash
# 注意 可以跳过 dnf update,直接安装 Certbot
# 直接更新 Certbot 及其相关依赖,而不是更新整个系统
sudo dnf install --refresh certbot python3-certbot-nginx
# 更新安全补丁
sudo dnf update --security -y
# 如果 Certbot 依赖的包需要升级,可以单独指定相关包:
sudo dnf update -y certbot python3-certbot python3-requests
# --------------------------------------------------------- #
# 更新整个系统
sudo dnf update -y
- 启用 EPEL 存储库:
bash
# 可以不开启
# EPEL 是由 Fedora 项目维护的一个额外包存储库,提供稳定的开源软件包,用于 RHEL 系列操作系统(包括 CentOS、Rocky Linux、AlmaLinux 等)。
sudo dnf install epel-release -y
# 如果遇到下面的报错,则需要启用 EPEL
Package python3-requests available, but not installed.
No match for argument: python3-requests
Error: No packages marked for upgrade.
- 安装 Certbot 和相关插件: 如果您使用的是 Apache:
bash
sudo dnf install certbot python3-certbot-apache -y
如果您使用的是 Nginx:
bash
sudo dnf install certbot python3-certbot-nginx -y
2. 获取 SSL 证书
为域名申请证书:
- 停止 Apache/Nginx 服务(如果需要): 如果您计划使用 standalone 模式,请先停止 Web 服务器:
bash
sudo systemctl stop httpd
sudo systemctl stop nginx
- 运行 Certbot:
- 使用 Apache 插件:
bash
sudo certbot --apache
- 使用 Nginx 插件:
bash
sudo certbot --nginx
- 使用 Standalone 模式:
bash
sudo certbot certonly --standalone -d example.com -d www.example.com
Certbot 将自动生成并安装 SSL 证书,并更新 Web 服务器配置。
- 验证证书: 您的证书将被保存在
/etc/letsencrypt/live/<your-domain>/
。- 主要文件:
fullchain.pem
: 完整的证书链。privkey.pem
: 私钥。
- 主要文件:
如果无法绑定80端口,可以使用下面的方法申请证书
2.1 使用 DNS 验证(无需绑定 80 端口)
DNS 验证模式不需要开放任何端口,也无需提供 .well-known/acme-challenge
路径。这种方式尤其适合无法绑定 80 端口或使用动态域名的场景。
操作步骤:
- 运行 Certbot 命令:
bash
sudo certbot certonly --manual --preferred-challenges dns
- 按提示设置 DNS 记录 : Certbot 会提供一段字符串,让你将其作为
_acme-challenge.<your-domain>
的 TXT 记录添加到域名的 DNS 配置中。配置方法见问题:DNS验证错误 - 完成验证后安装证书: 验证通过后,你会获得证书文件,可以直接配置到 Spring Boot。
3. 配置 Web 服务器
Certbot 的插件(如 --apache
或 --nginx
)会自动配置 HTTPS。如果您使用 Standalone 模式,则需要手动配置。
手动配置示例(以 Nginx 为例):
在 Nginx 配置文件中,添加以下内容:
nginx
server {
listen 80;
server_name example.com www.example.com;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl;
server_name example.com www.example.com;
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
location / {
root /var/www/html;
index index.html;
}
}
重新加载 Nginx 配置:
bash
sudo systemctl reload nginx
配置 Spring Boot 使用 HTTPS
配置方法见:macOS 第三段落(将 PEM 证书转换为 PKCS12 格式)
4. 设置自动续期
Let's Encrypt 证书有效期为 90 天,Certbot 会自动续期。
测试自动续期:
bash
sudo certbot renew --dry-run
配置自动续期:
Certbot 在安装时会自动创建续期任务。可以通过以下命令检查:
bash
sudo systemctl list-timers
如果未创建,可以手动添加 cron 任务:
bash
echo "0 0,12 * * * root certbot renew --quiet && systemctl reload nginx" | sudo tee -a /etc/crontab > /dev/null
5. 验证 HTTPS
通过浏览器访问 https://your-domain.com
验证 HTTPS 是否正常工作。
完成后,您的 CentOS 8 服务器将成功启用 Let's Encrypt SSL 证书,提供安全的 HTTPS 服务。
自签名证书
使用自签名证书为 localhost 配置 HTTPS
如果你只是在本地开发环境中需要 HTTPS,你可以为 localhost
生成一个自签名证书。以下是生成并配置自签名证书的步骤:
1. 生成自签名证书
首先,使用 openssl
生成自签名证书和私钥。
在终端中运行以下命令:
bash
# 生成私钥
openssl genpkey -algorithm RSA -out localhost.key
# 生成自签名证书
openssl req -new -x509 -key localhost.key -out localhost.crt -days 3650 -subj "/CN=localhost"
# 使用公网域名或ip
openssl req -x509 -new -nodes -key server.key -out server.crt -days 365 \
-subj "/C=US/ST=California/L=San Francisco/O=My Company/OU=IT Department/CN=<公网 IP 或 域名>" \
-extensions v3_req -config <(echo "[req]"; echo distinguished_name=req; echo "[v3_req]"; echo subjectAltName=DNS:<公网 IP 或 域名>)
这将生成以下两个文件:
localhost.key
:私钥localhost.crt
:证书
2. 将证书和私钥转换为 PKCS12 格式
Spring Boot 需要使用 PKCS12 格式的证书,因此我们需要将 .crt
和 .key
文件转换为 .p12
文件。
bash
openssl pkcs12 -export -in localhost.crt -inkey localhost.key -out localhost.p12 -name tomcat
这将生成 localhost.p12
文件,你可以在 Spring Boot 中使用它。
3. 配置 Spring Boot 使用自签名证书
接下来,配置 Spring Boot 使用生成的自签名证书。打开 application.properties
或 application.yml
并添加以下配置:
application.properties
properties
server.port=8443
server.ssl.enabled=true
server.ssl.key-store=classpath:localhost.p12
server.ssl.key-store-password=your_password_here
server.ssl.key-store-type=PKCS12
server.ssl.key-alias=tomcat
你可以将 localhost.p12
文件放置在 src/main/resources
目录下,或者指定文件的绝对路径。
4. 允许浏览器信任自签名证书(开发环境)
由于是自签名证书,浏览器会警告你不受信任。为了避免每次启动时都看到警告,你可以将证书添加到浏览器或操作系统的信任存储中。
将证书添加到 macOS 的信任存储
- 打开
Keychain Access
(钥匙串访问)应用。 - 拖动
localhost.crt
文件到Keychain Access
中。 - 在"系统"钥匙串中找到该证书,并双击它。
- 打开证书详情,展开"信任"设置,选择"始终信任"。
- 关闭并保存。
这样,浏览器就不会再显示警告了。
5. 访问本地 HTTPS 服务
在浏览器中,你可以通过 https://localhost:8443
访问你的服务。请注意,由于使用的是自签名证书,浏览器可能会提示"连接不安全",你需要手动确认继续访问。
问题
访问服务器报错: Invalid SNI
bash
STATUS: 400
MESSAGE: Invalid SNI
常见原因
- 主机名错误 :
- 发送请求时,SNI 的主机名和目标服务器不匹配。
- 比如使用了 IP 地址而不是域名。
- 例如:生成证书时使用的localhost,浏览器访问服务器时使用的是域名或公网ip
- 不支持 SNI 的客户端 :
- 使用的 HTTP 客户端或库过旧,无法正确处理 SNI 信息。
- 服务器未正确配置 :
- 服务器端未启用或未正确配置 SNI。
- SSL 协议版本问题 :
- 客户端和服务器支持的 TLS/SSL 协议版本不兼容。
- 网络代理或负载均衡问题 :
- 请求通过代理或负载均衡器时,代理未正确处理 SNI 信息。
- 错误的请求 :
- 请求头中包含错误的或缺失的
Host
信息。
- 请求头中包含错误的或缺失的
curl https失败
错误日志如下
python
curl: (60) SSL certificate problem: self signed certificate
More details here: https://curl.haxx.se/docs/sslcerts.html
curl failed to verify the legitimacy of the server and therefore could not
establish a secure connection to it. To learn more about this situation and
how to fix it, please visit the web page mentioned above.
解决方案
1. 确认是否需要忽略证书验证
如果您只是测试或不关心安全性(例如在本地开发环境中),可以暂时忽略证书验证。
- 使用
-k
或--insecure
参数:
bash
curl -k https://example.com
注意:忽略证书验证是不安全的,仅适用于测试环境。不要在生产环境中使用。
示例
假设目标服务器为 https://my-local-server.com
,自签名证书保存为 server-cert.pem
:
bash
# 忽略证书验证(仅用于测试)
curl -k https://my-local-server.com
# 使用自签名证书
curl --cacert server-cert.pem https://my-local-server.com
# 全局信任自签名证书(Linux 示例)
sudo cp server-cert.pem /usr/local/share/ca-certificates/
sudo update-ca-certificates
curl https://my-local-server.com
回滚包更新
1. 确认当前的更新状态
查看哪些包已经被更新,哪些包仍未更新:
bash
sudo dnf history
- 这将显示最近的
dnf
操作历史。 - 找到对应的更新操作的 ID(比如
ID 12
)。
2. 回滚到上一个状态
dnf
提供了回滚功能,可以尝试还原到之前的状态:
bash
sudo dnf history undo <ID>
- 将
<ID>
替换为之前更新操作的 ID。 - 如果更新中途失败,可能需要手动修复依赖冲突或其他问题。
注意:有些包在更新过程中可能无法完全回滚,尤其是系统关键组件。
3. 强制降级包
如果某些关键包已经更新且无法正常工作,可以尝试手动降级:
bash
sudo dnf downgrade <package-name>
例如,降级某个核心组件:
bash
sudo dnf downgrade glibc
4. 使用快照恢复
如果您在更新前启用了文件系统快照(例如通过 Btrfs 或 LVM),可以恢复到更新前的状态:
- 列出系统的快照:
bash
sudo lvdisplay
- 恢复到更新前的快照:
bash
sudo lvconvert --merge <snapshot_name>
注意:这种方法需要您提前配置了快照功能。
5. 排查问题包并修复
如果更新一半后出现问题,可以尝试修复依赖:
bash
sudo dnf check
sudo dnf clean all
sudo dnf distro-sync
**dnf check**
:检查已安装包的依赖关系是否一致。**dnf distro-sync**
:将系统包同步到当前发行版默认版本,可能降级不兼容的更新包。
6. 回滚失败的替代方法
如果无法直接回退,可以尝试手动重装某些关键包,或者:
- 重装系统核心包:
bash
sudo dnf reinstall <package-name>
例如:
bash
sudo dnf reinstall kernel glibc systemd
- 恢复系统备份:如果有系统镜像或配置备份,可以恢复到更新前的状态。
7. 建议
- 启用快照机制:在生产系统中,建议使用 Btrfs 或 LVM 配置文件系统快照,方便在类似情况下快速回滚。
- 逐步更新 :未来避免使用
sudo dnf update -y
一次性更新所有包,改为按需更新特定包,减少出错风险。
总结:使用 dnf history undo <ID>
是最直接的方式。如果无法解决问题,尝试使用快照恢复或重装关键包。
failovermethod
Invalid configuration value: failovermethod=priority in /etc/yum.repos.d/CentOS-epel.repo; Configuration: OptionBinding with id "failovermethod" does not exist
这个错误是因为 yum
配置文件中的 failovermethod
选项已不再被 CentOS 8 或 RHEL 8 的 dnf
包管理器支持。要解决这个问题,可以手动修改相关配置文件。
解决办法
- 找到报错的配置文件 根据错误提示,问题出在
/etc/yum.repos.d/CentOS-epel.repo
文件中。 - 编辑配置文件 使用文本编辑器打开文件,例如:
bash
sudo nano /etc/yum.repos.d/CentOS-epel.repo
或者:
bash
sudo vi /etc/yum.repos.d/CentOS-epel.repo
- 删除
**failovermethod**
行 在文件中查找failovermethod=priority
,然后将整行删除。例如:
plain
failovermethod=priority
删除这行即可。
- 保存并退出
- 如果使用
nano
,按Ctrl + O
保存文件,然后按Ctrl + X
退出。 - 如果使用
vi
,按Esc
输入:wq
保存并退出。
- 如果使用
- 清理缓存并重试 清理
dnf
缓存:
bash
sudo dnf clean all
再次尝试安装或更新:
bash
sudo dnf update
批量处理多个存储库文件
如果有多个存储库文件可能包含 failovermethod
配置,可以使用以下命令快速删除:
bash
sudo sed -i '/failovermethod/d' /etc/yum.repos.d/*.repo
- 该命令会检查
/etc/yum.repos.d
目录下的所有.repo
文件,并删除包含failovermethod
的行。
验证
再次运行 dnf
命令,确认问题已解决:
bash
sudo dnf repolist
默认镜像源问题
Errors during downloading metadata for repository 'appstream': - Curl error (6): Couldn't resolve host name for http://mirrorlist.centos.org/?release=8\&arch=x86_64\&repo=AppStream\&infra=stock [Could not resolve host: mirrorlist.centos.org]
这个问题的根本原因是 CentOS 8 已于 2021 年停止维护,其默认镜像源(mirrorlist.centos.org
)可能不可用。以下是解决办法:
1. 切换到 CentOS Vault 存储库
CentOS 提供了一个归档(Vault)镜像存储,用于保存旧版本的包。
替换默认的存储库配置
- 备份原有的存储库配置:
bash
sudo mv /etc/yum.repos.d/CentOS-* /etc/yum.repos.d/backup/
- 创建新的存储库配置:
bash
sudo nano /etc/yum.repos.d/CentOS-Vault.repo
- 添加以下内容:
plain
[BaseOS]
name=CentOS-8 - BaseOS
baseurl=http://vault.centos.org/8.5.2111/BaseOS/$basearch/os/
gpgcheck=1
enabled=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-centosofficial
[AppStream]
name=CentOS-8 - AppStream
baseurl=http://vault.centos.org/8.5.2111/AppStream/$basearch/os/
gpgcheck=1
enabled=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-centosofficial
[extras]
name=CentOS-8 - Extras
baseurl=http://vault.centos.org/8.5.2111/extras/$basearch/os/
gpgcheck=1
enabled=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-centosofficial
- 保存并退出文件。
- 清理缓存并生成新的元数据:
bash
sudo dnf clean all
sudo dnf makecache
sudo dnf update
2. 检查 DNS 配置
如果仍然出现类似的网络错误,可能是 DNS 配置问题导致的。尝试以下步骤:
修改 DNS 设置
- 编辑
/etc/resolv.conf
文件:
bash
sudo nano /etc/resolv.conf
- 添加可靠的 DNS 服务器:
bash
nameserver 8.8.8.8
nameserver 8.8.4.4
- 保存并退出文件。
- 测试网络和域名解析:
bash
ping 8.8.8.8
ping mirrorlist.centos.org
3. 迁移到其他版本或发行版
由于 CentOS 8 已停止维护,建议迁移到以下版本:
- CentOS Stream:滚动发布版,官方推荐。
- AlmaLinux 或 Rocky Linux:CentOS 的稳定替代品。
迁移到 AlmaLinux
- 安装迁移工具:
bash
sudo dnf install -y almalinux-deploy
- 运行迁移命令:
bash
sudo almalinux-deploy
迁移到 Rocky Linux
- 安装迁移工具:
bash
sudo dnf install -y rocky-release
- 运行迁移命令:
bash
sudo rocky-upgrade
总结
如果只是短期需要继续使用 CentOS 8,可以切换到 Vault 存储库。如果需要长期支持,建议迁移到 AlmaLinux 或 Rocky Linux,以获得社区支持和定期更新。
DNS验证错误
报错: Detail: DNS problem: NXDOMAIN looking up TXT for _acme-challenge.your-domain.cn - check that a DNS record exists for this domain
这个报错表明你在使用 DNS 验证 的方式申请 SSL 证书时,Let's Encrypt 的服务器无法找到 _acme-challenge.your-domain.cn
的 TXT 记录。这通常是因为 DNS 记录未正确添加或未生效。
解决方法
1. 确保正确添加了 TXT 记录
- 登录你的域名管理平台(如阿里云、腾讯云、Cloudflare)。
- 添加一个新的 TXT 记录:
- 主机记录(或名称) :
_acme-challenge
- 记录类型:TXT
- 记录值 :Certbot 提示生成的一段字符串(例如:
ZSYwtkVIMbfDED30Aou6hXTk9TuepsWisHgTa8ATTBY
)。 - 生存时间(TTL):可以选择较短的值(如 1 分钟)以便快速生效。
- 主机记录(或名称) :
2. 验证 TXT 记录是否生效
在添加记录后,使用以下命令检查 TXT 记录是否生效:
bash
nslookup -q=txt _acme-challenge.your-domain.cn
或:
bash
dig TXT _acme-challenge.your-domain.cn
- 如果返回类似以下结果,表示记录生效:
plain
_acme-challenge.your-domain.cn. 300 IN TXT "ZSYwtkVIMbfDED30Aou6hXTk9TuepsWisHgTa8ATTBY"
- 如果没有返回结果,可能是:
- DNS 配置未正确添加。
- DNS 记录尚未完全生效(可能需要几分钟到几小时)。
3. 等待 DNS 生效
如果确认 DNS 配置无误,但仍报错,可能是因为记录还未传播到 Let's Encrypt 的 DNS 服务器。
你可以稍等 10 分钟后再尝试重新运行 Certbot 命令。
4. 检查 DNS 服务器设置
确保你的域名解析使用的 DNS 服务器是正确的。可以通过以下方式检查:
bash
whois your-domain.cn | grep "Name Server"
确保查询结果中的 DNS 服务器与你的域名管理平台一致。如果不一致,需要更新域名的 DNS 设置。
5. 避免常见错误
- 主机记录误加域名 :一些域名管理平台可能自动添加主域名。如果你手动输入
_acme-challenge.lonngs.cn
,最终记录可能变成_acme-challenge.your-domain.cn.your-domain.cn
,导致无法生效。正确的主机记录应该是_acme-challenge
。 - 多个 TXT 记录冲突 :如果同一域名下已经存在多个
_acme-challenge
的 TXT 记录,可能会导致验证失败。请删除其他无关的 TXT 记录。
6. 重新运行 Certbot
在确认 TXT 记录生效后,重新运行 Certbot:
bash
sudo certbot certonly --manual --preferred-challenges dns
然后按照提示完成验证。
总结
- 确保 DNS TXT 记录正确配置。
- 检查 DNS 是否生效。
- 避免域名配置错误或冲突。
- 必要时等待 DNS 传播后再重试。