我的运维笔记

《服务器运维》课程 · 前三讲实操记录 · 阿里云 ECS / Rocky Linux 9.8

第 1 讲 服务器安全加固 把一台"裸奔"的服务器加固成只认密钥、守得住、会反击的服务器

这一章做了什么

关键命令

# 查看谁在爆破我的服务器:筛出 sshd 日志中含 failed 的最后 30 行
sudo journalctl -u sshd | grep -i "failed" | tail -30

# 新建日常用户并加入 wheel 组(能用 sudo)
sudo adduser study
sudo passwd study
sudo usermod -aG wheel study

# 在自己电脑上生成密钥对(私钥永不外传)
ssh-keygen -t ed25519 -C "myname-服务器加固"

# 服务器上安装公钥:目录 700、文件 600,缺一不可
sudo su - study
mkdir -p ~/.ssh
chmod 700 ~/.ssh
chmod 600 ~/.ssh/authorized_keys

# 为 teacher 配置免密 sudo(teacher 没有密码,wheel 的 sudo 要输本人密码,用不了)
echo "teacher ALL=(ALL) NOPASSWD: ALL" | sudo tee /etc/sudoers.d/teacher
sudo chmod 440 /etc/sudoers.d/teacher
sudo visudo -c                                # 检查语法,全部 parsed OK 才安全

# 加固 sshd(先验证密钥能登录,再改这些收口)
sudo vi /etc/ssh/sshd_config
#   PubkeyAuthentication yes / PasswordAuthentication no
#   PermitRootLogin no / MaxAuthTries 3
#   AllowUsers study teacher
sudo sshd -t                                  # 先测语法,无输出即正确
sudo systemctl reload sshd                    # reload 不断开当前连接

# 防火墙:Rocky 上必须 --permanent + --reload,否则重启后失效
sudo firewall-cmd --permanent --add-service=ssh
sudo firewall-cmd --reload
sudo firewall-cmd --list-all
sudo ss -tlnp                                 # 对照实际监听的端口

# fail2ban:Rocky 默认源没有,先装 EPEL
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

遇到的问题和解决办法

本章收获的三个习惯:私钥永不外传、改配置先留后路(VNC)、先验证再收口。

第 2 讲 网站上线 域名解析 + Nginx 个人主页 + 备案号

这一章做了什么

关键命令

# 在自己电脑上验证域名解析(记录类型 A,主机记录 @ 和 www,TTL 默认 10 分钟)
nslookup 我的域名
nslookup www.我的域名

# 防火墙放行 HTTP
sudo firewall-cmd --permanent --add-service=http
sudo firewall-cmd --reload
sudo firewall-cmd --list-services             # 应包含 ssh 和 http

# 安装并启动 Nginx
sudo dnf install -y nginx
sudo systemctl enable --now nginx
systemctl status nginx

# 准备网站目录(交给 study,以后不用 sudo 就能改网页)
sudo mkdir -p /var/www/mysite
sudo chown -R study:study /var/www/mysite
sudo chmod 755 /var/www/mysite

# 站点配置 /etc/nginx/conf.d/mysite.conf
#   listen 80;  server_name example.com www.example.com;
#   root /var/www/mysite;  index index.html;
sudo nginx -t                                 # 改完配置先测语法
sudo systemctl reload nginx

# 上传主页(scp 用的是同一把密钥,不需要密码)
scp index.html study@服务器公网IP:/var/www/mysite/

# 验证 server_name 机制:Host 不同,返回的站点不同
curl -H "Host: 我的域名" http://127.0.0.1     # 返回我的主页
curl http://127.0.0.1 | head -5               # 返回 Nginx 默认页

# 403 排障实验
chmod 600 /var/www/mysite/test.html           # 故意把权限收紧
curl -I -H "Host: 我的域名" http://127.0.0.1/test.html   # 403
ps -o user= -C nginx | sort -u                # 工作进程以 nginx 用户运行
sudo tail -3 /var/log/nginx/mysite_error.log  # 看到 Permission denied
chmod 644 /var/www/mysite/test.html           # 修复:其他人可读 → 200

