我的运维笔记

《服务器运维》模块一 · 第 1 ~ 3 讲 听课整理

第 1 讲服务器安全加固

目标:把一台"裸奔"的服务器加固成只认密钥、守得住、还会自动反击的服务器(本章不修改 SSH 端口)。

1. 先看见威胁:服务器正在被扫描

服务器接入公网的那一刻,就有自动化扫描程序昼夜不停地遍历 IP,一旦发现 22 端口(SSH)就疯狂尝试常见用户名密码——这叫暴力破解。

# 查看 SSH 服务日志中最近的登录失败记录
# journalctl -u sshd:查看 sshd 的系统日志
# grep -i "failed":只筛出含 failed 的行(-i 忽略大小写)
# tail -30:只显示最后 30 条
sudo journalctl -u sshd | grep -i "failed" | tail -30

你会看到大量来自陌生 IP 的失败记录,绝大多数在尝试 root。

2. 登录服务器的两条通道(关键认知)

通道走向是否受 SSH 配置影响
SSH(含控制台 Workbench) 走公网 → 安全组 22 端口 → 服务器 sshd 受影响:sshd 改崩或 22 被封,这条通道就断,不是后路
VNC 阿里云带外管理通道,相当于坐在物理显示器前 不受影响:不经过安全组、不经过 sshd,用系统账号密码登录
记住:真正能救命的后路是 VNC。正因为有它兜底,我们才敢大胆改配置。

3. 动手前先走通一次 VNC 后路

控制台 → 实例 → 远程连接 → VNC 远程连接,用普通用户登录后执行:

# 显示当前登录的用户名,应为 study
whoami

# 显示当前终端设备:VNC 显示 /dev/tty1,SSH 显示 /dev/pts/0 之类
# 两者不同,正好从系统内部印证"这是两条独立的通道"
tty

exit

4. 用密钥代替密码登录

4.1 原理

登录时服务器用公钥出一道只有对应私钥才能解开的"数学难题",攻击者拿到公钥也没用。

4.2 在自己电脑上生成密钥对(私钥从不经过网络)

# -t ed25519:现代、短小而安全的算法
# -C:给密钥加备注,方便日后辨认
ssh-keygen -t ed25519 -C "你的名字-服务器加固"

# Windows(PowerShell)查看公钥
type $env:USERPROFILE\.ssh\id_ed25519.pub

# Mac / Linux 查看公钥(不带 .pub 的那个是私钥,切勿外传)
cat ~/.ssh/id_ed25519.pub

复制以 ssh-ed25519 AAAA... 开头的一整行,中间不能有换行。

4.3 把公钥安装到服务器

# 切换到 study 用户(- 表示加载其环境,此后 ~ 就是 /home/study)
sudo su - study

# 创建存放密钥的目录
mkdir -p ~/.ssh

# 目录权限 700:仅本人可进入读写
chmod 700 ~/.ssh

# 编辑"已授权公钥"文件,粘贴公钥后 :wq 保存
vi ~/.ssh/authorized_keys

# 文件权限 600:仅本人可读写(权限过松 SSH 会静默拒绝登录!)
chmod 600 ~/.ssh/authorized_keys

# 核对:authorized_keys 应为 -rw------- 且属主是自己
ls -l ~/.ssh
最常见的坑:文件权限。权限过松时 SSH 会直接拒绝使用它登录,而且不报任何错。

4.4 铁律:先验证密钥能登录,再往下做

# 回自己的电脑执行:能直接登入且不要求输入密码,才算成功
ssh study@服务器公网IP
顺序一旦反了,就可能"密码已禁、密钥没配好",把自己关在门外。正确习惯:先验证,再收口。

4.5 为老师配置巡检账号 teacher

错误直觉:把私钥发给老师 ✘。正确做法:把老师的公钥安装到你的服务器上 ✔。

# 新建专供老师巡检的账号
sudo adduser teacher

# 为 teacher 创建 .ssh 目录并写入【老师发给你的公钥】
sudo mkdir -p /home/teacher/.ssh
sudo vi /home/teacher/.ssh/authorized_keys

# 权限与属主
sudo chmod 700 /home/teacher/.ssh
sudo chmod 600 /home/teacher/.ssh/authorized_keys
sudo chown -R teacher:teacher /home/teacher/.ssh

