📘 《服务器运维》模块一 · 学生实操笔记 · Rocky Linux 9

从裸奔到上锁
三讲服务器运维笔记

按「每章做了什么 → 用了什么命令 → 遇到的问题和解决办法」重新整理三讲教材,配套验证清单与命令速查,可搜索、可折叠、可一键复制,全部离线可用。

3讲课程
37个操作步骤
162条命令
30个问题/陷阱
24项验证清单

学习路线 · 三讲全景

从「守住门」到「开出门」再到「上安全锁」,一步依赖一步

贯穿三讲的三条铁律🔑 私钥永不外传SSH 私钥 / 只装老师的公钥 / privkey.pem🚪 改配置先留后路VNC 自救 / mysite.conf.bak 备份✅ 先验证再收口密钥先登录 / sshd -t、nginx -t / --dry-run
01
《服务器运维》模块一 · 第 01 讲

服务器安全加固

让你的第一台服务器学会自我防护

阿里云 ECS · Rocky Linux 9.8 · 2核2GSSH 密钥认证VNC 后路firewalld + 安全组fail2ban
本章一句话

把一台「裸奔」的服务器,加固成只认密钥、守得住、还会自动反击的机器。本章不改 SSH 端口。

学完本章,你将能够 点击展开
  • 说清 SSH 密钥认证原理,配置密钥登录并安全禁用密码登录
  • 理解并配置「安全组 + 主机防火墙」两层防护,读懂 ICMP 与端口的关系
  • 用 fail2ban 让服务器自动封禁暴力破解者
  • 把自己锁在门外时,用 VNC 完成自救
01

本章做了什么

12 个关键步骤
  1. 01

    看见威胁

    用 journalctl 调出 sshd 日志,看到大量陌生 IP 对 root 的失败登录,确认暴力破解真实存在,确定「攻击者会从哪里进来」这条主线。

  2. 02

    分清两条登录通道

    SSH / Workbench 走公网 22 端口、受 sshd 管辖;VNC 走阿里云带外管理通道,不经过安全组与 sshd —— 真正能救命的后路是 VNC。

  3. 03

    准备普通用户

    新建 study、设置密码、加入 wheel 组,为稍后禁止 root 远程登录做准备。

  4. 04

    亲自走通 VNC

    控制台 VNC 登录 study,用 whoami 与 tty 确认是 /dev/tty1 本地终端,再 exit 退出;后路只有走通过一次才靠得住。

  5. 05

    本机生成密钥对

    ssh-keygen -t ed25519 生成密钥对,私钥从诞生起只留在自己电脑,复制公钥准备安装。

  6. 06

    安装公钥并卡死权限

    写入 ~/.ssh/authorized_keys,目录 700、文件 600、属主本人,避开「SSH 静默拒绝、不给报错」这个最难排查的坑。

  7. 07

    铁律:先验证再收口

    回自己电脑 ssh study@公网IP 免密登录成功,才允许去禁用密码 —— 顺序反了就会把自己关在门外。

  8. 08

    配置 teacher 巡检账号

    只装老师的公钥,绝不交出自己的私钥;因 teacher 无密码,单独写免密 sudo 规则并用 visudo -c 校验语法。

  9. 09

    加固 sshd_config

    开密钥、禁密码、禁 root、限尝试次数、清空闲会话、设 AllowUsers 白名单;sshd -t 通过后 reload 生效。

  10. 10

    两层门最小化放行

    firewalld 加 --permanent 再 --reload 只放行 ssh;安全组保留 22 与 ICMP,读懂「ICMP 端口=任何」不是漏洞;ss -tlnp 对照实际监听。

  11. 11

    部署 fail2ban 自动反击

    装 EPEL 源,在 jail.d/sshd.local 写规则(Rocky 9 必须 backend = systemd),10 分钟失败 3 次封禁 1 小时,启动后查看 Banned IP list。

  12. 12

    验证与提交

    逐项核对 9 条清单;只向老师提交公网 IP,老师用自己的私钥登录检查。

02

用了什么命令

52 条 · 8 组

命令均以等宽字体代码块呈现,灰色 ↳ 行是作用说明(不会被复制);点击代码块右上角「复制全部」或组标题右侧「复制本组」即可带走该组命令。

威胁排查 · 看见正在发生的暴力破解

bash
sudo journalctl -u sshd | grep -i "failed" | tail -30↳ 查 sshd 系统日志 → 只筛含 failed 的行(-i 忽略大小写) → 只显示最后 30 条whoami↳ 显示当前登录用户名,VNC 下应为 studytty↳ 显示终端设备:VNC 为 /dev/tty1,SSH 为 /dev/pts/0 —— 从系统内部印证两条独立通道exit↳ 退出 VNC 登录

准备普通用户 study

bash
sudo adduser study↳ 新建普通用户;把 study 换成自己的用户名sudo passwd study↳ 设置登录密码(按提示输入两次)sudo usermod -aG wheel study↳ 加入 wheel 组,只有 wheel 成员才能用 sudo 执行管理员命令

生成密钥对(在自己的电脑上执行)

