我的运维笔记

《服务器运维》模块一 · Rocky Linux 9 实践笔记

第1讲 · 服务器安全加固

一、为什么要加固:你的服务器正在被扫描

当服务器接入公网的那一刻,互联网上大量自动化扫描程序会昼夜不停地遍历 IP 地址,一旦发现 22 端口(SSH 默认端口),就会用海量用户名和密码组合反复尝试登录——这就是暴力破解。

查看 SSH 登录失败记录的命令:

sudo journalctl -u sshd | grep -i "failed" | tail -30
提示:多半会看到大量来自陌生 IP 的登录失败记录,且绝大多数在尝试 root 用户登录。

二、登录服务器的两条通道

  • 通道一:SSH(含控制台 Workbench)——走公网、经过安全组 22 端口、受 sshd 配置管辖。如果改崩了配置或封了 22 端口,这条通道会一起断开,不是后路。
  • 通道二:VNC——走阿里云带外管理通道,相当于直接坐在服务器物理显示器前登录。不经过安全组也不经过 sshd,能救命的后路。
关键认知:真正能救命的后路是 VNC。所有加固操作万一把自己锁在门外,都可以从 VNC 登录进去改回来。

三、用密钥代替密码登录

3.1 密钥认证原理

密码有被猜中或泄露的弱点。密钥认证生成一对钥匙:

  • 私钥:留在自己电脑上,绝不外传,是身份的唯一凭证
  • 公钥:放到服务器上,可以公开

登录时服务器用公钥出一道只有对应私钥才能解开的"数学难题",持有私钥的人能顺利登录,没有私钥的攻击者无从下手。

3.2 准备普通用户

sudo adduser study                # 新建普通用户 study
sudo passwd study                 # 设置登录密码
sudo usermod -aG wheel study      # 加入 wheel 组以获得 sudo 权限

3.3 确认 VNC 后路

在阿里云控制台进入 云服务器ECS → 实例 → 远程连接 → 选择 VNC 远程连接。登录成功后执行:

whoami    # 显示当前用户名,应为 study
tty       # VNC 登录显示 /dev/tty1,SSH 登录显示 /dev/pts/0 之类

3.4 在本地生成密钥对

# Mac/Linux 终端执行:
ssh-keygen -t ed25519 -C "你的名字-服务器加固"
# 查看公钥内容:
cat ~/.ssh/id_ed25519.pub
# Windows PowerShell:
type $env:USERPROFILE\.ssh\id_ed25519.pub

3.5 把公钥安装到服务器

sudo su - study
mkdir -p ~/.ssh
chmod 700 ~/.ssh
vi ~/.ssh/authorized_keys
# 在 vi 中按 i 进入编辑 → 粘贴公钥 → Esc → :wq 保存
chmod 600 ~/.ssh/authorized_keys
ls -l ~/.ssh      # 核对:authorized_keys 应为 -rw-------
权限陷阱:如果 .ssh 目录或 authorized_keys 文件权限过于宽松,SSH 会直接拒绝使用它登录且不报任何错误!

3.6 先验证密钥能登录,再禁用密码(铁律!)

最重要的一条操作纪律:必须先确认新的登录方式(密钥)确实可用,才能去禁用旧的(密码)。顺序反了就会把自己关在门外。
# 在自己电脑上用 SSH 客户端登录验证:
ssh study@服务器公网IP

3.7 为老师配置巡检账号

sudo adduser teacher
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 没有密码,单独配置免密 sudo:
echo "teacher ALL=(ALL) NOPASSWD: ALL" | sudo tee /etc/sudoers.d/teacher
sudo chmod 440 /etc/sudoers.d/teacher
sudo visudo -c      # 检查语法
sudo -u teacher sudo -n true && echo "teacher 免密 sudo 可用"
注意:安装的是老师的公钥,不是自己的私钥!私钥自始至终只留在自己电脑上。

四、加固 sshd 配置

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                       # 测试配置文件语法
sudo systemctl reload sshd         # 重载配置生效