# teacher 没有密码,而 wheel 组用 sudo 必须输入本人密码,
# 所以单独为 teacher 配置免密 sudo
echo "teacher ALL=(ALL) NOPASSWD: ALL" | sudo tee /etc/sudoers.d/teacher
sudo chmod 440 /etc/sudoers.d/teacher

# 检查所有 sudo 配置语法,全部 parsed OK 才放心
sudo visudo -c

# 以 teacher 身份测试免密 sudo 是否可用
sudo -u teacher sudo -n true && echo "teacher 免密 sudo 可用"

5. 加固 sshd 配置(收口)

# sshd_config 是 SSH 服务端主配置,决定谁能登录、用什么方式登录
sudo vi /etc/ssh/sshd_config

找到并修改(没有就新增)以下几项:

PubkeyAuthentication yes        # 允许密钥登录(加固的基础)
PasswordAuthentication no       # 禁止密码登录(务必确认密钥能登录后再改)
PermitRootLogin no              # 禁止 root 直接远程登录,缩小攻击面
MaxAuthTries 3                  # 单次连接最多 3 次认证尝试,拖慢爆破
ClientAliveInterval 300         # 每 300 秒探测一次客户端是否还在
ClientAliveCountMax 2           # 连续 2 次无响应就断开,清理空闲会话
AllowUsers study teacher        # 登录白名单,其余用户一律拒绝
# 先验证语法:没有任何输出即正确
sudo sshd -t

# reload 不会断开当前连接,比 restart 安全
sudo systemctl reload sshd
两个高危项:PasswordAuthentication no(必须先验证密钥可用);AllowUsers(写错用户名或漏掉 teacher,对应的人就被挡在门外)。

6. 两道门:安全组 + 主机防火墙

两层相互独立、都要配置,原则是同一个词——最小化:只开必须的门。

# 永久放行 SSH 服务(--permanent 写入永久规则)
sudo firewall-cmd --permanent --add-service=ssh

# 重新加载,让永久规则真正生效(Rocky 上最容易忘的一步)
sudo firewall-cmd --reload

# 核对当前区域放行的服务/端口
sudo firewall-cmd --list-all

# 查看本机实际在监听哪些端口,与安全组规则互相印证
# -t 只看 TCP  -l 只看监听中  -n 用数字显示  -p 显示占用端口的进程
sudo ss -tlnp

安全组三点:

为什么 ICMP 规则的端口栏是"任何 / -1"?安全组按"协议 + 端口"两个维度控制,并不是只看端口。ICMP 是网络层诊断协议,本身不使用端口,-1/-1 只是占位符,不代表把所有端口都打开了。放行 ICMP 只意味着别人能 ping 通你,既无法登录也无法传数据。

7. 让服务器自动反击:fail2ban

# Rocky 默认源没有 fail2ban,先装 EPEL 扩展源
sudo dnf install -y epel-release

# 再安装 fail2ban 本体
sudo dnf install -y fail2ban

# 规范做法:在 jail.d/ 下新建 .local 文件,不直接改 jail.conf,
# 这样软件升级时自己的配置不会被覆盖
sudo vi /etc/fail2ban/jail.d/sshd.local
[sshd]                  # 针对 sshd 服务的防护规则
enabled  = true         # 启用本规则
backend  = systemd      # Rocky 9 从 systemd 日志读取失败记录(别抄读日志文件的老写法)
maxretry = 3            # 允许的最大失败次数
findtime = 600          # 统计窗口:600 秒(10 分钟)
bantime  = 3600         # 触发后封禁 3600 秒(1 小时)

连起来读:10 分钟内失败 3 次,就封这个 IP 一小时。

# 启动并设为开机自启
sudo systemctl enable --now fail2ban

# 查看 sshd 规则运行状态,重点看 Banned IP list
sudo fail2ban-client status sshd
封禁名单暂时为空不代表操作有误,只是这台机器还没被扫描器盯上。

8. 验证清单

第 2 讲网站上线:域名解析与 Nginx 个人主页

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

1. 一个网站能被访问的三个环节

环节做什么出问题时的表现
DNS添加 A 记录,域名指向服务器 IP域名打不开,IP 能打开
开门安全组 + firewalld 放行 80 端口连接超时
Nginx安装、配置站点、发布主页403、404 或看到默认页

排障时按这三个环节从前往后逐一检查。

2. 域名解析

DNS 是互联网的"通讯录",负责把域名翻译成 IP。三个字段:

在阿里云"云解析 DNS → 解析设置"里添加两条 A 记录:@ 和 www,记录值都填服务器公网 IP。

