ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

腾讯云SSL证书部署与Nginx排错:从DNS验证到证书链详解

腾讯云SSL证书部署与Nginx排错:从DNS验证到证书链详解 1. 为什么你的腾讯云SSL证书总是“不生效”先说一个扎心的事实我见过太多人把SSL证书不生效的锅甩给腾讯云其实超过一半的问题都是自己的操作顺序或者理解出了偏差。腾讯云的SSL证书服务本身很成熟但它的“一键部署”能力反而容易让使用者养成一个坏习惯——不管底层原理点了部署按钮看到“成功”就觉得万事大吉结果浏览器照样提示不安全。这篇文章就是想把我在腾讯云上折腾SSL证书的完整经验捋一遍。无论你是第一次在腾讯云申请免费证书还是已经在Nginx上手动部署过证书但遇到各种诡异问题或者只是被“证书链不完整”“证书和私钥不匹配”这类报错折磨过都应该能从里面找到对应的解决方案。我会把从申请、验证、下载、部署到排错的全链路都讲透尤其是那些控制台不会告诉你的细节。先说一个基本概念很多人混淆了“证书申请成功”和“证书部署成功”。腾讯云SSL证书控制台显示的“已签发”只代表CA机构证书颁发机构认可了你对域名的所有权跟你的服务器上是否真的正确使用了这张证书完全是两回事。这就好比你拿到了房产证但房子里的水电还没接通一样。所以当你发现证书状态是“已签发”但网站依然报错第一反应不应该是怀疑腾讯云而是回到自己的服务器环境里找问题。另外腾讯云上的SSL证书分为免费版和付费版。免费版通常是一年期单域名证书付费版支持多域名和通配符。如果你只是个人博客或者测试环境免费版完全够用如果是企业生产环境我会建议至少用OV级别的证书因为浏览器地址栏的展示效果和信任度不一样。但这个选择其实不影响部署逻辑下面讲的内容对两种证书都适用。2. 申请证书时最容易忽视的验证环节2.1 DNS验证不是“添加一条记录”那么简单在腾讯云申请SSL证书时最常见的验证方式是DNS验证。控制台会给你一个主机记录和一个记录值让你去域名解析控制台添加一条TXT记录。很多人以为只要添加了就一定能通过但实际踩坑点非常多。第一注意主机记录。如果你申请的是blog.example.com这个子域名的证书控制台给的主机记录可能长这样_dnsauth或者_dnsauth.blog具体取决于你申请的是主域名还是子域名。千万别小看这个前缀我见过有人把_dnsauth整个当成主机记录填上去结果解析记录变成_dnsauth._dnsauth.example.com验证当然过不了。第二记录值必须完整复制。TXT记录的值通常是一长串字符中间可能有大写字母、数字和连字符。有些域名解析服务商尤其是国外服务商会自动把值转换成小写或者截断过长内容这会导致验证失败。我的建议是复制之后先去命令行用dig txt _dnsauth.example.com确认一下返回的记录值和你在腾讯云控制台看到的是否完全一致。第三TTL值。虽然大多数情况下默认600秒就行但如果你之前已经存在同名的TXT记录新记录可能不会立即生效。遇到“验证失败”别急着疯狂点击“重新验证”先去检查DNS是否真的全球生效了。可以用dig 8.8.8.8 txt _dnsauth.example.com指定公共DNS查询如果返回记录为空那就是还没解析成功等待几分钟再试。提示腾讯云域名解析控制台和SSL证书控制台是在同一个账号下的话理论上可以自动添加记录。但如果你把域名托管在阿里云、Cloudflare或者其他服务商就必须手动添加。这种跨服务商场景下最容易出问题的是Cloudflare因为它的代理模式可能会缓存TXT记录导致你看到的结果是旧的。建议在Cloudflare的DNS面板里暂时把代理状态调整为“仅DNS”等验证通过后再改回。2.2 文件验证的坑路径和权限缺一不可如果域名不方便改DNS比如某些特殊的业务环境腾讯云还提供文件验证方式。原理就是CA机构会访问http://你的域名/.well-known/pki-validation/文件名称.txt通过这个URL能访问到你上传的验证文件就证明你对域名有控制权。这个方案在腾讯云的CVM云服务器上看起来很简单但实际部署时容易遇到两个问题。一是路径不对很多人在服务器根目录下建了个文件夹却忘了Nginx里配置的网站根目录不是/也不是默认的/var/www/html而是自己项目里的某个子目录。你要明白URL里的路径是相对于网站根目录的不是你服务器上的绝对路径。也就是说如果Nginx配置里root指向/data/www/blog那么验证文件就应该放在/data/www/blog/.well-known/pki-validation/下面。二是权限不对。Nginx运行用户通常是www-data或者nginx如果文件权限是644、目录权限是755一般没问题。但如果你图省事用root用户创建文件可能目录权限是700导致Nginx无法读取子目录访问URL时返回403。处理方法是chmod -R 755 /data/www/blog/.well-known chmod 644 /data/www/blog/.well-known/pki-validation/*.txt还有一个容易被忽略的细节如果你网站本身强制HTTP跳转HTTPS或者开启了HSTS那么CA机构用HTTP访问验证文件时可能会被重定向到HTTPS而HTTPS又是坏的没有证书导致验证请求失败。这种情况我建议先临时关掉HTTP强制跳转或者直接在Nginx配置里加一条location规则让/.well-known/pki-validation/路径不走重定向规则。3. 下载证书后如何正确部署到Nginx3.1 区分证书文件千万别把PEM格式和CRT格式搞混腾讯云签发证书后会提供一个下载页面里面根据服务器类型分成Apache、Nginx、IIS、Tomcat等不同文件夹。很多人直接下载Nginx文件夹然后看到里面有1_root_bundle.crt、2_xxx.crt、3_xxx.key三个文件就开始头晕。说一下Nginx下的正常使用姿势。Nginx需要的是两个东西一个是证书链文件包含服务器证书和根证书一个是私钥文件。腾讯云给出的xxx.crt就是服务器证书xxx_bundle.crt是根证书链.key就是私钥。但Nginx配置里ssl_certificate指令通常只需要引用一个文件这个文件必须包含完整的证书链。腾讯云给的文件里有时候服务器证书本身已经包含了中间证书有时候没有这就导致很多人只填了2_xxx.crt而漏掉了根证书结果浏览器报“证书链不完整”。我的做法是在服务器上把2_xxx.crt和1_root_bundle.crt合并成一个文件或者直接下载Nginx格式的证书包有的版本会提供一个整合过的.crt。合并命令cat 2_xxx.crt 1_root_bundle.crt combined.crt然后在Nginx配置里这样写listen 443 ssl; ssl_certificate /etc/nginx/certs/combined.crt; ssl_certificate_key /etc/nginx/certs/3_xxx.key;注意合并时服务器证书在前根证书链在后。顺序乱了会导致一些客户端不认账。合并后可以这样验证openssl crl2pkcs7 -nocrl -certfile combined.crt | openssl pkcs7 -print_certs -noout如果能看到多行证书信息就说明合并成功了。3.2 Nginx配置SSL时常见的语法和逻辑错误部署Nginx SSL时最容易出现的一个低级错误是配置了443端口但没有把80端口请求重定向到443或者反过来为了强制HTTPS把80端口配置写坏了。一个合规且安全的SSL server块应该长这样server { listen 80; server_name example.com www.example.com; return 301 https://$host$request_uri; } server { listen 443 ssl; http2 on; server_name example.com www.example.com; ssl_certificate /etc/nginx/certs/combined.crt; ssl_certificate_key /etc/nginx/certs/example.key; ssl_protocols TLSv1.2 TLSv1.3; ssl_ciphers HIGH:!aNULL:!MD5; ssl_prefer_server_ciphers on; location / { proxy_pass http://127.0.0.1:8080; # 或者 root 你的项目目录; } }这里要特别提醒listen 443 ssl写法是Nginx 1.25之前的版本新版本已经改成listen 443 ssl;也可以继续用。千万不要写成listen 443;然后忘记加ssl参数那样Nginx会认为是普通HTTP端口你还是没法用HTTPS访问。另外一个高频错误是证书路径里有特殊字符或者多打了空格。Nginx对路径非常敏感比如/etc/nginx/certs/ combined.crt这样多了个空格重启Nginx不会报错但实际加载证书时就会找不到文件。建议配置完以后一定用nginx -t测试语法并且额外检查一下nginx -t -c /etc/nginx/nginx.confnginx -t只检查语法不检查证书是否能正确加载。所以更稳妥的做法是重启Nginx后用浏览器访问如果页面能打开且地址栏出现锁头基本就没问题。如果Nginx已经启动证书加载失败一般会直接抛错看错误日志就能定位。3.3 别忘了安全组和防火墙这是腾讯云场景下特别典型的一个坑。你在服务器上把SSL配置得再完美如果腾讯云的安全组没有开放443端口外网访问照样不通。而且这个端口不是默认对外开放的腾讯云CVM在购买时的默认安全组可能只开放了80、22、3389等常用端口。443端口被安全组拦截后你从浏览器访问HTTPS会直接连接超时而不是证书错误。处理方法进入腾讯云控制台找到对应CVM实例的安全组添加入站规则协议TCP端口443来源建议先设置为0.0.0.0/0方便测试正式环境再按需限制IP。服务器内部的防火墙也要检查。如果使用了firewalldfirewall-cmd --add-servicehttps --permanent firewall-cmd --reload如果使用iptables则需要手动添加规则。这一步做完再测试telnet yourdomain.com 443如果能通说明网络层面已经放行。4. 证书部署后的诊断与“伪生效”问题4.1 为什么证书显示有效但浏览器还报警告有一种很迷惑的现象你确认证书已经部署成功用curl https://example.com也没报错但浏览器打开还是提示“不安全”或者“证书错误”。这种问题十有八九是证书链不完整导致的也就是第3节说的ssl_certificate文件里缺少中间证书。我之前用在线工具比如SSL Labs的SSL Server Test测过如果证书链完整评分会是A或者A如果只上传了服务器证书评分可能直接是T或者M。浏览器对证书链的容忍度比命令行工具低得多尤其是Chrome、Firefox最新版本只要中间证书缺失一律大红叉。验证证书链是否完整的一个快速命令openssl s_client -connect example.com:443 -servername example.com /dev/null 2/dev/null | openssl x509 -noout -issuer -subject然后看返回的subject和issuer。如果你看到证书的issuer不是腾讯云提供的CA根证书而是某个中间CA说明证书链里缺少中间证书你就需要把腾讯云给的那个bundle文件合并进来。另外ssl_certificate文件里也可以直接写多段证书Nginx从第一个证书开始读读到最后一个证书结束它会把服务器证书和中间证书都加载进去。所以合并时要注意顺序服务器证书必须在最前面。4.2 证书与私钥不匹配的排查有时候Nginx能正常启动但浏览器报ssl_error_rx_record_too_long或者其他协议错误很可能是证书和私钥不匹配。这种情况一般不是腾讯云发错文件而是你下载的时候下载错了把多个域名的证书搞混了。快速验证证书和私钥是否匹配# 私钥的模数 openssl rsa -noout -modulus -in your.key | openssl md5 # 证书的模数 openssl x509 -noout -modulus -in your.crt | openssl md5两个命令输出的MD5值一样说明匹配不一样说明你张冠李戴了。还有一个我踩过的坑私钥文件包含了额外的换行符或者被Windows记事本编辑过导致文件格式变成CRLFNginx加载时会报“Expecting: TRUSTED CERTIFICATE”之类的问题。解决办法是把私钥文件重新用Unix格式保存dos2unix your.key或者直接在Linux下用awk {sub(/\r$/,); print} your.key clean.key4.3 用在线工具和命令行工具做全面诊断部署完成后我习惯先本地再远程做一轮检查。本地检查Nginx是否正确加载证书链nginx -t systemctl restart nginx openssl s_client -connect 127.0.0.1:443 -servername example.com /dev/null 2/dev/null | grep Verify return code如果返回Verify return code: 0 (ok)说明链没问题。如果返回20 (unable to get local issuer certificate)说明证书链不完整。如果返回18 (self-signed certificate)说明加载的证书不是CA签发的正式证书。远程检查我推荐直接用curl -vI https://example.com看输出的SSL握手信息里SSL certificate verify ok这一行。如果显示这个说明你的服务器与外网之间的HTTPS链路基本是通的。之后可以用浏览器无痕模式访问站点按F12查看安全标签页里的证书信息确认域名、颁发机构、有效期都对得上。这一步能看出很多问题比如证书绑定的域名是不是和访问域名不一致。如果你申请的是example.com的证书但你用www.example.com访问而证书又不包含www.example.com浏览器一定会报警告。5. 腾讯云SSL证书的自动续期与免费证书的防过期策略5.1 免费证书为什么不能自动续期腾讯云的免费证书有效期是一年有的政策是90天具体以官方当前策略为准到期前需要手动重新申请。很多人在证书过期当天才发现问题因为浏览器开始报错才慌慌张张去申请但新证书签发需要时间导致网站出现一段时间的不可用。这个问题本质上不是腾讯云的问题而是免费证书的机制决定的。免费证书不具备自动续期接口和ACME客户端自动签发证书不同。腾讯云虽然提供了托管证书服务但免费版主要面向小流量个人站点等于你要每年手动操作一次。我自己的做法是在日历上设置提前一个月的提醒或者干脆写一个定时任务每周检查一下证书到期时间echo | openssl s_client -servername example.com -connect example.com:443 2/dev/null | openssl x509 -dates -noout把输出里的notAfter和当前日期对比如果剩余天数小于30天就发一封邮件或者一个钉钉消息提醒自己。虽然不能代替手动续期但至少不会等到过期才发现。5.2 手动续期时的高效流程腾讯云控制台的SSL证书列表里每条证书旁边有个“续期”按钮。点击后通常会要求重新验证域名所有权验证方式仍然是DNS或者文件。这里有个小技巧因为证书即将到期域名解析里往往还留着旧的TXT验证记录而续期验证会生成新的记录值新旧记录同时存在不影响验证也可以等验证通过后再删除旧的。为了简化操作我一般会先在本地准备好一段脚本实现在DNS服务商API自动添加TXT记录。但考虑到很多读者用的是腾讯云自带的DNSPod我建议直接用控制台手动添加因为数量少、操作快没必要为了一年一次的续期去折腾API。5.3 如果不想每年手工续期用ACME方案如果你会一些命令行操作完全可以跳出腾讯云的证书托管体系自己用ACME协议申请Let‘s Encrypt的免费证书。这种证书有效期是90天但可以通过脚本自动续期配合Nginx的reload操作基本可以做到一次配置、永久无忧。以certbot为例certbot certonly --nginx -d example.com -d www.example.com这个方案的好处是证书续期自动化。缺点是证书有效期的确短且Let’s Encrypt的根证书在部分老旧设备上可能不受信任不过现在覆盖率已经很高了。如果你既想用腾讯云签发的DV证书又想要自动续期其实还有一个折中方案用腾讯云API写一个定时任务在证书过期前调用申请接口然后自动部署到服务器。但这需要现成的接口权限官方文档写得并不算太友好不建议没有开发经验的用户尝试手动续期就好。6. 遇到诡异证书问题时的终极排错链路6.1 我把踩过的一个坑完整复盘Nginx配置了证书但网页还是跳HTTP有一个月我被一个新项目的证书问题折磨了两个小时。现象很迷惑浏览器访问http://example.com会自动跳转到https://example.com但页面直接显示“无法访问此网站”而Nginx进程明明在跑443端口也开着证书也是刚续期完的新证书。我先把问题拆成三层网络层、Nginx层、证书层。首先是网络层我检查安全组443是否开放、服务器防火墙是否放行用telnet example.com 443发现端口是通的。问题不在这一层。然后看Nginx配置。我用nginx -t显示语法没问题但再看实际监听的端口时发现443端口根本没有被监听。这就诡异了。于是我grep -r listen 443 /etc/nginx/发现有两处配置文件存在一处是sites-enabled里的配置一处是我手动新建在conf.d下的配置。两个文件里都有listen 443 ssl但其中一个文件里证书路径写的是ssl_certificate /etc/nginx/ssl/old.crt而这个old.crt文件已经被我删掉了。Nginx启动时加载了旧的配置片段因为证书文件缺失直接报错导致语法测试通过但进程没有成功监听443端口。可是既然证书文件缺失Nginx为什么nginx -t还能通过因为nginx -t只检查语法碰到缺失的证书文件时会报错但我手动测试时并没有加上依赖的完整配置文件所以掩盖了问题。这个教训是排查Nginx问题先确认监听的端口情况别只看配置语法。用ss -lntp | grep nginx看看有没有443比啥都直观。6.2 从现象到根因的检查清单如果你遇到SSL证书相关的问题建议按照下面这个顺序排查不要跳步确认域名解析正确指向服务器IPping一下或者用dig查A记录。确认443端口在外网可达使用telnet IP 443或者在线端口扫描工具。确认Nginx确实监听着443端口ss -lntp | grep 443。确认Nginx加载的证书和私钥文件存在且权限正确ls -l /etc/nginx/certs/。确认证书和私钥匹配用modulus比对。确认证书链完整用openssl s_client验证。确认浏览器访问的域名与证书绑定的域名一致尤其是有多个域名或泛域名时。这个清单能解决95%的部署类问题。剩下的5%往往是更底层的网络环境问题比如中间网络设备改包、运营商缓存那就要换网络再测试了。6.3 排查中实用的一些命令汇总我把我最常用的几条命令整理成了一张表方便你在出问题时快速复制排查目的命令检测证书信息openssl s_client -connect 域名:443 -servername 域名 /dev/null 2/dev/null检测证书链openssl s_client -showcerts -connect 域名:443 -servername 域名 /dev/null 2/dev/null检测证书到期时间echo | openssl s_client -servername 域名 -connect 域名:443 2/dev/null | openssl x509 -noout -dates检查私钥模数openssl rsa -in 私钥文件 -noout -modulus | md5sum检查证书模数openssl x509 -in 证书文件 -noout -modulus | md5sum检查Nginx端口ss -lntp | grep 443测试Nginx配置nginx -t6.4 腾讯云“证书托管”功能到底要不要用腾讯云控制台里有证书托管功能可以把证书托管给云到期前会提醒你续期。但这个功能不是自动续期只是帮你在到期前30天自动发起续期申请仍需你手动验证。我曾一度以为托管了就能一劳永逸结果还是差点翻车。如果你用的是腾讯云负载均衡CLB来承载HTTPS那确实可以把证书直接上传到CLB上到期后在控制台一键替换比去每台CVM上改配置要省心不少。若你用的是CVM 自己的Nginx证书托管意义就没那么大反正都得手动操作。还有一种比较特殊的场景腾讯云的CDN服务也支持HTTPS证书配置。如果你网站接了CDN但证书只部署在源站那么用户访问CDN节点时会因为节点上没有证书而报错。你需要在CDN控制台里单独上传证书或者让CDN自动回源获取证书。这个容易漏大家可以留意一下。7. 从SSL证书延伸到HTTPS性能优化的两个小建议证书部署正确之后下一步就该考虑HTTPS的性能了。很多人以为加了SSL就一定会拖慢网站其实优化得当的话HTTPS和HTTP的体验差距微乎其微。第一在Nginx开启OCSP Stapling。这个功能可以让Nginx在握手时主动把证书的OCSP查询结果发给浏览器省去了浏览器再去CA查询证书有效性的时间。配置方法ssl_stapling on; ssl_stapling_verify on; resolver 8.8.8.8;开启后可以用openssl s_client -connect example.com:443 -servername example.com -status检查返回里有没有OCSP Response。有的Nginx版本需要你给CA证书捆绑文件不然会报错。第二启用会话缓存。ssl_session_cache 可以复用TLS握手结果减少重复握手的开销ssl_session_cache shared:SSL:10m; ssl_session_timeout 10m;这两个优化对性能的提升肉眼看不到但对高并发场景的影响非常明显。如果哪天你的HTTPS站点响应速度有问题先别急着骂证书看看是不是握手频率太高了。最后说点个人体会。SSL证书本质上是“信任”的载体它解决的问题不是加密本身——加密算法早就成熟了——而是“让浏览器相信这个服务器确实是该域名的合法拥有者”。所以处理腾讯云SSL证书问题时核心思路永远是证书是合法的、链路是完整的、私钥是匹配的、端口是放行的。把这四句话刻在脑子里绝大多数报错都能迎刃而解。我每次给新环境配证书都会默念一遍然后按着这个逻辑去查基本没走过弯路。
返回列表