五、两道门:安全组与主机防火墙

云服务器有两层防护:

  • 安全组:阿里云平台层防火墙,管"公网流量能不能进入实例"
  • 主机防火墙(firewalld):操作系统内部防火墙,管"流量到达后放不放行到具体服务"

5.1 配置主机防火墙

sudo firewall-cmd --permanent --add-service=ssh
sudo firewall-cmd --reload
sudo firewall-cmd --list-all
注意:修改规则时必须加 --permanent 再执行 --reload,否则重启后规则失效!

5.2 配置阿里云安全组

进入 实例 → 安全组 → 配置规则 → 入方向,保留 SSH(TCP 22) 和 ICMP,删除不需要的端口。

5.3 查看监听端口

sudo ss -tlnp

六、让服务器自动反击:fail2ban

fail2ban 持续监控登录日志,发现某个 IP 反复失败登录就自动封禁。

6.1 安装

sudo dnf install -y epel-release
sudo dnf install -y fail2ban

6.2 编写防护规则

sudo vi /etc/fail2ban/jail.d/sshd.local
[sshd]
enabled  = true
backend  = systemd
maxretry = 3
findtime = 600
bantime  = 3600

含义:10 分钟内失败 3 次,就把这个 IP 封禁一小时。

6.3 启动并查看

sudo systemctl enable --now fail2ban
sudo fail2ban-client status sshd

七、验证清单

验证项命令/操作
VNC 以 study 登录控制台 VNC 登录,tty 显示 /dev/tty1
SSH 密钥登录无需密码ssh study@公网IP
密码登录被拒绝尝试密码登录应失败
root 无法直接登录ssh root@公网IP 应被拒绝
sshd 配置无报错sudo sshd -t
防火墙只放行 sshsudo firewall-cmd --list-all
fail2ban 正在运行sudo fail2ban-client status sshd
teacher 免密 sudo 可用sudo -u teacher sudo -n true

八、本章小结

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

第2讲 · 网站上线

一、从 IP 到域名

域名解决了一串 IP 地址难记的问题。DNS(域名系统)负责把域名翻译成 IP 地址,相当于互联网的"通讯录"。要让别人通过域名访问主页,需要打通三个环节:

  1. DNS:让域名指向服务器 IP
  2. 开门:安全组和防火墙放行 80 端口
  3. Nginx:运行 Web 服务器程序接收请求并返回网页

二、域名解析

2.1 添加解析记录

在阿里云控制台进入 云解析DNS → 域名解析 → 解析设置 → 添加记录:

  • 记录类型选 A,主机记录填 @,记录值填服务器公网 IP
  • 再添加一条:主机记录填 www,记录值同样填公网 IP

TTL 默认 10 分钟,修改记录后最多约 10 分钟各地才会更新。

2.2 验证解析

nslookup 你的域名
nslookup www.你的域名

三、为网站开门

3.1 阿里云安全组

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

3.2 主机防火墙

sudo firewall-cmd --permanent --add-service=http
sudo firewall-cmd --reload
sudo firewall-cmd --list-services

四、安装 Nginx 并配置站点

4.1 安装与启动

sudo dnf install -y nginx
sudo systemctl enable --now nginx
systemctl status nginx
nginx -v

在自己电脑浏览器访问 http://服务器公网IP,看到 Nginx 默认测试页说明安装成功。

4.2 准备网站目录

sudo mkdir -p /var/www/mysite
sudo chown -R study:study /var/www/mysite
sudo chmod 755 /var/www/mysite
ls -ld /var/www/mysite

4.3 编写站点配置

sudo vi /etc/nginx/conf.d/mysite.conf
server {
    listen       80;
    server_name  example.com www.example.com;
    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;
    }
}

保存后先检查语法再重载:

sudo nginx -t
sudo systemctl reload nginx

五、发布个人主页

5.1 制作主页