为什么第一步就做解析?DNS 记录生效需要时间,先提交让它后台慢慢生效,同时去做后面的步骤。把需要等待的事情提前做,是运维常用思路。
# 验证解析:看 Address 一栏是不是你的服务器公网 IP
nslookup 你的域名
nslookup www.你的域名

3. 为网站开门(80 端口)

"最小化"不是"什么都不开",而是只在服务真正上线时才开放对应的门。本章只开 80;443 等下一章配证书时再开。

安全组:实例 → 安全组 → 配置规则 → 入方向 → 添加规则,协议 TCP,端口 80,授权对象 0.0.0.0/0。

# 主机防火墙永久放行 HTTP 服务(即 TCP 80)
sudo firewall-cmd --permanent --add-service=http
sudo firewall-cmd --reload

# 核对:应包含 ssh 和 http
sudo firewall-cmd --list-services

4. 安装 Nginx 并配置站点

# 从系统软件源安装 Nginx
sudo dnf install -y nginx

# 立即启动并设为开机自启
sudo systemctl enable --now nginx

# 查看运行状态,应显示 active (running),按 q 退出
systemctl status nginx

# 查看版本号
nginx -v

浏览器访问 http://你的服务器公网IP,看到 Nginx 默认测试页说明安装成功、80 端口已通。

4.1 准备网站目录

# 为自己的站点单独建目录,结构清晰、以后加站点不互相干扰
sudo mkdir -p /var/www/mysite

# 把目录交给 study,之后上传修改网页不必用 sudo
sudo chown -R study:study /var/www/mysite

# 755:属主可读写,其他人(包括 Nginx)可进入
sudo chmod 755 /var/www/mysite

# 核对:应显示 drwxr-xr-x,属主为 study
ls -ld /var/www/mysite

# 查看 SELinux 状态:阿里云 Rocky 镜像默认 Disabled
getenforce

4.2 编写站点配置

Nginx 会自动加载 /etc/nginx/conf.d/ 下所有 .conf 结尾的文件。

sudo vi /etc/nginx/conf.d/mysite.conf
server {
    listen 80;                                  # 监听 80 端口,接收 HTTP 请求
    server_name example.com www.example.com;     # 带 www 和不带 www 都要写

    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
    }
}
server_name 最关键:一台服务器可跑多个网站,Nginx 靠 HTTP 请求头里的 Host 字段区分——请求域名和哪个站点的 server_name 匹配,就交给哪个站点。下一章申请 HTTPS 证书时,证书工具也靠这一行识别域名。
# 先检查语法,显示 syntax is ok 和 test is successful 才算通过
sudo nginx -t

# reload 不中断正在进行的访问
sudo systemctl reload nginx

5. 发布个人主页

硬性要求:首页底部必须显示本人 ICP 备案号,并链接到 https://beian.miit.gov.cn/。这是合规要求,不是可选项。

# 方式一:在自己电脑上用 scp 上传(用同一把密钥,不需要密码)
scp index.html study@你的服务器公网IP:/var/www/mysite/

# 方式二:直接在服务器上编辑(目录已交给 study,不需要 sudo)
vi /var/www/mysite/index.html

AI 生成的主页必须自己检查:备案号是不是自己的、链接是否正确、页面能否正常显示。

为什么用 IP 访问看到的是默认页?

用 IP 访问时请求里的 Host 不是你的域名,匹配不上你的站点,于是交给系统默认站点处理——这正是 server_name 在起作用。

# -H 手动指定请求头中的 Host 字段,127.0.0.1 表示访问本机
# 带 Host: 你的域名 → 返回你的主页内容
curl -H "Host: 你的域名" http://127.0.0.1

# 不带你的域名 → 返回默认测试页;head -5 只看前 5 行
curl http://127.0.0.1 | head -5

6. 排障实验:亲手制造一次 403

# 在网站目录新建一个测试页面
echo "<h1>test</h1>" > /var/www/mysite/test.html

# 权限改为 600:只有属主 study 能读写,其他人不可读
chmod 600 /var/www/mysite/test.html

# -I 只看响应头:结果是 403 Forbidden
curl -I -H "Host: 你的域名" http://127.0.0.1/test.html

# 查证 Nginx 到底以什么身份运行:root(主进程)+ nginx(工作进程)
ps -o user= -C nginx | sort -u

