我的运维笔记

《服务器运维》课程笔记 · 阿里云 ECS · Rocky Linux 9.8 · 2核2G

第 1 讲 服务器安全加固

这一讲做了什么

服务器刚买来接入公网,就开始被扫描器暴力猜密码。我先看了登录日志确认确实有人在爆破,然后沿着"攻击者会从哪里进来"这条线索,一步步把门堵死:新建普通用户、配置 SSH 密钥登录、禁用密码登录和 root 登录、配置安全组和 firewalld 两层防火墙、装 fail2ban 自动封禁爆破 IP,还给老师配了一个巡检账号。

关键命令

先看证据——查 SSH 登录失败记录:

sudo journalctl -u sshd | grep -i "failed" | tail -30

journalctl -u sshd 查看 sshd 服务的系统日志,grep -i "failed" 筛出登录失败行(-i 忽略大小写),tail -30 只看最后 30 条。

新建日常用的普通用户并加入 wheel 组(wheel 组成员才能用 sudo):

sudo adduser study
sudo passwd study
sudo usermod -aG wheel study

在自己电脑上生成密钥对(私钥留在本机,公钥放到服务器):

ssh-keygen -t ed25519 -C "我的名字-服务器加固"

把公钥装到服务器上,关键是权限:

mkdir -p ~/.ssh
chmod 700 ~/.ssh
vi ~/.ssh/authorized_keys   # 粘贴公钥(一整行)
chmod 600 ~/.ssh/authorized_keys
ls -l ~/.ssh                # 核对:-rw-------,属主是 study

验证密钥能登录后,加固 sshd 配置 /etc/ssh/sshd_config:

PubkeyAuthentication yes    # 允许密钥登录
PasswordAuthentication no   # 禁止密码登录
PermitRootLogin no          # 禁止 root 远程登录
MaxAuthTries 3              # 单次连接最多 3 次认证尝试
AllowUsers study teacher    # 登录白名单

sudo sshd -t                # 先测语法,没输出才继续
sudo systemctl reload sshd  # reload 不会断开当前连接

主机防火墙只放行 SSH(Rocky 上必须带 --permanent,否则重启就丢):

sudo firewall-cmd --permanent --add-service=ssh
sudo firewall-cmd --reload
sudo firewall-cmd --list-all
sudo ss -tlnp               # 看机器实际监听了哪些端口

安装并配置 fail2ban(10 分钟内失败 3 次就封 1 小时):

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

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

sudo systemctl enable --now fail2ban
sudo fail2ban-client status sshd   # 看 Banned IP list

遇到的问题和解决办法

第 2 讲 网站上线:域名解析与 Nginx

这一讲做了什么

这一讲把网站真正发布出去,打通三个环节:① 域名解析(DNS)——让域名指向服务器 IP;② 开门——安全组和防火墙放行 80 端口;③ Nginx——安装、写站点配置、发布带备案号的个人主页,还做了一次 403 排障实验。

关键命令

在阿里云云解析里添加两条 A 记录(主机记录分别为 @ 和 www,记录值填服务器公网 IP,TTL 默认 10 分钟),然后验证解析是否生效:

nslookup 我的域名
nslookup www.我的域名

为网页开门(两层门都要开):

# 安全组:入方向添加规则 TCP 80,授权对象 0.0.0.0/0
sudo firewall-cmd --permanent --add-service=http
sudo firewall-cmd --reload
sudo firewall-cmd --list-services

安装并启动 Nginx:

sudo dnf install -y nginx
sudo systemctl enable --now nginx
systemctl status nginx      # 应显示 active (running)
nginx -v

准备网站目录并写站点配置:

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

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 # 再生效

上传主页并验证 server_name 的作用:

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

curl -H "Host: 我的域名" http://127.0.0.1   # 带 Host 头 → 返回我的主页
curl http://127.0.0.1 | head -5             # 不带 → 返回 Nginx 默认页

做 403 实验并看日志:

echo "<h1>test</h1>" > /var/www/mysite/test.html
chmod 600 /var/www/mysite/test.html
curl -I -H "Host: 我的域名" http://127.0.0.1/test.html   # 403 Forbidden
sudo tail -3 /var/log/nginx/mysite_error.log             # (13: Permission denied)
chmod 644 /var/www/mysite/test.html
curl -I -H "Host: 我的域名" http://127.0.0.1/test.html   # 200 OK

看第一位访客:

sudo tail -f /var/log/nginx/mysite_access.log   # Ctrl+C 退出

遇到的问题和解决办法

第 3 讲 HTTPS 与证书自动续期

这一讲做了什么

先用 tcpdump 亲手"偷看"了一次自己网站的 HTTP 明文流量,证实了网站在"裸奔";然后给网站申请 Let's Encrypt 免费证书,改写 Nginx 配置启用 HTTPS(80 只负责跳转,443 提供内容),最后配置了证书自动续期。再抓一次包对比,流量已经全是密文了。

关键命令

抓包看 HTTP 明文的裸奔现场:

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

-i any 所有网卡抓包,-A 以文本显示内容,-nn 数字显示 IP 和端口。

开放 443 端口(安全组加 TCP 443 规则 + 防火墙,80 端口不能关:跳转和证书续期都要用):

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

安装 certbot 并先演练再正式申请(--webroot 方式,-w 是网站目录,-d 是域名):

sudo dnf install -y certbot

sudo certbot certonly --webroot -w /var/www/mysite \
  -d example.com -d www.example.com \
  -m 我的邮箱 --agree-tos --no-eff-email --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 正式申请

sudo certbot certificates   # 查看证书:域名、到期时间、文件位置
sudo openssl x509 -in /etc/letsencrypt/live/example.com/cert.pem \
  -noout -issuer -dates -ext subjectAltName

改写 Nginx 配置启用 HTTPS(80 跳转,443 提供内容):

sudo cp /etc/nginx/conf.d/mysite.conf /etc/nginx/conf.d/mysite.conf.bak   # 先备份

# ① 80 端口:提供续期验证文件 + 其余请求 301 跳转到 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;
# }

sudo nginx -t
sudo systemctl reload nginx

curl.exe -I http://example.com    # 应返回 301
curl.exe -I https://example.com   # 应返回 200

配置自动续期(证书只有 90 天有效期,必须靠自动化):

sudo systemctl enable --now certbot-renew.timer   # 启用续期定时器
systemctl list-timers 'certbot*'

# 续期后自动重载 Nginx:写 deploy 钩子脚本
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 certbot renew --dry-run    # 演练一次完整续期流程

再抓一次包对比 HTTPS:

sudo tcpdump -i any -A -nn -c 40 'tcp port 443'

遇到的问题和解决办法

三门课串起来:第 1 讲把门锁牢(密钥登录 + 两层防火墙 + fail2ban),第 2 讲让网站上线(DNS + Nginx + 备案号),第 3 讲给网站上锁(HTTPS + 自动续期)。三个贯穿始终的习惯:私钥永不外传、改配置先留后路、先验证再收口。