
在阿里云买了域名、把网站搭起来之后我遇到的第一件尴尬事是浏览器地址栏里那三个字——不安全。域名解析没问题、页面能打开、内容也没毛病但就是因为站里跑的还是HTTP明文协议SSL证书一张都没有任何访客打开都会被浏览器标记为不安全的站点。其实这个问题在个人开发者里非常普遍。你在阿里云买了个域名租了一台服务器辛辛苦苦把网站搭起来但用的是HTTP协议也就是明文传输。浏览器一看到走的是HTTP立刻会降低信任等级轻则显示不安全重则某些功能被限制。想要消除这个提示、把网站变成真正的HTTPS访问核心动作就一个申请一张SSL证书把它配置到服务器上让网站的流量通过TLS加密隧道传输。这篇文章把我从买域名到成功实现HTTPS访问的完整过程写出来重点讲阿里云的数字证书管理服务里免费的个人测试证书怎么申请、怎么在Nginx下配置、HTTP怎么自动跳转到HTTPS以及我在换证书的过程中踩过的几个坑。刚入门的站长、正在折腾个人博客的朋友照着走一遍基本都能通。1. 为什么域名弄好了浏览器还提示不安全1.1 HTTP和HTTPS最直观的差别先说明一下基础概念。HTTP是超文本传输协议它本身不包含任何加密机制。你输入账号密码、提交表单、上传文件这些内容在网络里都是明文传输的沿途任何一个节点都有可能截获并直接阅读。可以把它理解成寄明信片写什么内容中途经过的邮局、分拣员都看得一清二楚。而HTTPS是在HTTP外面套了一层TLS加密协议相当于把明信片装进一个只有收件人才能打开的保险箱再寄出去。TLS负责加密证书负责证明这个保险箱确实是属于你的。至于SSL和TLS的关系SSL是TLS的前身现在实际使用的都是TLS协议但大家叫习惯了证书领域仍然统一叫SSL证书。所以你在阿里云控制台看到SSL证书数字证书管理服务这些入口指的都是同一个东西。1.2 浏览器到底在验证什么证书在HTTPS里的作用主要有三块身份校验确认这个网站真的是域名对应的持有者。数据加密浏览器和服务器之间协商出一套对称加密密钥后续数据都走加密通道。完整性保护数据在传输中被篡改接收方能够发现。整个TLS握手的流程简化一下就是四步。第一步浏览器发起连接请求第二步服务器把自己的证书里面带有公钥发给浏览器第三步浏览器验证证书是否由受信任的CA签发、域名是否匹配、证书是否过期第四步验证通过后浏览器和服务器各自用随机数协商出同一个会话密钥之后所有HTTP数据都用这个密钥做对称加密传输。受信任的CA这一点值得多说一句。浏览器内置了一批公共CA机构的根证书只有这些CA签发的证书才会被信任。如果证书不是公共CA签的而是自己用OpenSSL随便生成的自签名证书浏览器也会弹警告。所以正规做法是去阿里云这类平台申请一张由正规CA机构签发的证书哪怕是最便宜的那种DV证书也比自签名强得多。2. 阿里云免费SSL证书的真实情况类型、配额与有效期2.1 个人测试证书和付费证书差在哪阿里云控制台里最常见的免费证书叫个人测试证书也叫免费证书或DV单域名证书。它和付费证书的区别主要体现在下面这几点对比项个人测试证书免费付费证书以DV/OV/EV为例验证级别仅验证域名所有权DV验证域名OV/EV还会验证企业身份支持域名数量单张证书只能绑定一个具体域名可支持单域名、多域名、通配符域名浏览器显示效果有锁标志但无企业名OV/EV证书地址栏会显示企业信息有效期目前通常为3个月左右通常为1年不同服务商有差异签发速度几分钟到几小时分钟级到工作日不等适用场景个人博客、测试环境、个人API企业官网、电商、金融类业务免费证书本质上是一张DV证书它只能证明你拥有这个域名但不能证明你是一家合法注册的公司。对个人博客、学习项目、微信小程序后台接口来说完全够用。如果你在做企业官网尤其是涉及支付、登录、用户隐私的站点建议至少上付费的OV证书地址栏的企业名称对用户信任度有实质提升。2.2 免费背后的三个限制第一有效期很短。阿里云免费证书目前签出来的有效期通常只有3个月到期后需要重新申请换发。这是整个流程里最容易被忽略的坑很多人申请完就忘了三个月后网站突然打不开或者报证书过期才反应过来。第二免费额度有数量限制。阿里云免费证书不是无限量随便申请的控制台的免费证书配额页面会显示你剩余的申请张数如果短时间申请太多触发额度上限会提示暂时无法继续创建。具体额度数值建议以控制台当前显示为准。第三不支持通配符域名。一张免费证书只能绑定一个具体的域名比如www.example.com和example.com是两个完全不同的域名需要分别申请两张证书。如果你希望一张证书搞定*.example.com下面所有子域名那得选择付费的通配符证书。2.3 标题里的自动配置到底指什么很多人被自动配置这个词吸引进来结果发现好像还是要手动操作。这里把自动拆成三种情况你对号入座第一种是阿里云控制台的云产品部署。证书签发后在控制台点部署可以直接把证书推送到SLB、CDN、OSS、WAF这些阿里云产品上。如果你的网站本身就跑在负载均衡或CDN后面这种方式确实算自动部署不需要登录服务器改文件。第二种是手动下载证书后配置到自建Nginx。这种场景下阿里云并不提供全自动但实际过程也就是下载两个文件、上传到服务器、改一下Nginx配置、reload十分钟之内能完成。第三种是彻底的自动化用acme.sh这类客户端配合DNS API申请并自动续期Lets Encrypt证书。域名从阿里云买完全没问题证书提供商换成Lets Encrypt一样免费而且可以通过cron实现到期前自动续期。如果你追求的是一辈子不管那直接研究acme.sh才是正路。3. 申请前的准备工作域名解析和443端口3.1 域名解析是否真的指向了服务器IP申请证书本身不要求域名一定解析到你的服务器因为域名验证是单独做的。但证书配置完之后HTTPS访问要生效域名必须正确指向服务器IP。建议在申请之前就把这一步做掉后面能少很多排查时间。登录阿里云控制台在域名产品里进入域名列表找到你的域名点解析设置。添加一条记录主机记录www记录类型A记录值你的ECS公网IPTTL用默认600。如果你打算让用户直接访问不带www的根域名就再添加一条主机记录为的A记录。解析生效后用ping或nslookup验证一下确认域名解析出来的IP和服务器公网IP一致。这一步经常有新手卡住以为添加了解析就立刻生效实际上运营商DNS缓存可能需要几分钟耐心等一下再用nslookup确认。3.2 安全组和服务器防火墙都要放行443端口这个坑是我见过最多的。有人Nginx配置完全正确、证书文件路径也正确、nginx -t也通过浏览器就是打不开HTTPS页面折腾半天发现ECS安全组没有放行443端口。阿里云ECS默认只放行22、80等少数端口443通常需要手动加。操作方法ECS控制台 → 实例 → 安全组 → 配置规则 → 入方向 → 手动添加协议类型选TCP端口范围填443/443授权对象填0.0.0.0/0描述写HTTPS。授权对象填0.0.0.0/0意味着所有人可以通过443端口访问你的服务这是Web服务的正常姿势不用担心。安全组放行后还要确认ECS系统内部的防火墙没有拦截。如果你用的是CentOS并且装了firewalld执行firewall-cmd --permanent --add-servicehttps firewall-cmd --reload如果是Ubuntu且启用了ufw执行ufw allow 443/tcp验证端口是否真的在监听在服务器本机执行ss -lntp | grep 443能看到nginx监听443就说明Nginx起来了。从你本地电脑用telnet 服务器IP 443测试一下如果通说明安全组和防火墙都放行了。4. 控制台申请个人测试证书从创建名额到下载文件4.1 找到免费证书入口登录阿里云控制台在顶部搜索框直接搜SSL证书或数字证书管理服务就能进入证书管理控制台。左边菜单找到证书申请或SSL证书相关页面里面会显示免费证书区域和你的剩余配额。阿里云控制台界面改版过很多次入口位置可能略有变化认准数字证书管理服务这个产品名就不会迷路。4.2 创建证书并填写申请信息进入免费证书页面后先点创建证书。这一步相当于占一个免费名额创建成功后会生成一条证书订单记录。然后点击该证书后面的证书申请进入填写页面绑定域名填你要保护的完整域名比如www.example.com。注意不要带http://或https://。联系人信息填真实可用的邮箱和手机号。证书到期前阿里云会通过这些方式发提醒虽然我建议你自己也设一遍日历提醒但平台提醒仍然值得留着。提交后进入域名验证阶段。如果你的域名DNS正好在阿里云管理系统有可能直接提供一键添加解析的入口如果不在就按页面给出的解析记录去对应DNS平台手动添加。这一步比较关键下面单独说。4.3 域名验证DNS验证比文件验证更省心阿里云免费证书常用的验证方式有两种验证方式操作内容适用场景DNS验证在域名解析里添加一条CNAME或TXT记录有DNS管理权限推荐使用文件验证将CA提供的一个文本文件放到网站根目录指定路径能操作服务器但DNS不在手里我用下来的体会是能走DNS验证坚决走DNS验证。原因很简单DNS验证不用管服务器上跑的是什么Web软件、网站根目录在哪里、Nginx有没有正常启动只要解析记录添加正确CA侧就能通过域名解析完成验证。以阿里云为例申请页面会给出类似主机记录_dnsauth、记录值dnsauth.example.com.xxxxxxxx这样的CNAME记录。去域名解析控制台添加这条解析记录时注意主机记录里的_开头不要漏掉记录值也要完整复制。添加完成后回到证书申请页面点验证通常会显示验证通过。整个签发过程一般几分钟到几小时不等我实际测试时大多在几分钟内就完成了。用文件验证的场景我也遇到过比如域名在某个不常登录的第三方DNS系统里。此时需要把CA给的验证文件上传到服务器网站根目录的/.well-known/pki-validation/路径下CA会通过HTTP访问这个文件来确认你对域名的控制权。需要注意如果网站还没有配好Web服务器或者根目录路径不对文件验证会一直卡在验证中状态没有DNS验证那么省心。4.4 下载证书文件认识.pem和.key证书签发成功后在证书列表点下载。下载页面会让选择服务器类型Nginx、Apache、Tomcat、IIS都有对应打包。如果服务器是Nginx选择Nginx下载。解压后会得到两个文件.pem文件这是公钥证书文件里面通常包含了服务器证书和CA中间证书链。Nginx配置里的ssl_certificate指向它。.key文件这是私钥文件极其敏感。Nginx配置里的ssl_certificate_key指向它。私钥文件千万不要提交到Git仓库不要发给任何人不要放在网站根目录。谁拿到这个私钥谁就拥有了你用这个域名跑HTTPS服务的完整能力。我见过有人把xxx.key直接丢在项目目录里然后项目压包上传服务器时顺手传了幸好及时发现不然后果很严重。5. 服务器端配置Nginx证书上传、监听、跳转与验收5.1 证书文件上传服务器的目录规划拿到.pem和.key之后先在服务器上规划一个专门存放证书的目录。我的习惯是mkdir -p /etc/nginx/cert然后把两个文件上传到这个目录。用scp命令在本地终端执行scp /本地路径/www.example.com.pem root服务器IP:/etc/nginx/cert/ scp /本地路径/www.example.com.key root服务器IP:/etc/nginx/cert/上传完成后立刻调整权限避免私钥被其他用户读取chmod 644 /etc/nginx/cert/www.example.com.pem chmod 600 /etc/nginx/cert/www.example.com.keychmod 600意味着只有root用户能读写私钥文件Nginx主进程如果用root启动worker进程在读取证书文件时也不会受到权限阻滞。如果你用的是非root用户启动Nginx权限可能需要适当放宽到640但一定不要让key文件对所有人可读。5.2 Nginx增加SSL监听配置Nginx配置的写法因安装方式略有差异。用apt install nginx或者yum install nginx安装的主配置文件通常在/etc/nginx/nginx.conf站点配置常见于/etc/nginx/conf.d/或/etc/nginx/sites-available/。不管放在哪里核心server块是一样的。下面是一个最简可用的HTTPS server块server { listen 443 ssl; server_name www.example.com; ssl_certificate /etc/nginx/cert/www.example.com.pem; ssl_certificate_key /etc/nginx/cert/www.example.com.key; ssl_session_cache shared:SSL:10m; ssl_session_timeout 10m; ssl_protocols TLSv1.2 TLSv1.3; 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; ssl_prefer_server_ciphers on; root /var/www/html; index index.html index.htm; }逐个解释几个参数。ssl_session_cache和ssl_session_timeout是TLS会话复用的优化手段开启后同一个客户端在超时时间内再次请求可以跳过完整握手过程显著降低HTTPS请求的延迟。ssl_protocols我们只保留TLSv1.2和TLSv1.3TLSv1.0和TLSv1.1已经被淘汰浏览器基本不再支持留着只会变成靶子。ssl_ciphers是加密套件列表只要遵循禁用空加密、禁用MD5、禁用RC4的大原则再用Mozilla的SSL配置生成器生成一份稳妥列表基本不会出问题。如果你是较新版本的Nginx1.25.1之后listen 443 ssl后面不再建议直接写http2参数而是在server块内单独写http2 on;来开启HTTP/2。这个特性对性能有帮助但属于可选项可以等HTTPS跑通之后再研究。5.3 80端口配置301跳转到HTTPS证书配置好之后如果用户输入http://www.example.com依然会走80端口此时服务器需要返回一个301跳转把人引导到HTTPS地址上。最简单可靠的做法是单独写一个80端口的server块server { listen 80; server_name www.example.com example.com; return 301 https://$host$request_uri; }这里用$host保留用户访问时输入的域名用$request_uri保留路径和请求参数这样跳转后URL不会丢掉任何信息。比如用户访问http://www.example.com/blog?id1会原样跳转到https://www.example.com/blog?id1。不建议在同一个server块里用if ($scheme http) { return 301 ... }这种写法因为Nginx的if在server级别的配置里有一些历史遗留的坑拆成两个server块更清晰运维上也更好维护。5.4 reload之后怎么确认真的生效配置改完先检查语法nginx -t看到syntax is ok和test is successful两条信息后平滑重载systemctl reload nginx然后从本地执行几个验证命令。先看HTTP头信息curl -I https://www.example.com如果返回200并且HTTP/1.1 200 OK前面没有证书告警说明至少通了。再看证书信息openssl s_client -connect www.example.com:443 -servername www.example.com 2/dev/null | openssl x509 -noout -dates这条命令会直接打印证书的开始日期和结束日期用于确认服务器加载的是不是最新那张证书。最后用浏览器访问一次地址栏出现锁标志点击锁标志还能看到证书详情和连接类型。如果你配置了80跳转再访问一次http://www.example.com浏览器地址栏应该会自动变成https://开头。6. 实测踩坑记录证书不匹配、TLS版本、换证流程、部署方式6.1 配置写错文件导致Nginx拒绝启动先讲症状修改配置后执行nginx -t直接报错nginx: [emerg] BIO_new_file() failed (/etc/nginx/cert/www.example.com.pem) nginx: configuration file /etc/nginx/nginx.conf test failed这类问题的排查链路其实很固定。第一步检查路径是不是拼错了文件名和目录名大小写有没有问题。第二步检查文件权限ls -l看key文件的权限位确保启动Nginx的用户可读。第三步检查pem和key是不是匹配的一对。验证pem和key是否匹配的方法也很简单把两个文件各自的modulus取出来做md5对比openssl x509 -noout -modulus -in /etc/nginx/cert/www.example.com.pem | openssl md5 openssl rsa -noout -modulus -in /etc/nginx/cert/www.example.com.key | openssl md5两个命令输出的一致说明公钥和私钥确实配成一对不一致那就说明中间某个环节拿错文件了最常见的是申请证书时用了www域名下载证书时却下了另一个域名的包。我还遇到过一种情况pem文件被Windows记事本打开保存过导致换行符被改变Nginx读取时报错。解决办法是永远不要用记事本编辑证书文件上传前也不要二次另存为。如果必须编辑用vi或者nano并确认首行和尾行的BEGIN/END标识完整。6.2 TLS协议版本和加密套件配置别让老设备全部报错有朋友按照网上老教程配置完电脑浏览器能正常打开但手机上一部分老App或者旧版安卓WebView会报SSL连接错误或者服务器不支持SSL。排查到最后发现是ssl_protocols里面写了SSLv3 TLSv1 TLSv1.1这类古老版本或者只写了TLSv1.3导致不兼容。处理原则很简单ssl_protocols只保留TLSv1.2 TLSv1.3。TLSv1.3虽然更先进但某些老设备只支持到1.2如果只开1.3它们就彻底连不上。1.2和1.3并存是最稳的配置安全性和兼容性兼顾。加密套件方面用我上面示例里那一串ECDHE-RSA-AES128-GCM-SHA256开头的列表即可核心思想是优先使用现代AEAD加密套件把!aNULL、!MD5、!RC4这些风险套件全部排除掉。配置完成后可以用myssl.com或者本地openssl工具检查评级个人站点能拿到A级就完全够用了。6.3 免费证书有效期短到期换证的正确姿势前面说过免费证书目前通常是3个月有效期。阿里云会在到期前发短信/站内信提醒但个人开发者的邮箱和短信经常被淹没我的建议是自己设置一个提前30天换证的日历提醒。换证流程和第一次申请几乎一模一样回到数字证书管理服务控制台在免费证书页面重新创建证书订单。对新的证书订单发起证书申请域名填和旧证书一样的域名。域名验证方式走DNS验证添加解析记录。如果域名在阿里云DNS且系统提供一键添加直接点掉。新证书签发后下载Nginx格式得到新的pem和key文件。把新文件覆盖到服务器/etc/nginx/cert/目录注意文件名建议带域名便于新旧区分。执行nginx -t确认语法正确然后systemctl reload nginx。用openssl s_client命令验证新证书的到期时间。注意一点免费证书的换证不是简单的点击续期它本质上是一次重新的申请签发流程。所以我的习惯是把换证步骤写成一个checklist贴在自己的笔记里这样每3个月照做一遍不会遗漏。千万别拖到到期当天才处理。我有一次就是到期前一天发现还没换手忙脚乱地申请、下载、配置虽然最后赶上了但中间十分钟网站出现证书错误提示恰好有用户访问体验非常糟糕。免费证书本身就是高危提醒器每次到期都在提醒你HTTPS这件事必须长期维护。6.4 一键部署和手动部署到底该选哪个如果你用的是阿里云SLB或CLB这类负载均衡或者挂了CDN控制台的部署功能确实很方便。选中证书点部署选择目标云产品系统会把证书自动推送到对应产品上免去每台机器手动替换的麻烦。这种场景下控制台部署至少能帮你省掉一半的重复工作。如果你只是单台ECS自建Nginx我更推荐手动部署。原因有三个。第一手动部署时你会顺手检查Nginx配置是否正常对服务器状态心里有数。第二证书文件落在自己服务器上将来迁移主机或切换Nginx环境时更灵活不会受制于控制台的部署记录。第三控制台对自建Nginx的部署支持不如SLB/CDN那样无感有时候部署完还要去服务器手动核对反而多一道工序。至于自动续期阿里云免费证书目前还做不到完全无人值守。如果你确实不想每三个月手动折腾一次我建议直接上acme.sh配套Lets Encrypt的方案把acme.sh安装到服务器配置DNS API后它会自动完成域名验证、证书签发、部署到Nginx、到期自动续期真正做到全自动。域名放在阿里云毫无影响只是证书签发机构从阿里云集成的CA换成了Lets Encrypt。两条路径我都试过阿里云免费证书适合偶尔运维的轻量站点acme.sh适合彻底托管的长期站点两者没有高下只有场景差异。最后说点实在的对个人站点来说HTTPS现在已经不是加分项而是默认项。域名、服务器、HTTPS这三件事应该是动手做网站第一天就配齐的基础设施而不是访客都到门口了才临时补的窟窿。我个人每次换证书都固定走一遍流程控制台重新申请、下载Nginx格式、覆盖服务器文件、nginx -t、systemctl reload nginx、再用openssl验证有效期全程五到六分钟。如果这一篇能帮你把第一次配证书的时间从半天缩短到半小时那它就没白写。关于自动配置再强调一句别指望点了申请之后什么都不用管。阿里云免费证书到现在还是要到期手动换发的控制台的云产品部署也只适用于SLB/CDN这类托管产品。想要真正的自动续期就老老实实研究acme.sh那套自动化。先把这篇里的手动流程走通再考虑去自动化顺序千万别反。