# 核对权限:test.html 显示 -rw-------,只有 study 可读
ls -l /var/www/mysite/

# 错误日志里有 (13: Permission denied),直接说明原因
sudo tail -3 /var/log/nginx/mysite_error.log

# 修复:644 = 属主可读写,其他人可读
chmod 644 /var/www/mysite/test.html
curl -I -H "Host: 你的域名" http://127.0.0.1/test.html   # 返回 200 OK

# 实验结束,删除测试文件
rm /var/www/mysite/test.html
403 排查思路:先看错误日志找原因,再用 ls -l 核对权限。网页文件至少 644,目录至少 755,Nginx 才能正常读取。真正读文件的是 nginx 用户(工作进程),不是 study。

7. 看见你的第一位访客

# tail -f 持续显示文件末尾新增内容,按 Ctrl+C 退出
sudo tail -f /var/log/nginx/mysite_access.log

每刷新一次页面就多一行:来访 IP、时间、访问页面、状态码、浏览器。日志是运维最重要的信息来源,网站出问题第一件事就是看日志。

8. 验证清单

合规提醒:除 ICP 备案外,网站开通后 30 日内还需在"全国互联网安全管理服务平台"办理公安联网备案,取得公安备案号后同样要显示在网站底部。具体要求以当地规定为准。

第 3 讲给网站加上安全锁:HTTPS 与证书自动续期

前提:http://你的域名 和 http://www.你的域名 都能看到主页,两个域名缺一不可。

1. 你的网站正在"裸奔":亲手抓一次包

HTTP 传输的内容全是明文,链路上任何一台设备都能原样看到你访问了什么页面、提交了什么内容。

# 安装 tcpdump:一个能抓取并显示网络数据包的工具
sudo dnf install -y tcpdump

# -i any :所有网卡上抓包
# -A     :以文本形式显示数据包内容
# -nn    :IP 和端口都用数字显示,不做名称解析
# 'tcp port 80':只抓 80 端口(HTTP)流量
# grep -a -E:只显示含请求行、域名、浏览器信息或网页标题的行
sudo tcpdump -i any -A -nn 'tcp port 80' | grep -a -E "GET |Host: |User-Agent|title"

请同学用手机访问你的 http 站点,屏幕上会出现:请求的页面(GET /)、访问的域名(Host:)、手机和浏览器型号(User-Agent),甚至网页标题(title)。如果页面有登录表单,账号密码也会被看得一清二楚。按 Ctrl+C 停止抓包。

2. HTTPS 与证书的原理

2.1 HTTPS 解决了两个问题

身份认证依靠数字证书——网站的"身份证",上面写明证书属于哪些域名、由谁颁发、什么时候到期。

2.2 谁来颁发证书

证书由 CA(证书颁发机构)签发。浏览器和操作系统内置一份受信任的 CA 名单,只有名单上的 CA 签发的证书才会显示安全锁。本章使用 Let's Encrypt:免费、全自动的公益 CA。

2.3 CA 怎么确认域名是你的(HTTP-01 验证)