首页底部必须显示 ICP 备案号并链接到工信部备案查询网站。可以用 AI 辅助生成主页,但必须自己检查备案号和链接是否正确。

5.2 上传到服务器

方式一:用 scp 上传

scp index.html study@你的服务器公网IP:/var/www/mysite/

方式二:直接在服务器上编辑

vi /var/www/mysite/index.html

六、排障实验:403 Forbidden

最常见的故障是文件权限不对。Nginx 工作进程的身份是 nginx 用户,不是 study。当文件权限设为 600 时,nginx 用户(作为"其他人")无法读取,返回 403。

# 查看 nginx 运行用户
ps -o user= -C nginx | sort -u
# 查看文件权限
ls -l /var/www/mysite/
# 查看错误日志
sudo tail -3 /var/log/nginx/mysite_error.log
# 修复:放宽权限
chmod 644 /var/www/mysite/test.html
# 验证
curl -I -H "Host: 你的域名" http://127.0.0.1/test.html
记住排查 403 的思路:先看错误日志找原因,再用 ls -l 核对权限。网页文件至少 644,目录至少 755。

七、看见你的第一位访客

# 持续显示访问日志末尾新增内容,Ctrl+C 退出
sudo tail -f /var/log/nginx/mysite_access.log

八、常见故障排查表

现象可能原因排查方法
域名打不开,IP 能打开解析未生效或记录填错nslookup 查看解析结果
连接超时80 端口没开检查安全组和 firewall-cmd
403 Forbidden文件或目录权限不足看错误日志 + ls -l 核对权限
404 Not Found文件名或路径不对确认文件名是 index.html
用域名访问仍是默认页server_name 写错检查配置 + nginx -t
Nginx 启动或重载失败配置语法错误sudo nginx -t 看报错行号

九、本章小结

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

第3讲 · HTTPS 与证书自动续期

一、你的网站正在"裸奔"

HTTP 协议传输的所有内容都是明文,经过的每一台网络设备都能原样看到访问内容。可以用 tcpdump 抓包验证:

sudo dnf install -y tcpdump
sudo tcpdump -i any -A -nn 'tcp port 80' | grep -a -E "GET |Host:|User-Agent|<title>"

抓包结果会显示请求的页面、域名、浏览器信息甚至网页标题——如果有登录表单,账号密码也会暴露。

二、HTTPS 与证书的原理

2.1 HTTPS 做了什么

  • 加密:传输内容变成只有浏览器和服务器才能解开的密文
  • 身份认证:证明连接的是真实服务器而非中间冒充者

2.2 证书颁发机构(CA)

证书由 CA 签发,浏览器内置了受信任的 CA 名单。本章使用 Let's Encrypt——免费、全自动的公益 CA。

2.3 CA 验证域名归属(HTTP-01)

  1. 服务器上运行 certbot 向 Let's Encrypt 申请证书
  2. Let's Encrypt 给 certbot 一串随机内容,要求放到 http://域名/.well-known/acme-challenge/随机文件名
  3. certbot 把文件写进网站目录
  4. Let's Encrypt 从互联网访问该地址,验证成功则签发证书
申请证书的三个前提(也是排查方向):域名正确解析到服务器、80 端口对外开放、Nginx 的 server_name 和 root 正确。

2.4 证书有效期

Let's Encrypt 证书有效期仅 90 天(2028年2月前将缩短至45天),且已停止发送到期提醒邮件。自动续期是必须完成的步骤,不是可选项。

三、开放 443 端口

HTTPS 使用 443 端口,两层门都要开:

sudo firewall-cmd --permanent --add-service=https
sudo firewall-cmd --reload
sudo firewall-cmd --list-services
80 端口不能关!原因:一是 HTTP 访问需要跳转到 HTTPS;二是证书续期时 Let's Encrypt 仍要通过 80 端口验证。

四、申请证书

4.1 安装 certbot

sudo dnf install -y certbot
certbot --version

4.2 先演练:--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. 说明演练成功。行尾反斜杠 \ 表示命令换行继续。

