引言
HTTPS 协议是 HTTP 的加强版本。HTTPS 基于 HTTP 协议,以 TCP 协议为底层协议,外加 SSL/TLS 协议用于加密和安全认证。默认端口是 443。关于 HTTPS 与 HTTP 的区别请看这里。
对为什么设置 HTTPS 有了认识后,配置证书时以为只需要 nginx -s reload 就完事了,结果浏览器一片红,“不安全”触目惊心。
本篇记录从申请证书到配置 Nginx,再到排查错误,最终实现完美访问的全过程。
一、Nginx 与证书配置——刚起步就熄火
本人使用的服务器是京东云,所以本文配置以京东云服务器为例,腾讯云/阿里云配置流程都相类似。
1. 申请免费证书
进入京东云ssl数字证书管理后台,按照说明申购证书。支付完成后,需进入申购管理页面补全证书信息。
2. 进行域名解析
在申购管理页面点击【详情】可以查看解析值,包括【主机记录】、【记录类型】和【记录值】。进入京东云域名解析管理后台,点击【添加域名】进行添加解析,将解析值填入对应位置后,回到申购管理页面进行【验证】。稍等片刻,有一条显示校验成功即可。接下来静静等待证书签发,时间比较久,耐心等待。
3. 下载 SSL 证书
进入京东云ssl数字证书管理后台,根据服务器安装的类型下载对应的证书。如何判断 web 服务器安装的是否为 Nginx ?在终端输入 curl -I http://127.0.0.1 ,查看 Server 字段即可。该行命令可以查看任何一个网址后台服务器的类型,只需要输入想查看的地址。
查看梦塔世界博客的后台服务器类型:curl -I https://www.dreamtowerworld.top

查看百度的后台服务器类型:curl -I https://www.baidu.com

4. 配置 nginx.conf 文件(以 Nginx 服务器为例)
通过 Termius 远程连接服务器,在 Nginx 安装目录下创建【cert】目录,并将下载的证书文件和密钥文件拷贝到【cert】目录中,Termius 有可视化的文件上传界面,非常方便。
输入 whereis nginx 查看 Nginx 的安装路径,确认配置文件在 /etc/nginx/nginx.conf 中

打开配置文件,内容部分如下

可以看到在 nginx.conf 文件中没有 server 相关配置,有可能是写到别的文件中做引入处理。文件底部一行写有 inclue /etc/nginx/conf.d/*.conf,进入 /etc/nginx/conf.d/*.conf 目录中,找到了 default.conf 文件并打开,发现 server 的相关配置确实在这里。

根据图中内容,主要修改红框部分内容,配置文件里如果没有需要补齐。
# 配置如下
server {
listen 443 ssl; #SSL协议访问端口号为443。此处如未添加ssl,可能会造成Nginx无法启动。
server_name localhost; #将localhost修改为证书绑定的域名,例如:www.example.com 和 example.com,多个域名之间用空格隔开。
ssl_certificate cert/domain name.crt; #将domain name.crt替换成证书文件名。
ssl_certificate_key cert/domain name.key; #将domain name.key替换成证书的密钥文件名。
ssl_session_timeout 5m;
ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4; #使用此加密套件。
ssl_protocols TLSv1 TLSv1.1 TLSv1.2; #使用该协议进行配置。
ssl_prefer_server_ciphers on;
location / {
root html; #站点目录。
index index.html index.htm;
}
}
保存文件后退出,执行 nginx -t 检查配置文件是否出错。如果显示 syntax is ok 和 test is successful 说明正确,可以进行下一步重启;如果报错,根据报错信息修改。

执行 nginx -s reload 重启 Nginx 。
执行 ps aux | grep nginx 命令查看 Nginx 服务当前是否正常运行。

可以看到一共有四个进程。
root 359 … –color=auto nginx 是刚才执行的 grep 命令本身产生的进程,可以忽略。
root 2366 … nginx: master process nginx 是 Nginx 的主进程,它由 root 用户运行,负责读取配置文件、管理 worker 进程。
nginx 25448 … 和 nginx 25736 … 这两个是 Nginx 的工作进程,由 nginx 用户运行。工作进程的数量通常等于 CPU 核心数,负责处理用户的 HTTP 请求。
服务已经成功运行,最后需要将 Nginx 平滑重载配置,执行 nginx -s reload 命令。
二、HTTP 到 HTTPS 的跳转——先从小坑踩出来,然后小坑带大坑继续踩
1. 在配置 nginx.conf 文件的时候,listen 字段值除了配置 443 端口,还要加上 ssl
2. server-name 字段配置域名的时候把 www 前缀的域名也加上,使得 Nginx 同时支持 dreamtowerworld.top 和 www.dreamtowerworld.top 两个地址转发。
3. ssl 证书路径采用绝对路径,配置的文件一定是 .crt 和 .key 结尾的文件,有些云厂商还会有其他的文件,比如 .pem 文件,注意不要配错。
4. 如果发现配置没有问题,网页依旧访问失败,查看后端程序是否启动成功,需要查看proxy_pass http://127.0.0.1:9001; 这一行代表 Nginx 把请求转发给后端的 9001 端口,如果后端程序没有启动成功,网页会报 502 Bad Gateway。验证 9001 端口命令 curl -v http://127.0.0.1:9001,如果返回 Connection refused,说明后端服务启动失败。
上面全部配置完成后,网站访问依旧显示不安全,继续排查错误。
三、终极 BOSS——应用层的“死循环”
命令行输入 curl -vI https://www.dreamtowerworld.top 检查证书和域名是否匹配。
返回的结果如下:

先来说结论:由于博客网站基于 WordPress 搭建完成,WordPress 的默认配置与 Nginx 配置相冲突导致“死循环重定向”。
1. Nginx 工作正常:SSL Connection using TLS … 说明 HTTPS 证书握手成功了,Nginx 已经正确加载了证书。
2. 请求被后端接管:X-Power-By: PHP/7.4.30 和 X-Redirect-By: WordPress 说明请求已经成功穿透 Nginx,但是是通过重定向到达了后端 WordPress 程序。
3. 发现问题所在:在命令行中输入的命令想要访问 https://www.dreamtowerworld.top,结果后端服务 WordPress 返回了301 Moved Permanently,重定向目标为 Location: https://117.72.48.129/,显示的是服务器的 IP 地址,而非域名。
具体来讲,WordPress 数据库里记录的“站点地址”是 IP 地址(https://117.72.48.129/),而非域名。当用户访问域名时,与 WordPress 数据库中记录的不一样,于是服务强制把域名重定向回它认为正确的地址,即 IP 地址。而我们的 Nginx 又配置了访问 IP 必须跳回域名,这就形成了 域名-> IP -> 域名-> IP 的死循环,导致浏览器显示“重定向次数过多”或“不安全”。
4. 解决方案:登录服务器,修改 WordPress 的配置,将网址从 IP 改为域名。先找到配置文件 wp-config.php,输入命令 find / -name wp.config.php 可以找到路径

找到路径,打开配置文件,找到 /* That’s all, stop editing! Happy publishing. */ 这一行,在它的上方添加以下两行代码:
define('WP_HOME', 'https://www.dreamtowerworld.top');
define('WP_SITEURL', 'https://www.dreamtowerworld.top');
wp.config.php 文件截取如下