由此推出申请证书的三个前提,也是失败时的三个排查方向:
  • 域名必须正确解析到你的服务器(A 记录);
  • 80 端口必须对外开放(Let's Encrypt 通过 HTTP 验证);
  • Nginx 必须能把验证文件发出去(server_name 和 root 都要正确)。

2.4 证书的有效期

Let's Encrypt 证书有效期只有 90 天,并宣布将在 2028 年 2 月之前逐步缩短到 45 天;同时已于 2025 年停止发送到期提醒邮件。靠人记着续期迟早会忘,自动续期是必须完成的步骤,不是可选项。

3. 开放 443 端口

安全组:入方向添加规则,协议 TCP,端口 443,授权对象 0.0.0.0/0(控制台通常有"HTTPS(443)"快速添加)。

# 永久放行 HTTPS 服务(即 TCP 443 端口)
sudo firewall-cmd --permanent --add-service=https

# 重新加载,使永久规则生效
sudo firewall-cmd --reload

# 核对:应包含 ssh、http、https
sudo firewall-cmd --list-services
80 端口不能关!两个理由:①有人直接输入 http:// 访问时,需要 80 端口把他引导到 HTTPS;②证书每次续期时,Let's Encrypt 仍要通过 80 端口验证。关掉 80,三个月后证书就无法续期。

4. 申请证书

4.1 安装 certbot

# 从 EPEL 源安装 certbot(第 1 章装 fail2ban 时已装过 EPEL)
sudo dnf install -y certbot

# 查看版本号,确认安装成功
certbot --version

4.2 先演练:--dry-run

Let's Encrypt 对失败次数有限制:同一域名一小时内验证失败太多次会被暂时拒绝。所以先演练——走完整流程但连接测试环境,既不真签发,也不占用正式环境次数。先演练,再正式,和前两章"改配置之前先测试"是同一个习惯。

# certonly       :只申请证书,不自动修改 Nginx 配置
# --webroot      :用"网站目录"方式验证,把验证文件放进网站目录由 Nginx 发出
# -w /var/www/mysite:网站目录,即 Nginx 配置里的 root
# -d             :证书要包含的域名,带 www 和不带 www 各写一个
# -m             :联系邮箱
# --agree-tos    :同意 Let's Encrypt 服务条款
# --no-eff-email :不订阅 EFF 的新闻邮件
# --dry-run      :演练模式,使用测试环境,不真正签发证书
sudo certbot certonly --webroot -w /var/www/mysite \
  -d example.com -d www.example.com \
  -m 你的邮箱 --agree-tos --no-eff-email --dry-run

行尾的反斜杠 \ 表示"命令还没写完,下一行接着写",三行合起来是一条命令。

看到 The dry run was successful. 说明演练成功。失败则按"解析、80 端口、Nginx"三个方向逐一排查,修好后重新演练。

4.3 正式申请

# 演练成功后,去掉 --dry-run
sudo certbot certonly --webroot -w /var/www/mysite \
  -d example.com -d www.example.com \
  -m 你的邮箱 --agree-tos --no-eff-email

看到 Successfully received certificate. 说明证书已签发。

4.4 看看你的证书

# 列出本机所有证书:包含哪些域名、到期时间、剩余天数、文件位置
sudo certbot certificates

# 证书文件所在目录(目录名取自第一个 -d 域名)
sudo ls -l /etc/letsencrypt/live/example.com/

# 查看证书具体内容
# -noout            :不输出证书原始编码
# -issuer           :显示颁发者,应包含 Let's Encrypt
# -dates            :显示生效时间 notBefore 和到期时间 notAfter
# -ext subjectAltName:显示证书包含的域名列表
sudo openssl x509 -in /etc/letsencrypt/live/example.com/cert.pem \
  -noout -issuer -dates -ext subjectAltName
文件内容用途
fullchain.pem你的证书 + 中间证书发给访问者,证明网站身份(本章使用)
privkey.pem证书私钥留在服务器上用于解密,绝不能泄露(本章使用)
cert.pem仅你的证书本章不直接使用
chain.pem仅中间证书本章不直接使用
privkey.pem 与第 1 章的 SSH 私钥同理:谁拿到它,谁就能冒充你的网站。它所在目录只有 root 能访问,这是 certbot 有意的保护。

自己核对两件事:到期时间是否大约在 90 天之后?域名列表中两个域名是否都在?

5. 配置 Nginx 启用 HTTPS

5.1 先备份

# 备份文件名不能以 .conf 结尾,否则会被 Nginx 一并加载造成重复配置
sudo cp /etc/nginx/conf.d/mysite.conf /etc/nginx/conf.d/mysite.conf.bak

5.2 改写站点配置

网站分成两部分:80 端口只负责为证书续期提供验证文件 + 把其余请求跳转到 HTTPS;443 端口才真正提供网站内容。

sudo vi /etc/nginx/conf.d/mysite.conf
# ===== 80 端口:只做两件事 =====
server {
    listen 80;
    server_name example.com www.example.com;

    # 证书续期时,Let's Encrypt 仍通过 HTTP 读取这里的验证文件
    location /.well-known/acme-challenge/ {
        root /var/www/mysite;
    }

    # 其余请求永久跳转(301)到同一地址的 HTTPS 版本
    location / {
        return 301 https://$host$request_uri;
    }
}

# ===== 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;
    }
}

$host 和 $request_uri 是 Nginx 变量,分别代表访问者请求的域名和路径。这样访问 http://www.example.com/about.html 会被准确跳转到 https://www.example.com/about.html,而不是一律跳回首页。

注意:全文所有 example.com 都要换成自己的域名(共 6 处:两行 server_name 各 2 处,两行证书路径各 1 处)。

5.3 测试并生效

# 检查语法,显示 syntax is ok 和 test is successful 才算通过
sudo nginx -t