4.3 正式申请

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
sudo ls -l /etc/letsencrypt/live/example.com/
# 查看证书详细内容:
sudo openssl x509 -in /etc/letsencrypt/live/example.com/cert.pem -noout -issuer -dates -ext subjectAltName
文件内容用途
fullchain.pem证书 + 中间证书发给访问者,证明网站身份
privkey.pem证书私钥留在服务器,用于解密,绝不能泄露

五、配置 Nginx 启用 HTTPS

5.1 备份配置

sudo cp /etc/nginx/conf.d/mysite.conf /etc/nginx/conf.d/mysite.conf.bak

5.2 改写站点配置

sudo vi /etc/nginx/conf.d/mysite.conf

将文件内容替换为以下配置(把 example.com 换成你的域名,共 6 处):

# ① 80 端口:证书续期验证 + 跳转 HTTPS
server {
    listen       80;
    server_name  example.com www.example.com;
    location /.well-known/acme-challenge/ {
        root /var/www/mysite;
    }
    location / {
        return 301 https://$host$request_uri;
    }
}
# ② 443 端口:真正提供网站内容
server {
    listen       443 ssl;
    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;
    }
}

5.3 测试并生效

sudo nginx -t
sudo systemctl reload nginx

5.4 验证

# Windows PowerShell 中执行(注意写 curl.exe):
curl.exe -I http://example.com         # 应返回 301 Moved Permanently
curl.exe -I https://example.com        # 应返回 200 OK
curl.exe -I https://www.example.com    # 应返回 200 OK

六、配置自动续期

6.1 启用续期定时器

sudo systemctl enable --now certbot-renew.timer
systemctl list-timers 'certbot*'

6.2 续期后自动重载 Nginx

sudo vi /etc/letsencrypt/renewal-hooks/deploy/reload-nginx.sh
#!/bin/bash
systemctl reload 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

6.3 演练续期

sudo certbot renew --dry-run

看到 Congratulations, all simulated renewals succeeded 说明续期流程正常。

七、再抓一次包:HTTPS 的流量

# 抓取 443 端口数据包,抓够 40 个后自动停止
sudo tcpdump -i any -A -nn -c 40 'tcp port 443'

对比 HTTP 抓包:HTTPS 抓包看不到 GET、User-Agent、网页标题,内容已被加密。但域名仍然可见——因为浏览器建立加密连接前需先告诉服务器访问哪个网站,这一步是明文的。所以 HTTPS 隐藏的是你看了什么内容,而不是你访问了哪个网站。

八、验证与交付清单

验证项命令/操作
安全组和 firewalld 放行 443,80 仍开放检查安全组 + sudo firewall-cmd --list-services
证书包含两个域名,剩余约 89 天sudo certbot certificates
Nginx 配置通过sudo nginx -t
HTTP 自动跳转 HTTPS,地址栏有锁浏览器访问 http://域名
curl 验证 301 和 200curl.exe -I http://域名 / https://域名
续期定时器已启用systemctl list-timers 'certbot*'
续期演练成功sudo certbot renew --dry-run
备案号正常显示浏览器查看页面底部

九、常见故障排查表

现象可能原因排查方法
certbot 报 DNS problem: NXDOMAIN域名或 www 子域名没有解析记录nslookup 域名,补上 A 记录
certbot 报 Timeout during connect80 端口不通检查安全组和 firewall-cmd
certbot 报 unauthorized 且有 404验证文件没能被访问到核对 -w 与 Nginx root 一致
certbot 报 too many failed authorizations一小时内失败次数过多等待一小时,先用 --dry-run 演练
nginx -t 报 cannot load certificate证书路径写错对照 sudo certbot certificates 修改
https 访问超时443 端口没开检查安全组和 firewalld
访问 http 没有跳转配置未生效或浏览器缓存nginx -t 后 reload
锁的图标带有警告页面引用了 http:// 开头的资源改为 https:// 或相对路径

十、本章小结

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