保存退出后,再次测试。在终端中输入 curl -vI https://www.dreamtowerworld.top

不再出现 Location: https://117.72.48.129/,而且状态码变为 HTTP/1.1 200 OK。
四、总结
经过排查错误,最终浏览器地址显示正常,curl -vI 也成功返回 200 OK,无奇怪的重定向问题,手机访问也正常。
回顾整个流程:DNS->Nginx->SSL-> App Config
配置服务器不仅是改配置文件,更是理解数据流向的过程!
五、本文涉及的 Linux 命令
1. curl -I 和 curl -vI 和 curl -v
这两个命令都是向网址链接发送请求,区别在于 -v 参数,v 是 verbose 的缩写,代表详细模式。
简单来讲:
curl -I :只看结果(响应头)。适合快速检查状态码、重定向目标。
curl -vI:看全过程(握手细节+请求头+响应头)。适合排查 SSL 证书问题、连接失败原因、协议版本等深层故障。
curl -v:看真·全过程。会把整个通信过程的每一个细节都打印到屏幕上,当然也包括响应体和前端界面的 HTML 代码。
具体来讲:
curl -I 会发送一个 HEAD 请求,只获取服务器返回的响应头部信息,不下载网页内容(body)。其中返回的内容包括 HTTP 状态码(如 200 OK,301 Moved)和响应头(如 Server、Date、Content-Length、Content-Type、Location)
适用场景:快速检查网站是否存活,检查是否有重定向(看 Location 字段),检查服务器类型或缓存策略。
curl -vI 依然只会发送一个 HEAD 请求,但是返回结果会更详尽。除了 -I 所展示的信息外,还会显示连接过程(正在解析 DNS、正在连接哪个 IP、端口是多少)、SSL/TLS 握手细节(使用的 TLS 版本、服务器证书详情:颁发者Issuer,有效期Start/Expire date,主题Subject/CN)、完整的请求头(发送给服务器的确切数据:User-Agent、Host 等)以及完整的响应头(服务器返回的原始数据)。
适用场景:排查 SSL 证书问题,排查连接超时或被防火墙拦截,查看具体的 TLS 协议版本是否过旧。
curl -v 会展示连接细节、SSL/TLS握手、完整的 HTTP 请求头、完整的 HTTP 响应头、网页内容。
2. whereis 和 find
这两个命令都是在 Linux 下查找文件的命令,但是各自适用场景不一样。
简单来讲:
whereis:是“查户口”。它只找特定的系统文件,速度极快,因为它查的是系统预建的数据库。
适用场景:查找软件所在位置,比如查找 nginx 相关的安装路径和配置路径:whereis nginx
find:是“地毯式搜索”。它可以遍历整个磁盘,按文件名、大小、时间、权限等任意条件查找,功能强大但速度较慢。
适用场景:递归地遍历每个字目录找到符合条件的文件,比如查找 wp-config.php 文件的位置:find / -name wp-config.php,表示从根目录 / 开始查找名为 wp-config.php 的文件
3. nginx -s reload
重新加载 Nginx 的配置文件,不会中断服务
4. ps aux | grep nginx
这条命令由三部分组成,通过管道符 | 连接:
ps aux | grep nginx
↑ ↑ ↑
│ │ └─ 3. 过滤关键词:只保留包含 "nginx" 的行
│ └─ 2. 管道符:将前一个命令的输出,作为后一个命令的输入
└─ 1. 列出进程:显示系统中所有用户的所有进程的详细信息
ps(Process Status):查看当前进程状态的快照
aux:传给 ps 的参数,决定显示的格式和范围
|:竖线代表不让 ps 的结果直接打印到屏幕,而是将所有的进程信息输送给 grep 处理
grep:文本搜索工具,用于从输入流中匹配特定字符串
所以这条命令可以在所有进程中快速筛选与 Nginx 相关的进程信息。
深入解析 ps aux 之为什么要加 aux ?
ps 默认只显示当前终端下的当前用户进程。如下所示,当前终端只有常驻进程 bash 和刚刚启动的 ps 这两个进程。