# 重新加载配置使其生效
sudo systemctl reload nginx
若 nginx -t 报 cannot load certificate,多半是证书路径中的域名写错,对照 certbot certificates 的结果核对目录名。

5.4 验证

浏览器访问 http://你的域名:地址自动变为 https://,出现锁的图标;点击可查看颁发者和有效期。

# Windows PowerShell 里要写 curl.exe,因为 PowerShell 的 curl 是另一个命令的别名
# -I 只获取响应头
curl.exe -I http://example.com          # 应返回 301,Location 指向 https://example.com/
curl.exe -I https://example.com         # 应返回 200 OK
curl.exe -I https://www.example.com     # 带 www 的同样应返回 200 OK

6. 配置自动续期

6.1 启用续期定时器

# certbot 自带 systemd 定时器,每天检查一次,到期前约 30 天自动续期
# enable 保证重启后依然有效,--now 立即开始计时
sudo systemctl enable --now certbot-renew.timer

# 查看定时器:NEXT 一列是下次检查的时间
systemctl list-timers 'certbot*'

6.2 续期后自动重载 Nginx(deploy 钩子)

证书续期只更新磁盘上的文件,Nginx 不会自动读取,必须重载才生效。放在 /etc/letsencrypt/renewal-hooks/deploy/ 目录下的脚本,会在每次续期成功后自动执行。

sudo vi /etc/letsencrypt/renewal-hooks/deploy/reload-nginx.sh

写入以下两行:

#!/bin/bash
systemctl reload nginx   # 续期成功后重载 Nginx,让新证书生效
# 钩子脚本必须有执行权限才会被调用
sudo chmod +x /etc/letsencrypt/renewal-hooks/deploy/reload-nginx.sh

# 手动运行一次,确认脚本本身没有问题
sudo /etc/letsencrypt/renewal-hooks/deploy/reload-nginx.sh

# 确认 Nginx 仍在正常运行,应显示 active
systemctl is-active nginx

6.3 演练一次续期

# 模拟一次续期全过程(使用测试环境,不会真的更换证书)
sudo certbot renew --dry-run

看到 Congratulations, all simulated renewals succeeded 说明续期流程通了。

演练时 certbot 会提示跳过了 deploy 钩子,这是正常现象:演练不产生新证书,自然不需要重载 Nginx。钩子脚本本身已在 6.2 节手动验证过。

7. 再抓一次包:HTTPS 的流量长什么样

# -c 48:抓够 48 个数据包后自动停止
sudo tcpdump -i any -A -nn -c 48 'tcp port 443'

请同学用手机访问你的 https 站点,与第 1 节对比:这次看不到 GET、User-Agent,也看不到网页标题,屏幕上全是无法阅读的乱码——内容已经被加密了。

但仔细看,乱码里还能找到你的域名。因为浏览器在建立加密连接之前,要先告诉服务器"我要访问哪个网站",服务器才能拿出对应证书,这一步是明文进行的。所以请记住:HTTPS 隐藏的是你看了什么内容,而不是你访问了哪个网站。

8. 验证与交付清单

9. 常见故障速查

现象可能原因排查方法
certbot 报 DNS problem: NXDOMAIN域名或 www 子域名没有解析记录nslookup 两个域名,补上缺失的 A 记录
certbot 报 Timeout during connect80 端口不通检查安全组和 firewall-cmd --list-services
certbot 报 unauthorized(404)验证文件没能被访问到核对 -w 是否与 Nginx 的 root 一致、server_name 是否含该域名
certbot 报 too many failed authorizations一小时内失败次数过多等一小时;之后先用 --dry-run 演练成功再正式申请
nginx -t 报 cannot load certificate证书路径写错对照 certbot certificates 中的路径修改
https 访问超时443 端口没开检查安全组和 firewalld
访问 http 没有跳转配置未生效或浏览器缓存nginx -t 后 reload;用 curl.exe -I 查看响应
锁的图标带有警告页面引用了 http:// 开头的图片或脚本改为 https:// 或相对路径
改坏了配置想恢复—sudo cp mysite.conf.bak mysite.conf,再 nginx -t 和 reload

总结贯穿全课的三个运维习惯

从"看得见威胁"到"守得住、会还手",再到"网站能访问、有安全锁、证书自动续期"——三讲下来,一个带域名、备案号与 HTTPS 安全锁的完整个人主页就诞生了。