# 看见第一位访客
sudo tail -f /var/log/nginx/mysite_access.log

遇到的问题和解决办法

合规硬性要求:首页底部必须显示 ICP 备案号并链接到 https://beian.miit.gov.cn/ ;网站开通后 30 日内还需办理公安联网备案。

第 3 讲 HTTPS 与证书自动续期 让网站从不安全的 http:// 变成带安全锁的 https://

这一章做了什么

关键命令

# 抓包看看 HTTP 有多"裸":-i any 全网卡,-A 文本显示,-nn 不解析名称
sudo dnf install -y tcpdump
sudo tcpdump -i any -A -nn 'tcp port 80' | grep -a -E "GET |Host:|User-Agent|"

# 放行 443
sudo firewall-cmd --permanent --add-service=https
sudo firewall-cmd --reload

# 安装 certbot,先演练再正式申请(防止一小时内失败次数超限被暂时拒绝)
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
# 演练成功(The dry run was successful.)后去掉 --dry-run 正式申请

sudo certbot certificates                    # 查看证书域名、到期时间(约 90 天)
sudo openssl x509 -in /etc/letsencrypt/live/example.com/cert.pem \
  -noout -issuer -dates -ext subjectAltName  # 核对颁发者、有效期、域名列表

# HTTPS 站点配置要点(mysite.conf 拆成两个 server 块)
#   80:  location /.well-known/acme-challenge/ { root /var/www/mysite; }
#        location / { return 301 https://$host$request_uri; }
#   443: listen 443 ssl;
#        ssl_certificate     .../fullchain.pem;
#        ssl_certificate_key .../privkey.pem;
#        ssl_protocols TLSv1.2 TLSv1.3;
sudo nginx -t
sudo systemctl reload nginx

# 自动续期:定时器 + deploy 钩子
sudo systemctl enable --now certbot-renew.timer
systemctl list-timers 'certbot*'
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                 # 模拟续期,验证流程是通的

# 对比实验:加密后的流量
sudo tcpdump -i any -A -nn -c 40 'tcp port 443'</code></pre>

  <h3>遇到的问题和解决办法</h3>
  <ul>
    <li><b>certbot 报 DNS problem: NXDOMAIN</b>:域名或 www 子域名缺解析记录,<code>nslookup</code> 检查后补 A 记录。</li>
    <li><b>certbot 报 unauthorized</b>:验证文件访问不到——核对 <code>-w</code> 目录是否与 Nginx 的 root 一致、<code>server_name</code> 是否包含该域名。</li>
    <li><b>nginx -t 报 cannot load certificate</b>:证书路径里域名写错,对照 <code>certbot certificates</code> 的输出核对目录名。</li>
    <li><b>锁的图标带警告</b>:页面里还引用了 <code>http://</code> 开头的资源,改成 <code>https://</code> 或相对路径。</li>
    <li><b>改坏了想恢复</b>:改配置前先备份,且备份文件名不能以 .conf 结尾(否则会被 Nginx 一并加载造成重复配置):<code>cp mysite.conf mysite.conf.bak</code>。</li>
  </ul>

  <div class="box"><b>两个重要认知:</b>① 证书私钥 privkey.pem 和第 1 讲的 SSH 私钥同理,谁拿到谁就能冒充我的网站,绝不外泄;② HTTPS 加密的是"看了什么内容",但"访问了哪个网站"(域名)在建立连接时仍是明文。80 端口不能关:HTTP→HTTPS 跳转和证书续期验证都靠它。</div>
</section>

</main>

<footer>
  <a href="https://beian.miit.gov.cn/" target="_blank" rel="noopener noreferrer">皖ICP备2026034117号</a>
</footer>

</body>
</html>