
最近一个朋友的生产环境证书悄悄过期了周六早上他打电话过来语气里带着一种“我已经猜到了但还是有点崩溃”的感觉网站打开显示红色警告手机上更是直接被浏览器拦截用户已经开始在群里问了。我第一句话就是你看SSL证书要及时更新啊。这不是我第一次遇到这种情况。自己买过服务器、维护过个人网站或NAS的朋友迟早会在某个周末的早晨被证书这件事叫醒。SSL证书这个东西你不用它的时候觉得它不存在一旦过期它比谁都显眼。这篇内容不聊高深理论只讲和证书更新相关的那点事阿里云免费证书怎么续期、cer怎么转成Tomcat用的pfx、群晖换证书报“抱歉您所指定的页面不存在”怎么排查、vsftpd对证书到底有什么要求。适合所有自己维护站点、NAS和FTP服务的同学尤其是那种“证书到期前总觉得还有时间”的人。1. 证书过期不是小事一个被忽略的90天周期1.1 过期之后你的站点会发生什么证书过期的第一个后果就是浏览器把整个站点的可信度归零。用户访问时看到的不再是地址栏里的小锁而是“您的连接不是私密连接”这类大字警告部分浏览器还会强制拦截连“继续访问”的按钮都不给。对于电商、博客、企业官网这类依赖访问者信任的场景这一个警告足以让转化率归零。更麻烦的是证书过期不只是浏览器端的问题。很多API接口、微信小程序回调、第三方支付回调服务端在调用你的HTTPS接口时也会校验证书有效期。证书一过期接口直接报错而且报错信息通常都很抽象什么“SSL certificate has expired”“certificate verify failed”第一次看到的人很容易误判成网络或代码问题绕一大圈才发现是证书凉了。还有个容易被忽略的移动端App对证书的校验比PC浏览器更严格。有些原生App内置了证书校验逻辑证书一过期App里所有网络请求全部失败表现成“服务器开小差”或“网络异常”用户只会认为你的App做得很烂根本想不到是证书过期。1.2 为什么现在的免费证书越来越“短命”早年很多云厂商的免费证书还有一年有效期现在的主流免费证书基本都压缩到了90天也就是三个月左右。我这个朋友用的阿里云免费证书单张有效期就是3个月到期前需要重新申请、重新部署。这个变化不是云厂商故意折腾人而是行业在推动更短的证书生命周期——证书有效期越长万一私钥泄露影响面就越大缩短有效期能强迫大家更频繁地轮换密钥整体安全性反而更高。但对于普通站长来说90天的周期确实很考验人。你稍微忙一点、忘记在日历上做提醒再想起来的时候大概率已经过期了。而且免费证书通常不支持通配符域名也就是一张证书只能覆盖一个域名你要是开了几个子域名每个子域名都要单独申请、单独部署维护成本直接翻倍。1.3 别把证书当一次性的配置先建好台账我自己踩过几次坑之后养成一个习惯证书不是配置完就不管的东西它有明确的生日和死亡日期。每申请一张证书我都会在一个文档里记录域名、证书类型、有效期起止、部署在哪台服务器、用的哪个目录、私钥文件名是什么。这个台账看起来很简单但真到了证书批量到期的那天它能救你的命。另外一个建议是不要把私钥到处乱放。私钥一旦泄露别人可以用你的域名发起钓鱼攻击浏览器里的锁形图标反而成了骗人的工具。私钥文件建议放在只有root可读的目录权限设成600别跟着压缩包一起丢到随便一个网站目录里。2. 阿里云免费SSL证书的续期流程从申请到重新部署2.1 免费证书的申请入口与配额以阿里云为例控制台搜索“SSL证书”就能进入证书管理页面。免费证书的申请入口在“证书管理”或“SSL证书”菜单下目前免费证书的规则是单张有效期90天左右每个自然年能申请的额度有限具体数量以控制台提示为准。早期还有一年期的免费证书现在已经基本看不到了。这里有个关键点免费证书没有“续期”按钮只有“重新申请”。很多人翻遍控制台找“续期”找不到其实逻辑是对的——免费证书本质上是每90天给你发一张全新的证书到期后重新走一遍申请流程拿到新证书再替换旧证书。对于付费证书情况会稍微好一点一般支持到期前自动或手动续期有些还能一键部署到云产品。但如果你用的是免费证书就要接受“三个月折腾一次”的现实。2.2 申请签发要填的几个关键字段申请免费证书时第一个要填的就是域名。域名必须是你有控制权的否则无法完成验证。阿里云验证域名所有权的方式通常是DNS验证系统会生成一条TXT记录你把这条记录加到域名的DNS解析里等系统验证通过证书就会签发。如果你的域名本来就托管在阿里云DNS验证过程会更顺滑申请时选“自动DNS验证”系统会在后台自动加记录基本不用人工操作。如果域名不在阿里云DNS就得自己去域名注册商那边手动添加TXT记录等几分钟到几十分钟生效后再回来点“验证”。签发速度通常很快快的话几分钟慢的话可能个把小时。证书签发后记得在有效期内下载并部署别等它躺在那儿又过期了。2.3 下载证书时选对服务器类型这是最容易搞混的一步。阿里云证书下载页会让你选择服务器类型常见的有Nginx、Apache、Tomcat、IIS等。你到底选哪个取决于你的Web服务软件不是取决于你的操作系统。选Nginx下载到的是一对文件通常是一个.pem证书文件和一个.key私钥文件有的还会附带chain.pem链证书或fullchain.pem完整链。选Tomcat下载到的是.pfx或.jks格式的密钥库文件需要设置密码。选Apache下载到的是.crt证书和.key私钥。这里我建议如果你用的是Nginx或类Nginx的Web服务器优先选Nginx类型因为pem/key一对文件用起来最直观后续转到别的场景也更方便转换。如果你不确定自己用的什么服务器先去看一眼配置文件不要凭感觉猜。2.4 部署后如何验证真的生效部署完成后别急着关页面先用命令验证一下证书是否真的生效了。最常用的就是openssl命令echo | openssl s_client -connect yourdomain.com:443 -servername yourdomain.com 2/dev/null | openssl x509 -noout -issuer -subject -dates这个命令会连接到你的站点把服务器返回的证书信息打印出来重点看notAfter字段也就是证书过期时间。如果显示的日期和你在证书详情里看到的一致说明新证书已经生效。如果不一致多半是Web服务器没有重启或者你改的配置文件不是当前站点真正加载的那份。另外浏览器访问时如果还显示旧证书先强制刷新清一下缓存有时候是浏览器缓存了旧证书链服务器其实已经换好了。3. cer转pfx给Tomcat一次格式转换背后的原理3.1 为什么Tomcat偏偏要pfx或jks有时候你手里的证书文件是一个.cer但Tomcat认的是.pfx或.jks这就涉及格式转换。Tomcat和很多Java系的中间件一样默认从“密钥库”里读取证书和私钥而不是像Nginx那样从两个独立的文件里读取。密钥库相当于一个保险箱证书和私钥都放进里面再用一个密码锁住。最常用的密钥库格式就是PKCS12文件后缀一般是.pfx或.p12旧一点的还有JKS格式。所以“cer转pfx”这个操作本质上不是改个后缀名而是把散落的证书文件和私钥文件重新封装到一个带密码的密钥库文件里。这个过程需要工具最通用的就是openssl。3.2 先用openssl把cer变成pem.cer文件有两种常见编码DER二进制和Base64文本。如果是DER编码openssl直接读不了需要先转成PEM格式openssl x509 -inform DER -in yourdomain.cer -out yourdomain.pem如果是Base64文本编码通常直接改后缀名就能当pem用但你最好打开文件看一眼PEM格式的文件应该以-----BEGIN CERTIFICATE-----开头。如果开头不是这个就是DER编码按上面的命令转换。另外你需要找到对应的私钥文件一般是.key文件。没有私钥的话光有cer证书是做不了pfx的因为PFX需要同时包含证书和私钥否则Tomcat无法完成TLS握手。如果你只拿到一张cer、没有私钥那得先找给你证书的人要私钥这是绕不过去的前提。3.3 pkcs12导出pfx及server.xml配置证书转成pem、私钥也准备好之后执行下面的命令生成pfxopenssl pkcs12 -export \ -out tomcat.pfx \ -inkey yourdomain.key \ -in yourdomain.pem \ -certfile chain.pem-inkey指定私钥文件-in指定证书文件-certfile是可选参数用于把中间链证书一并打包进去。执行后openssl会提示你设置一个导出密码这个密码就是pfx密钥库的访问密码一定不能忘记后面配置Tomcat要用的。如果你手里有多级证书链比如根证书和中间证书分开的文件建议把它们都打包进pfx否则部分客户端可能报“证书链不完整”的错误。一般阿里云下载的压缩包里已经带了chain文件直接用就行。拿到tomcat.pfx后把它放到Tomcat的conf目录下然后修改server.xml里的HTTPS连接器配置Connector port443 protocolorg.apache.coyote.http11.Http11NioProtocol maxThreads150 SSLEnabledtrue SSLHostConfig Certificate certificateKeystoreFileconf/tomcat.pfx certificateKeystoreTypePKCS12 certificateKeystorePassword你的密码 / /SSLHostConfig /Connector改完重启Tomcat再用前面说的openssl s_client命令检查一遍确认443端口返回的证书过期时间是新的。3.4 转换时最容易翻车的几个细节第一个坑私钥和证书不匹配。转换时报错unable to load private key或者生成了pfx但Tomcat启动报错很多就是私钥文件跟证书根本不是一对。可以用下面命令比对两者的公钥信息openssl x509 -in yourdomain.pem -noout -pubkey openssl rsa -in yourdomain.key -pubout两边输出的公钥内容应该一致不一致就是文件搞错了。第二个坑密码里有特殊字符。pfx密码如果要放到server.xml里注意XML的转义规则比如要写成amp;。我见过有人密码里带个Tomcat直接解析失败折腾了半天才发现是转义问题。第三个坑Tomcat版本不同配置写法不同。Tomcat 8.5以上推荐用SSLHostConfig写法老版本可能还是keystoreFile直接写在Connector里的方式。配置前先确认你的Tomcat大版本网上抄配置的时候别拿8.0的去改9.0。4. 群晖换了阿里云证书显示“抱歉您所指定的页面不存在”排查实录4.1 先看清楚这个报错到底是谁抛出来的很多人看到群晖报“抱歉您所指定的页面不存在”就慌以为是证书文件坏了其实这个提示是DSM的通用错误页面类似于404。它不直接告诉你问题出在证书内容上而是说“DSM这个Web前端在处理请求时没有得到期望的结果”。我遇到过的真实案例里这个报错的触发场景五花八门有导入证书时格式不对的有Web Station站点证书没绑定到位的还有纯粹是浏览器缓存了旧页面导致跳转异常。所以正确思路不是盯着证书文件本身而是按“证书是否导入成功 - 服务是否绑定了新证书 - 前端是否刷新/缓存 - 系统会话是否正常”这个顺序排查。4.2 按照这个顺序排查基本十分钟能定位第一步确认证书是否真的导入成功。进群晖的“控制面板 - 安全性 - 证书”看证书列表里有没有你新导入的证书证书状态是否正常有效期是否正确。如果列表里根本没这张证书说明上传那一步就出问题了。第二步确认服务证书是否切换到了新证书。群晖的证书管理里有一个“服务证书”的概念你导入的证书默认不会自动应用到所有服务。需要手动指定DSM桌面、Web Station、FTP、邮件服务分别用哪张证书。如果证书导入了但没给服务绑定访问的时候还是旧证书或者直接报错。第三步清理浏览器缓存和DSM会话。换证书后建议退出DSM重新登录或者用无痕窗口访问一次。有时候浏览器缓存了旧的证书链和DSM页面脚本导致跳转到一个不存在的路径表现就是“抱歉您所指定的页面不存在”。第四步检查系统时间。群晖的系统时间如果偏差过大证书验证会失败部分情况下会表现成奇怪的报错页面。进“控制面板 - 区域选项”里确认时间同步正常。4.3 正确的群晖证书导入姿势DSM 7.x以阿里云下载的Nginx类型证书为例你手上会有一个.pem和一个.key文件。在群晖DSM 7.x里导入时点“新增”选择“导入证书”在证书格式里选“带有私钥的证书”然后分别把.pem文件和.key文件上传上去。这里最容易犯的错是误把证书压缩包zip直接拖上去或者只上传了证书、私钥还躺在本机文件夹里。私钥缺失的话DSM会拒绝导入表现可能就是弹出一个通用错误页面。如果你是下载Tomcat类型的.pfx文件导入时要选择对应格式并正确输入pfx密码。密码错误同样会导入失败。导入成功后记得回到“服务证书”标签页把DSM、Web Station等服务的证书切换成新导入的那张然后保存。4.4 下次换证书可以顺手做的检查清单换完证书后我一般会做三件事第一用手机流量访问一下群晖的HTTPS地址排除本地网络和缓存干扰第二用openssl s_client命令看公网域名返回的证书是不是最新的第三检查反向代理配置如果你用群晖的反向代理功能每个代理规则的证书也要单独更新这个位置特别容易被漏掉漏了就会导致反代站点打不开或报错。5. vsftpd的SSL证书要求FTPS加密与证书更新的完整配置5.1 FTP默认明文传输证书是刚需很多人觉得FTP只是传文件危险就危险在“只是传文件”这几个字。传统FTP协议默认明文传输用户名、密码、文件内容在网络上都是裸奔的只要有人抓包账号密码直接泄露。vsftpd要支持FTPS就必须配置SSL/TLS证书让控制连接和数据连接都走加密通道。vsftpd对证书的要求不复杂但有几个硬性条件证书和私钥必须是PEM格式、私钥不能设置密码、证书文件和私钥文件权限要合理。这几个条件缺一个vsftpd要么启动报错要么连上后客户端直接断开。5.2 自签证书生成-nodes参数不能省如果你没有购买商业证书只是想给内网或测试环境的FTP加一层加密可以用openssl生成自签证书mkdir -p /etc/vsftpd/ssl openssl req -x509 -nodes -days 3650 -newkey rsa:2048 \ -keyout /etc/vsftpd/ssl/vsftpd_key.pem \ -out /etc/vsftpd/ssl/vsftpd_cert.pem \ -subj /CNftp.example.com重点说下-nodes这个参数。它的意思是“不加密私钥”生成的私钥文件不带密码。vsftpd是开机启动的服务启动时没有交互式终端让你输入私钥密码所以私钥必须不带密码。如果你习惯性地加上了-des3之类的加密参数vsftpd启动时就会卡住或报错问你要密码又给不出来非常尴尬。另外-days 3650表示自签证书有效期为10年既然是自签证书有效期长一点省心。CN字段建议填你的FTP服务器实际域名或IP。5.3 vsftpd.conf里的SSL相关配置在/etc/vsftpd/vsftpd.conf里加以下配置ssl_enableYES allow_anon_sslNO force_local_data_sslYES force_local_logins_sslYES ssl_tlsv1YES ssl_sslv2NO ssl_sslv3NO rsa_cert_file/etc/vsftpd/ssl/vsftpd_cert.pem rsa_private_key_file/etc/vsftpd/ssl/vsftpd_key.pem require_ssl_reuseNO解释一下几个关键项ssl_enableYES是总开关force_local_data_sslYES和force_local_logins_sslYES强制本地用户在登录和数据传输时都必须走TLS否则拒绝连接ssl_tlsv1YES启用TLSv1ssl_sslv2NO和ssl_sslv3NO禁用老旧的SSLv2/SSLv3协议这些协议已经不安全了。require_ssl_reuseNO这一项值得单独说有些FTP客户端默认不会复用TLS会话如果vsftpd开启了严格的会话复用检查客户端会在数据连接时被拒报错信息类似“TLS session of data connection got resumed”。平时连不上FTPS的时候优先检查这一项。证书和私钥文件路径配置好后检查权限私钥文件vsftpd_key.pem建议改成600属主设为root即chmod 600 /etc/vsftpd/ssl/vsftpd_key.pem chmod 644 /etc/vsftpd/ssl/vsftpd_cert.pem然后重启vsftpdsystemctl restart vsftpd如果你用FileZilla连接选择“要求显式FTP over TLS”确认能正常列出目录和传输文件就说明配置没问题。另外记一下vsftpd的FTPS默认端口是21启用TLS后还是连21端口跟SFTP那种走22端口的完全不是一回事。5.4 更新证书后客户端仍然报错的排查FTPS最烦的是更新证书后客户端还记着旧证书。FileZilla这类客户端会缓存服务器证书信息如果你重新生成了自签证书客户端会提示证书不匹配并给出新旧证书的指纹。这时候要在FileZilla的站点管理器里把该站点的“信任的证书”清掉重新连接并信任新证书。如果更新证书后客户端提示“证书过期”但openssl查看证书明明没过期先查客户端本地时间有些终端设备的系统时间不准会直接导致证书校验失败。另外vsftpd的TLS配置里如果强制了TLS版本而客户端太老不支持新版本也会连接失败这时可以适当降低ssl_tlsv1级别但除非设备实在老旧不建议这么做。6. 证书到期前我会提前做好的三件小事6.1 用一行openssl命令搞定期限巡检证书多了之后人肉记有效期是不现实的。我每次部署完新证书都会记一个备忘下次检查时间定在到期前两周。实际操作时用openssl直接查远程站点的证书过期时间echo | openssl s_client -connect yourdomain.com:443 -servername yourdomain.com 2/dev/null | openssl x509 -noout -enddate本地证书文件也可以用类似命令查看openssl x509 -in yourdomain.pem -noout -dates看到notAfter字段后和当前日期对比一下如果剩余天数小于30天就可以准备续期了。这里建议到期前两周就动手别卡在最后一天云厂商审核、DNS验证这些环节都可能比你预期的慢。6.2 给证书续期加一个“人肉提醒”脚本自动续期是理想方案但对于大多数用云厂商免费证书的朋友来说免费的证书往往不支持API自动轮换只能到期前手动重新申请。这时候一个靠谱的提醒机制就很重要。最简单的做法是在日历上建重复事件每三个月提醒一次。进阶一点写个crontab脚本每周检查一次证书剩余天数少于30天就发个通知到邮箱或钉钉Webhook。#!/bin/bash # 每天检查证书剩余天数少于30天输出告警 domainyourdomain.com expire_date$(echo | openssl s_client -connect $domain:443 -servername $domain 2/dev/null | openssl x509 -noout -enddate | cut -d -f2) expire_ts$(date -d $expire_date %s) now_ts$(date %s) left_days$(( (expire_ts - now_ts) / 86400 )) if [ $left_days -lt 30 ]; then echo $domain 证书剩余 $left_days 天请尽快续期 fi这段脚本里date -d $expire_date能直接解析openssl输出的日期格式注意不同发行版可能有差异如果解析失败就先手动跑一次看看格式。脚本写好后加到crontab里每周跑一次就够了。6.3 证书文件归档把密钥当钥匙串管理我在文章开头提到要建台账这里补充一下细节。每张证书我用一个独立目录命名方式类似2025-06-yourdomain.com目录里放证书文件、私钥文件、chain文件以及一个README.txt记录申请时间、到期时间、部署服务器、配置文件路径。这样半年后回头看每个证书的背景信息一目了然。私钥文件在这个目录里也要记得设权限。如果归档目录本身在网盘或多台机器间同步建议把私钥单独用zip加密打包密码单独保存。网上有不少因为私钥随压缩包外泄导致域名被恶意使用的案例加密归档是个能救命的小习惯。最后再说几句我个人的经验是SSL证书这类东西最怕的不是技术难度而是“觉得它不重要”。它不像代码上线那样有明确的发布会、灰度验证你部署完那一刻页面看着正常就以为万事大吉了。但恰恰是这种“静默的配置项”最容易在某个不起眼的清晨突然发作。现在每次换证书我都会顺手把提醒日历、检查脚本、归档目录一起更新整套流程固定下来之后反而觉得每个季度折腾一次也不是什么大负担。希望这篇内容能帮你少踩几个我踩过的坑至少下次看到群晖那个“页面不存在”的时候心里能有个大概的排查方向。