为了看到全系统的进程,需要以下参数:
a:显示所有用户的进程(不仅仅是 root 的)
u:以用户友好的格式显示(包括 CPU、内存、启动时间等详细信息)
x:显示没有控制终端的进程(很多后台服务如 Nginx、MySQL 都是守护进程,没有终端,不加 x 就看不到它们)
所以当运行 ps aux 时,可以看到全系统的进程,每一列的含义是排查问题的关键:

| 列名 | 全称 | 含义解读 | 运维排查价值 |
|---|---|---|---|
| USER | User | 进程所有者 | 检查权限问题。 |
| PID | Process ID | 进程唯一标识符 | 最重要。用于 kill -9 <PID> 杀掉卡死的进程,或 top -p <PID> 单独监控。 |
| %CPU | CPU Usage | CPU 占用率 (%) | 重要监控参数 |
| %MEM | Memory Usage | 物理内存占用率 (%) | 检查是否有内存泄漏。 |
| VSZ | Virtual Size | 虚拟内存大小 (KB) | 进程申请的全部内存(包含未使用的)。通常参考意义不大。 |
| RSS | Resident Set Size | 常驻内存 (KB) | 真实占用的物理内存。排查内存溢出时主要看这个。 |
| TTY | Teletype | 终端类型 | ? 表示后台守护进程(正常);pts/0 表示你在某个终端窗口启动的。 |
| STAT | State | 进程状态 (重点!) | S: 睡眠 (Sleeping, 正常) R: 运行 (Running) D: 不可中断睡眠 (通常在等磁盘 IO,危险) Z: 僵尸进程 (Zombie, 父进程没回收,需处理) s: 会话首领 (Session leader) <: 高优先级 例如 Ss 表示:睡眠 + 会话首领。 |
| START | Start Time | 启动时间 | 判断进程是否刚重启过,或者已经运行了很久没更新。 |
| TIME | CPU Time | 累计占用 CPU 时间 | 注意:这不是运行时长,而是真正消耗 CPU 的时间。如果进程跑了10天,TIME 只有 1 分钟,说明它很空闲。 |
| COMMAND | Command | 启动命令及参数 | 查看加载的配置文件路径。 |
深入解析 grep nginx
接收 ps aux 输出的所有文本行,逐行扫描,只要行里包含字符串 nginx,就打印出来,值得注意的是,grep nginx 对大小写敏感,不会匹配到 Nginx。如果需要忽略大小写,加 -i 参数:grep -i nginx。如果需要排除 grep 本身进程,可以加入 -v 参数,表示反向选择:ps aux | grep nginx | grep -v grep
适用场景:
场景A:查看 Nginx 占用了多少内存?
关注 RSS 列。如果 Worker 进程的 RSS 异常高,可能配置了过大的缓冲区或有内存泄漏
场景B:找出卡死的 Worker 进程
如果某个 Worker 的 STAT 是 D 或者 R 且 %CPU 极高,那么记下它的 PID,查看它正在处理什么(适用 strace -p <PID>),然后杀掉:kill -9 <PID>
场景C:统计 Nginx 进程总数
ps aux | grep nginx | grep -v grep | wc -l
其中 wc -l 用于统计数,通常是 1(master) + N(workers)。如果在 nginx.conf 配置文件中配置了 worker_processes auto; 那么统计结果应该是 CPU 核心数 + 1。

No responses yet