bash
ssh-keygen -t ed25519 -C "你的名字-服务器加固"↳ 生成 ed25519 密钥对(现代、短小、安全),一路回车即可;私钥绝不外传type $env:USERPROFILE\.ssh\id_ed25519.pub↳ Windows PowerShell 查看公钥(.pub 结尾)cat ~/.ssh/id_ed25519.pub↳ macOS / Linux 查看公钥;不带 .pub 的那个是私钥

安装公钥到服务器 · 权限一步都不能省

bash
sudo su - study↳ 切换到 study 并加载其环境,此后 ~ 代表 /home/studymkdir -p ~/.ssh↳ 创建 .ssh 目录;-p 表示已存在也不报错chmod 700 ~/.ssh↳ 目录 700:仅本人可进入读写,权限过松 SSH 会直接拒绝使用且不报错vi ~/.ssh/authorized_keys↳ 按 i 进入编辑 → 粘贴公钥(一整行,中间不能换行)→ Esc → :wq 保存chmod 600 ~/.ssh/authorized_keys↳ 文件 600:SSH 强制要求,权限过松会拒绝用它登录ls -l ~/.ssh↳ 核对:authorized_keys 应为 -rw-------,且属主是本人而不是 rootssh study@服务器公网IP↳ 回到自己电脑验证:能直接登入且不要求输密码,才算密钥配置成功

为老师配置巡检账号 teacher

bash
sudo adduser teacher↳ 新建专供老师巡检的账号sudo mkdir -p /home/teacher/.ssh↳ 为 teacher 创建 .ssh 目录sudo vi /home/teacher/.ssh/authorized_keys↳ 贴入【老师发给你的公钥】一整行 —— 注意不是你自己的公钥sudo chmod 700 /home/teacher/.ssh↳ 目录权限 700sudo chmod 600 /home/teacher/.ssh/authorized_keys↳ 文件权限 600sudo chown -R teacher:teacher /home/teacher/.ssh↳ 用 sudo 建的目录属主是 root,必须改回 teacherecho "teacher ALL=(ALL) NOPASSWD: ALL" | sudo tee /etc/sudoers.d/teacher↳ teacher 无密码,wheel 组 sudo 需本人密码,故单独写免密规则sudo chmod 440 /etc/sudoers.d/teacher↳ sudoers 规则文件要求权限 440(只读)sudo visudo -c↳ 检查所有 sudo 配置语法,全部 parsed OK 才算过;写错会让所有账号 sudo 失效sudo -u teacher sudo -n true && echo "teacher 免密 sudo 可用"↳ 以 teacher 身份测试,-n 表示不询问密码

收口:加固 /etc/ssh/sshd_config

/etc/ssh/sshd_config
sudo vi /etc/ssh/sshd_config↳ 打开 SSH 服务端主配置文件PubkeyAuthentication yes↳ 允许密钥登录(本章加固的基础,保持开启)PasswordAuthentication no↳ 禁止密码登录,杜绝被猜密码 —— 务必确认密钥能登录后再改这一项PermitRootLogin no↳ 禁止 root 直接远程登录,缩小攻击面MaxAuthTries 3↳ 单次连接最多 3 次认证尝试,超过即断开,拖慢暴力破解ClientAliveInterval 300↳ 每 300 秒探测一次客户端是否还在ClientAliveCountMax 2↳ 连续 2 次无响应就断开,自动清理空闲会话AllowUsers study teacher↳ 登录白名单:写错用户名或漏掉 teacher,对应的人就会被挡在门外sudo sshd -t↳ 测试配置语法:没有任何输出即正确,有错会指出具体行号sudo systemctl reload sshd↳ 重新加载生效;reload 不会断开当前连接,比 restart 安全

两道门 · firewalld 与端口核对

bash
sudo firewall-cmd --permanent --add-service=ssh↳ 永久放行 SSH;Rocky 上必须加 --permanent,否则重启后规则失效sudo firewall-cmd --reload↳ 重新加载防火墙,让永久规则真正生效sudo firewall-cmd --list-all↳ 列出当前区域放行的服务/端口,核对结果sudo ss -tlnp↳ -t 只看 TCP / -l 只看监听 / -n 数字显示不解析 / -p 显示占用进程;与安全组规则对照

让服务器自动反击 · fail2ban

/etc/fail2ban/jail.d/sshd.local
sudo dnf install -y epel-release↳ 先装 EPEL 扩展源(Rocky 默认源里没有 fail2ban)sudo dnf install -y fail2ban↳ 安装 fail2ban 本体sudo vi /etc/fail2ban/jail.d/sshd.local↳ 在 jail.d/ 写 .local 规则,不直接改 jail.conf —— 软件升级时配置不会被覆盖[sshd]↳ 针对 sshd 服务的防护规则enabled  = true↳ 启用本规则backend  = systemd↳ Rocky 9 关键:日志由 systemd 统一管理;旧教程读 /var/log/secure 在这里不生效maxretry = 3↳ 允许的最大失败次数findtime = 600↳ 统计窗口:600 秒(10 分钟)内累计失败bantime  = 3600↳ 触发后的封禁时长:3600 秒(1 小时)sudo systemctl enable --now fail2ban↳ 启动并设为开机自启(--now 立即启动,enable 开机自启)sudo fail2ban-client status sshd↳ 查看运行状态,重点看 Banned IP list(已被自动封禁的攻击者 IP)
03

遇到的问题和解决办法

9 个
01SSH 连不上了+
可能原因sshd 配置改崩 / 22 端口被封 / AllowUsers 写错
解决办法不要慌,用阿里云控制台 VNC 登录(不走 SSH,不受 sshd 与安全组影响,用系统账号密码登录),把 sshd_config 改回来,再依次执行 sudo sshd -t 验证、sudo systemctl reload sshd 生效。
sudo sshd -t
sudo systemctl reload sshd
02密钥登录总是要求输入密码+
可能原因99% 是权限问题(属主不对 / 权限过松,SSH 静默拒绝且不报错)
解决办法检查 ~/.ssh 是否为 700、authorized_keys 是否为 600、且属主是本人而不是 root。用 ls -l ~/.ssh 核对,三项都对才会生效。
ls -l ~/.ssh
chmod 700 ~/.ssh
chmod 600 ~/.ssh/authorized_keys
03老师连不上你的机器+
可能原因AllowUsers 里漏了 teacher,或 teacher 的 .ssh 目录属主没改回 teacher
解决办法在 sshd_config 的白名单补上 teacher;用 sudo chown -R teacher:teacher /home/teacher/.ssh 改回属主,再 reload sshd。
sudo chown -R teacher:teacher /home/teacher/.ssh
sudo systemctl reload sshd
04sudo 报 sudoers 语法错误,所有账号都用不了 sudo+
可能原因/etc/sudoers.d/teacher 写错(漏了 visudo -c 检查)
解决办法用 VNC 以 root 登录,修正或删除 /etc/sudoers.d/teacher 后再执行 visudo -c 检查;如果忘了 root 密码,可在控制台重置实例密码(重启后生效)。
sudo visudo -c
05firewalld 改了规则不生效 / 重启后丢失+
可能原因忘了加 --permanent,或加了却忘了 --reload
解决办法两条都补上:--permanent 写入永久规则,--reload 让规则真正生效;改完用 --list-all 核对。
sudo firewall-cmd --permanent --add-service=ssh
sudo firewall-cmd --reload
06陷阱:把「我的私钥」发给老师+
可能原因直觉错误 —— 私钥是身份唯一凭证,发出去任何人都能完全控制这台机器
解决办法正确思路恰恰相反:让老师自己生成一对钥匙,你只把【老师的公钥】装到服务器上。公钥本就可以公开,没有对应私钥照样进不来。
07陷阱:照抄旧教程让 fail2ban 读日志文件+
可能原因Rocky 9 日志由 systemd 统一管理,读 /var/log/secure 的老写法不生效
解决办法在 jail.d/sshd.local 里写 backend = systemd;并且规则放进 jail.d/*.local,别直接改 jail.conf(升级会被覆盖)。
08陷阱:Banned IP list 是空的+
可能原因不代表操作有误,只是这台机器目前还没被扫描器盯上
解决办法规则已经生效,让机器挂一段时间自然会出现记录;把它和本章开头的爆破日志对照看。
sudo fail2ban-client status sshd
09陷阱:安全组里 ICMP 规则端口显示「任何 / -1」+
可能原因不是把所有端口都打开了
解决办法安全组按「协议+端口」两维控制;ICMP 是网络层诊断协议,本身不使用端口,-1 只是占位符。放行它只让别人能 ping 通(知道机器在线),既不能登录也不能传数据;保留它还有助于日后判断「网络问题还是 SSH 配置问题」。
04

验证清单

勾选状态自动保存
验证清单0 / 9
05

本章小结

攻击者想做的事你部署的加固
猜密码登进来SSH 密钥登录 + 禁用密码 + 禁止 root
从别的端口钻进来firewalld + 安全组,两层最小化放行
反复爆破 SSHfail2ban 自动封禁
进来了不被发现journal 日志审计
三个受用终身的运维习惯:私钥永不外传 · 改配置先留后路(VNC)· 先验证再收口。
02
《服务器运维》模块一 · 第 02 讲

网站上线

域名解析与 Nginx 个人主页

已备案域名 · Nginx · 阿里云 ECSDNS A 记录放行 80 端口Nginx 站点配置403 排障
本章一句话

为已备案域名配置解析,安装 Nginx,发布带备案号的个人主页,让任何人输入域名都能访问。

学完本章,你将能够 点击展开
  • 说清 DNS 的作用,为域名添加解析记录并验证生效
  • 按需在安全组和防火墙中开放网页访问端口
  • 安装 Nginx、编写站点配置,并安全地让配置生效
  • 发布个人主页,排查 403、404、连接超时等常见故障
01

本章做了什么

13 个关键步骤
  1. 01

    补做 teacher 免密 sudo

    上一章 teacher 没设密码,而 wheel 组成员用 sudo 必须输本人密码,实际用不了 sudo;先补 NOPASSWD 规则并 visudo -c 校验。

  2. 02

    理清上线的三个环节

    DNS 让域名指向 IP → 开门放行 80 → Nginx 接收请求并发出主页,三者缺一不可,排查也按这个顺序。

  3. 03

    先做解析,让等待在后台发生

    添加 A 记录:@ 与 www 都指向公网 IP,TTL 默认 10 分钟;把需要等待的事提前做,是运维常用思路。

  4. 04

    验证解析

    本机 nslookup 查两个域名;暂时查不到或 IP 不对先继续做后面步骤,几分钟后再查。

  5. 05

    最小化开门

    安全组 + firewalld 只放行 80;443 留到下一章配证书时再开 —— 最小化不是什么都不开,而是服务真正上线才开对应的门。

  6. 06

    安装并启动 Nginx

    dnf 安装、enable --now 开机自启、看状态与版本;浏览器访问公网 IP 看到默认测试页,说明 80 已打通。

  7. 07

    准备网站目录

    /var/www/mysite 交给 study、权限 755,之后上传改网页不必 sudo;getenforce 确认阿里云 Rocky 镜像 SELinux 默认 Disabled。

  8. 08

    编写站点配置

    conf.d/mysite.conf 写 server_name / root / index / 双日志 / try_files;server_name 最关键,Nginx 靠 Host 请求头区分站点;nginx -t 通过后 reload。

  9. 09

    发布个人主页

    硬性要求:首页底部必须显示 ICP 备案号并链接工信部备案查询网站;AI 生成或模板修改后必须自己核对;scp 上传或 vi 直接编辑。

  10. 10

    理解 server_name 与 Host

    用 curl -H 手动指定 Host 亲眼验证;用 IP 访问因 Host 不匹配,请求被交给默认站点,所以看到的仍是 Nginx 默认页。

  11. 11

    亲手制造并修复一次 403

    chmod 600 → curl -I 得 403 → 错误日志出现 Permission denied → ps 查到 nginx 工作进程身份 → chmod 644 恢复 200 → 删除测试文件。

  12. 12

    看见第一位访客

    tail -f 访问日志,同学每刷新一次就多一行:来访 IP、时间、页面、状态码、浏览器。

  13. 13

    验证与提交

    逐项核对 7 条清单,向老师提交域名;合规提醒:开通后 30 日内还需办理公安联网备案。

02

用了什么命令

48 条 · 10 组

命令均以等宽字体代码块呈现,灰色 ↳ 行是作用说明(不会被复制);点击代码块右上角「复制全部」或组标题右侧「复制本组」即可带走该组命令。

补做:为 teacher 配置免密 sudo

bash
echo "teacher ALL=(ALL) NOPASSWD: ALL" | sudo tee /etc/sudoers.d/teacher↳ teacher 无密码,wheel 组 sudo 需本人密码,所以用不了,单独写免密规则sudo chmod 440 /etc/sudoers.d/teacher↳ sudoers 规则文件要求权限 440sudo visudo -c↳ 必须全部 parsed OK;写错会让所有账号 sudo 失效,用 VNC 以 root 修复sudo -u teacher sudo -n true && echo "teacher 免密 sudo 可用"↳ 以 teacher 身份验证免密 sudo 是否可用

DNS 解析验证(在自己电脑上执行)

bash
nslookup 你的域名↳ 查询解析结果,看 Address 一栏是不是服务器公网 IPnslookup www.你的域名↳ 带 www 的记录同样要能查到

为网站开门 · 只放行 80

bash
控制台:安全组入方向添加 TCP 80 / 0.0.0.0/0↳ 允许任何来源访问网页;控制台通常也有 HTTP(80) 快速添加选项sudo firewall-cmd --permanent --add-service=http↳ 永久放行 HTTP 服务(即 TCP 80)sudo firewall-cmd --reload↳ 重新加载防火墙,使永久规则生效sudo firewall-cmd --list-services↳ 查看已放行服务,应包含 ssh 和 http

安装与启动 Nginx

bash
sudo dnf install -y nginx↳ 从系统软件源安装,-y 自动确认sudo systemctl enable --now nginx↳ 立即启动并设为开机自启systemctl status nginx↳ 查看运行状态,应显示 active (running),按 q 退出nginx -v↳ 查看 Nginx 版本号

准备网站目录

bash
sudo mkdir -p /var/www/mysite↳ 单独建自己的站点目录,结构清晰,以后加第二个站点不互相干扰sudo chown -R study:study /var/www/mysite↳ 把目录交给 study,之后上传和修改网页不必用 sudosudo chmod 755 /var/www/mysite↳ 目录 755:属主可读写,其他人(包括 Nginx)可进入ls -ld /var/www/mysite↳ 核对:应显示 drwxr-xr-x,属主为 studygetenforce↳ 查看 SELinux 状态:阿里云 Rocky 公共镜像默认显示 Disabled

编写站点配置 /etc/nginx/conf.d/mysite.conf

/etc/nginx/conf.d/mysite.conf
sudo vi /etc/nginx/conf.d/mysite.conf↳ Nginx 自动加载 conf.d/ 下所有 .conf 文件;把 example.com 换成自己的域名server {↳ 站点配置块开始    listen       80;↳ 监听 80 端口,接收 HTTP 请求    server_name  example.com www.example.com;↳ 本站响应哪些域名:带 www 和不带 www 都要写;Nginx 靠 Host 请求头匹配它    root         /var/www/mysite;↳ 网站文件所在目录    index        index.html;↳ 访问目录时默认返回的首页文件    access_log   /var/log/nginx/mysite_access.log;↳ 本站访问日志:记录每一次访问    error_log    /var/log/nginx/mysite_error.log;↳ 本站错误日志:出问题时先看这里    location / {↳ 路径匹配规则        try_files $uri $uri/ =404;↳ 按请求路径查找文件或目录,找不到就返回 404    }↳ 结束 location}↳ 结束 serversudo nginx -t↳ 检查所有配置语法,显示 syntax is ok 和 test is successful 才算通过sudo systemctl reload nginx↳ 重新加载生效;reload 不中断正在进行的访问

发布个人主页 · 两种方式任选其一

bash
scp index.html study@你的服务器公网IP:/var/www/mysite/↳ 方式一:本地写好再上传,用的是和 ssh 同一把密钥,不需要密码(推荐)vi /var/www/mysite/index.html↳ 方式二:直接在服务器上编辑;目录已交给 study,所以不需要 sudo页面底部:<a href="https://beian.miit.gov.cn/" target="_blank">浙ICP备XXXXXXXX号-1</a>↳ 硬性合规要求:备案号换成自己的,链接指向工信部,新窗口打开

验证 server_name 与 Host 请求头机制

bash
curl -H "Host: 你的域名" http://127.0.0.1↳ 手动指定 Host 为你的域名 → 返回你的主页内容curl http://127.0.0.1 | head -5↳ 不带你的域名 → 返回默认测试页;head -5 只看前 5 行

排障实验 · 亲手制造并修复 403

bash
echo "<h1>test</h1>" > /var/www/mysite/test.html↳ 在网站目录新建一个测试页面chmod 600 /var/www/mysite/test.html↳ 权限改为 600:只有属主 study 能读写curl -I -H "Host: 你的域名" http://127.0.0.1/test.html↳ -I 只看响应头:结果是 403 Forbiddenps -o user= -C nginx | sort -u↳ 查 nginx 进程身份:主进程 root,工作进程 nginx —— 真正读文件的是 nginx 用户ls -l /var/www/mysite/↳ test.html 显示 -rw-------,对 nginx 用户属于「其他人」,600 不允许读sudo tail -3 /var/log/nginx/mysite_error.log↳ 错误日志里有 (13: Permission denied),直接说明原因chmod 644 /var/www/mysite/test.html↳ 改为 644:属主可读写,其他人可读 —— 网页文件至少需要 644curl -I -H "Host: 你的域名" http://127.0.0.1/test.html↳ 再次访问:返回 200 OKrm /var/www/mysite/test.html↳ 实验结束,删除测试文件

看见你的第一位访客

bash
sudo tail -f /var/log/nginx/mysite_access.log↳ 持续显示文件末尾新增内容,按 Ctrl+C 退出;每刷新一次多一行访问记录
03

遇到的问题和解决办法

9 个
01域名打不开,IP 能打开+
可能原因解析未生效或记录填错
解决办法nslookup 查看解析结果;若记录填错则改正,否则等待 TTL(默认约 10 分钟)时间后再试。解析需要时间全网生效,先做后面的步骤即可。
nslookup 你的域名
nslookup www.你的域名
02连接超时+
可能原因80 端口没开
解决办法检查阿里云安全组入方向规则是否放行 TCP 80,以及 firewall-cmd --list-services 是否包含 http;两层门都要开。
sudo firewall-cmd --list-services
03403 Forbidden+
可能原因文件或目录权限不足,Nginx 读不了
解决办法先看错误日志找原因(Permission denied),再用 ls -l 核对权限:网页文件至少 644、目录至少 755。Nginx 工作进程以 nginx 用户身份运行,不是 study。
sudo tail -3 /var/log/nginx/mysite_error.log
ls -l /var/www/mysite/
chmod 644 /var/www/mysite/文件名
04404 Not Found+
可能原因文件名或路径不对
解决办法确认文件名是 index.html,确认站点配置里的 root 路径正确,并确认文件确实在 /var/www/mysite/ 下。
ls -l /var/www/mysite/
05用域名访问仍是默认页+
可能原因server_name 写错或漏写 www
解决办法检查 mysite.conf 的 server_name 是否同时包含带 www 与不带 www 的域名;改完 sudo nginx -t 通过后 reload。
sudo nginx -t
sudo systemctl reload nginx
06Nginx 启动或重载失败+
可能原因配置语法错误
解决办法sudo nginx -t 看报错行号定位;journalctl -u nginx 看服务日志。改配置必须「先测试、再生效」,否则可能导致网站中断。
sudo nginx -t
journalctl -u nginx
07teacher 账号无法使用 sudo+
可能原因Rocky 规定 wheel 组成员用 sudo 必须输入本人密码,而 teacher 没设密码
解决办法单独写 /etc/sudoers.d/teacher 免密规则,chmod 440,并用 visudo -c 校验;这是巡检 / 自动化账号的通行做法。
sudo visudo -c
08改完配置直接 reload,网站中断了+
可能原因没先测语法就生效
解决办法养成和上一章 sshd -t 同样的习惯:nginx -t 显示 syntax is ok / test is successful 之后才 reload。
sudo nginx -t
09本地安装的 Rocky 遇到 403(非阿里云镜像)+
可能原因可能是 SELinux 强制访问控制拦截
解决办法getenforce 查看状态;阿里云 Rocky 公共镜像默认 Disabled,本章不涉及,但在其他环境遇到 403 时 SELinux 也是一个排查方向。
getenforce
04

验证清单

勾选状态自动保存
验证清单0 / 7
05

本章小结

环节本章做了什么出问题时的表现
DNS添加 A 记录,域名指向服务器 IP域名打不开,IP 能打开
开门安全组 + firewalld 放行 80 端口连接超时
Nginx安装、配置站点、发布主页403、404 或看到默认页
今后排查网站故障,就按 DNS → 开门 → Nginx 这三个环节从前往后逐一检查。合规提醒:除 ICP 备案外,网站开通后 30 日内还需办理公安联网备案。
03
《服务器运维》模块一 · 第 03 讲

HTTPS 与证书自动续期

给网站加上安全锁

Let's Encrypt · certbot · Nginx TLSTLS 加密HTTP-01 验证certbot --dry-run自动续期
本章一句话

为上一章的个人主页申请免费 HTTPS 证书,让网站从「不安全」变为带安全锁的加密站点,并配置到期自动续期。

学完本章,你将能够 点击展开
  • 说清 HTTP 明文传输的风险,以及 HTTPS 加密了什么、没有加密什么
  • 理解数字证书作用,以及 CA 如何确认域名属于你
  • 用 certbot 申请证书,并编写 Nginx 的 HTTPS 配置
  • 配置证书自动续期,并验证它确实可用
01

本章做了什么

12 个关键步骤
  1. 01

    亲眼看见 HTTP 在「裸奔」

    装 tcpdump 抓 80 端口,屏幕上出现 GET /、Host、User-Agent、甚至 <title> —— 若有登录表单,账号密码也会被看得一清二楚。

  2. 02

    理解 HTTPS 解决什么

    HTTPS = HTTP + TLS:一是加密(内容变只有浏览器和服务器能解开的密文),二是身份认证(证书=网站身份证,由浏览器信任的 CA 签发)。

  3. 03

    理解 HTTP-01 验证与三个前提

    CA 给 certbot 一串随机内容 → 放进 /.well-known/acme-challenge/ → Let's Encrypt 从公网访问验证 → 推出三个前提:域名正确解析、80 对外开放、Nginx 能发出验证文件(server_name 与 root 都要对)。

  4. 04

    认识到自动续期是必须项

    证书有效期 90 天,并宣布 2028 年 2 月前逐步缩短到 45 天;Let's Encrypt 已于 2025 年停发到期提醒邮件 —— 靠人记着续期迟早会忘。

  5. 05

    开放 443,并牢牢保留 80

    安全组 + firewalld 放行 https;80 不能关:一是 http 访问要跳转,二是每次续期 Let's Encrypt 仍通过 80 做 HTTP-01 验证。

  6. 06

    安装 certbot,先演练再正式

    --dry-run 走 Let's Encrypt 测试环境,不真签证书、不占正式环境失败次数;看到 The dry run was successful. 再去掉参数正式申请。

  7. 07

    查看并认识证书

    certbot certificates 看域名 / 到期时间 / 路径;openssl x509 看颁发者、有效期、SAN 域名列表;认识 fullchain.pem 与 privkey.pem —— 证书私钥绝不外泄,目录仅 root 可访问。

  8. 08

    备份并改写 Nginx 配置

    备份名必须以 .bak 结尾(写成 .conf 会被一并加载造成重复配置);80 只做 ACME 验证 + 301 跳转,443 才提供内容(只允许 TLSv1.2 / TLSv1.3);nginx -t 通过后 reload。

  9. 09

    验证跳转与安全锁

    浏览器访问 http 自动变 https 并出现锁;Windows PowerShell 里 curl 是别名,必须写 curl.exe -I 才能拿到 301 / 200 响应头。

  10. 10

    配置自动续期

    启用 certbot-renew.timer;写 deploy 钩子 reload-nginx.sh 并 chmod +x、手动跑一次确认;最后 certbot renew --dry-run 演练整个续期流程。

  11. 11

    再抓一次 443 包做对比

    内容全是无法阅读的乱码,但仍能在其中找到自己的域名(SNI 明文)—— HTTPS 隐藏的是「你看了什么内容」,不是「你访问了哪个网站」。

  12. 12

    验证与交付

    逐项核对 8 条清单。★ 作品一完成:带域名、备案号与 HTTPS 安全锁的完整规范网站;本章无需提交新材料。

02

用了什么命令

62 条 · 11 组

命令均以等宽字体代码块呈现,灰色 ↳ 行是作用说明(不会被复制);点击代码块右上角「复制全部」或组标题右侧「复制本组」即可带走该组命令。

第 1 节 · 亲手「偷看」HTTP 明文流量

bash
sudo dnf install -y tcpdump↳ 安装抓包工具 tcpdumpsudo tcpdump -i any -A -nn 'tcp port 80' | grep -a -E "GET |Host:|User-Agent|<title>"↳ -i any 所有网卡 / -A 文本显示 / -nn 数字不解析 / -a 二进制当文本;请同学用手机访问 http://你的域名 观察

开放 443 端口 · 80 保留不关

bash
控制台:安全组入方向添加 TCP 443 / 0.0.0.0/0↳ 控制台通常也提供 HTTPS(443) 快速添加选项sudo firewall-cmd --permanent --add-service=https↳ 永久放行 HTTPS 服务(即 TCP 443)sudo firewall-cmd --reload↳ 重新加载防火墙使永久规则生效sudo firewall-cmd --list-services↳ 核对:应包含 ssh、http、https

安装 certbot

bash
sudo dnf install -y certbot↳ 从 EPEL 源安装(第 1 章装 fail2ban 时已装过 EPEL)certbot --version↳ 查看版本号,确认安装成功

先演练 --dry-run(申请失败有次数限制)

bash
sudo certbot certonly --webroot -w /var/www/mysite \↳ certonly 只申请证书不自动改 Nginx;--webroot 把验证文件放进网站目录由 Nginx 发出;行尾 \ 表示命令未完     -d example.com -d www.example.com \↳ -d 证书要包含的域名,带 www 和不带 www 各写一个     -m 你的邮箱 --agree-tos --no-eff-email --dry-run↳ -m 联系邮箱 / --agree-tos 同意条款 / --no-eff-email 不订阅新闻 / --dry-run 演练模式

正式申请(去掉 --dry-run)

bash
sudo certbot certonly --webroot -w /var/www/mysite \↳ 看到 Successfully received certificate. 说明证书已签发     -d example.com -d www.example.com \↳ 两个域名缺一不可     -m 你的邮箱 --agree-tos --no-eff-email↳ 演练成功后才执行这一步

查看证书与四个 pem 文件

bash
sudo certbot certificates↳ 列出本机所有证书:包含哪些域名、到期时间、剩余天数、文件位置sudo ls -l /etc/letsencrypt/live/example.com/↳ 目录名取自第一个 -d 域名;fullchain.pem 证书链发访问者 / privkey.pem 私钥留服务器绝不泄露sudo openssl x509 -in /etc/letsencrypt/live/example.com/cert.pem -noout -issuer -dates -ext subjectAltName↳ -issuer 颁发者应含 Let's Encrypt / -dates 生效与到期时间 / -ext subjectAltName 域名列表

备份并改写站点配置(共 6 处 example.com 要替换)

/etc/nginx/conf.d/mysite.conf
sudo cp /etc/nginx/conf.d/mysite.conf /etc/nginx/conf.d/mysite.conf.bak↳ 备份名不能以 .conf 结尾,否则会被 Nginx 一并加载造成重复配置sudo vi /etc/nginx/conf.d/mysite.conf↳ 把文件全部内容替换为下面的双 server 块# ① 80 端口:只做 ACME 验证 + 跳转到 HTTPS↳ 80 不再直接提供网页server {↳ 80 server 块    listen       80;↳ 监听 80    server_name  example.com www.example.com;↳ 两个域名都要写    location /.well-known/acme-challenge/ {↳ 证书续期验证专用路径        root /var/www/mysite;↳ Let's Encrypt 仍通过 HTTP 读取这里的验证文件    }↳ 结束 location    location / {↳ 其余请求        return 301 https://$host$request_uri;↳ $host 请求域名 / $request_uri 请求路径,保证 /about.html 准确跳转而不是一律回首页    }↳ 结束 location}↳ 结束 80 server# ② 443 端口:真正提供网站内容↳ HTTPS 站点server {↳ 443 server 块    listen       443 ssl;↳ 监听 443 并启用 SSL/TLS 加密    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;↳ 证书私钥,留在服务器用于解密,绝不能泄露    ssl_protocols        TLSv1.2 TLSv1.3;↳ 只允许较新的安全协议版本,淘汰有漏洞的旧版本    root         /var/www/mysite;↳ 网站目录    index        index.html;↳ 首页文件    access_log   /var/log/nginx/mysite_access.log;↳ 访问日志    error_log    /var/log/nginx/mysite_error.log;↳ 错误日志    location / {↳ 路径匹配        try_files $uri $uri/ =404;↳ 找不到就返回 404    }↳ 结束 location}↳ 结束 443 serversudo nginx -t↳ 显示 syntax is ok 和 test is successful 才算通过;报 cannot load certificate 多半是路径域名写错sudo systemctl reload nginx↳ 重新加载配置使其生效

验证跳转(Windows PowerShell 必须写 curl.exe)

bash
curl.exe -I http://example.com↳ 应返回 301 Moved Permanently,Location 指向 https://example.com/curl.exe -I https://example.com↳ 应返回 200 OKcurl.exe -I https://www.example.com↳ 带 www 的同样应返回 200 OK

配置自动续期 · 定时器 + deploy 钩子

renewal-hooks/deploy/reload-nginx.sh
sudo systemctl enable --now certbot-renew.timer↳ 启用续期定时器并立即计时;每天检查,到期前约 30 天自动续期systemctl list-timers 'certbot*'↳ 查看定时器:NEXT 一列是下次检查时间sudo vi /etc/letsencrypt/renewal-hooks/deploy/reload-nginx.sh↳ 续期成功后自动执行的钩子脚本#!/bin/bash↳ 脚本内容第 1 行systemctl reload nginx↳ 脚本内容第 2 行:Nginx 不会自动读新证书,必须重载一次才生效sudo chmod +x /etc/letsencrypt/renewal-hooks/deploy/reload-nginx.sh↳ 钩子脚本必须有执行权限才会被调用sudo /etc/letsencrypt/renewal-hooks/deploy/reload-nginx.sh↳ 手动运行一次,没有报错即可systemctl is-active nginx↳ 确认 Nginx 仍在正常运行,应显示 activesudo certbot renew --dry-run↳ 演练一次续期全过程;成功显示 Congratulations, all simulated renewals succeeded

第 7 节 · 再抓一次包看 HTTPS

bash
sudo tcpdump -i any -A -nn -c 40 'tcp port 443'↳ -c 40 抓够 40 个包自动停止;看不到 GET / User-Agent / 标题,全是乱码,但域名(SNI)仍明文

改坏了配置想恢复

bash
sudo cp /etc/nginx/conf.d/mysite.conf.bak /etc/nginx/conf.d/mysite.conf↳ 用备份还原sudo nginx -t && sudo systemctl reload nginx↳ 还原后照例先测语法再生效
03

遇到的问题和解决办法

12 个
01certbot 报 DNS problem: NXDOMAIN+
可能原因域名或 www 子域名没有解析记录
解决办法nslookup 域名、nslookup www.域名 逐一确认,补上缺失的 A 记录;申请证书时两个域名缺一不可。
nslookup 你的域名
nslookup www.你的域名
02certbot 报 Timeout during connect+
可能原因80 端口不通(HTTP-01 验证走 80)
解决办法检查安全组入方向规则与 firewall-cmd --list-services;确认 80 对外可访问,且没有被误关。
sudo firewall-cmd --list-services
03certbot 报 unauthorized 且有 404+
可能原因验证文件没能被访问到
解决办法核对 -w 是否与 Nginx 配置里的 root 一致、server_name 是否包含该域名;必要时用 curl 手动访问 /.well-known/acme-challenge/ 下的测试文件。
sudo nginx -t
04certbot 报 too many failed authorizations+
可能原因同一域名一小时内验证失败次数过多,被暂时拒绝
解决办法等待一小时;之后务必先用 --dry-run 演练成功,再去掉参数正式申请,避免再次撞限流。
sudo certbot certonly --webroot -w /var/www/mysite -d example.com -d www.example.com --dry-run
05nginx -t 报 cannot load certificate+
可能原因证书路径中的域名写错了
解决办法对照 sudo certbot certificates 中的实际路径修改;配置里共 6 处 example.com 都要换成自己的域名(两行 server_name 各 2 处、两行证书路径各 1 处)。
sudo certbot certificates
06https 访问超时+
可能原因443 端口没开
解决办法检查安全组入方向 TCP 443 与 firewalld 是否放行 https,两层门都要开。
sudo firewall-cmd --list-services
07访问 http 没有跳转+
可能原因配置未生效,或浏览器缓存了 301
解决办法nginx -t 通过后 reload;用 curl.exe -I http://域名 直接看响应头排除浏览器缓存干扰。
curl.exe -I http://example.com
sudo systemctl reload nginx
08锁的图标带有警告+
可能原因页面引用了 http:// 开头的图片或脚本(混合内容)
解决办法把页面中的资源地址改为 https:// 或相对路径,让全站资源都走加密连接。
09改坏了配置想恢复+
可能原因配置写错导致站点异常
解决办法用备份还原:sudo cp /etc/nginx/conf.d/mysite.conf.bak /etc/nginx/conf.d/mysite.conf,再执行 nginx -t 和 reload。
sudo cp /etc/nginx/conf.d/mysite.conf.bak /etc/nginx/conf.d/mysite.conf
sudo nginx -t && sudo systemctl reload nginx
10陷阱:把 80 端口关掉+
可能原因以为全站 HTTPS 就不需要 80
解决办法80 必须保留,两个理由:① 有人直接输入 http:// 访问时需要 80 把他 301 引导到 HTTPS;② 证书每次续期时 Let's Encrypt 仍通过 80 做 HTTP-01 验证,关掉后三个月证书就无法续期。
11陷阱:备份文件名写成 mysite.conf.bak.conf 之类+
可能原因以 .conf 结尾会被 Nginx 自动加载,造成重复配置
解决办法备份名用 .bak 结尾即可,例如 mysite.conf.bak,不要带 .conf 后缀。
12陷阱:certbot renew --dry-run 提示跳过 deploy 钩子+
可能原因演练不会真的产生新证书,自然也不需要重载 Nginx
解决办法这是正常现象。钩子脚本本身已在配置时手动运行验证过;真正续期成功时它会自动执行。
04

验证清单

勾选状态自动保存
验证清单0 / 8
05

本章小结

步骤做了什么关键点
开门放行 443 端口80 端口不能关:跳转和续期都要用到
申请证书certbot 以 webroot 方式申请先 --dry-run 演练,再正式申请
配置 HTTPS80 负责跳转,443 提供内容证书私钥 privkey.pem 绝不外泄
自动续期定时器 + deploy 钩子90 天有效期,靠自动化而不是靠人记
你的个人主页现在拥有域名、备案号和 HTTPS 安全锁,已经是一个完整、规范的网站了。