服务器安全加固
把一台“裸奔”的服务器加固成只认密钥、守得住、还会自动反击的服务器。
一、看见威胁:服务器一直在被扫描
服务器接入公网的那一刻起,自动化扫描程序就会昼夜遍历 IP。发现 22 端口(SSH 默认端口)后,会用大量常见用户名和密码反复尝试,这就是暴力破解。
sudo journalctl -u sshd | grep -i "failed" | tail -30
journalctl -u sshd:查看 SSH 服务日志。grep -i "failed":只筛登录失败记录,忽略大小写。tail -30:只看最后 30 条。
多半会看到大量陌生 IP 的失败记录,且绝大多数在尝试 root。加固思路就是沿着“攻击者会从哪里进来”,一处处把门堵死。
二、两条登录通道:SSH 与 VNC
- SSH(含控制台 Workbench):走公网、经过安全组 22 端口、受
sshd配置管辖。把 SSH 配置改崩或封掉 22,这条通道会一起断开,它不是后路。 - VNC:阿里云带外管理通道,相当于坐在服务器物理显示器前,用系统账号密码直接登录。不经过安全组,也不经过
sshd。
真正能救命的后路是 VNC。 后路只有亲自走通一次才靠得住。任何有风险的修改之前,先用 VNC 登录验证一遍。
whoami
tty
whoami:显示当前用户名,应为study。tty:VNC 显示/dev/tty1(本地控制台终端);SSH 显示/dev/pts/0这类伪终端。
VNC 使用提示:粘贴支持较差,长命令手动输入或使用控制台“复制命令输入”;忘记系统密码可在控制台重置实例密码,重启生效;禁用 SSH 密码登录和 root 远程登录只作用于 SSH,不影响 VNC 用系统密码登录。
三、用密钥代替密码登录
密码可能被猜中、也可能泄露。密钥认证使用一对相互配对的钥匙:
- 私钥:留在自己电脑上,绝不外传,是身份的唯一凭证。
- 公钥:放到服务器上,可以公开。
登录时服务器用公钥出一道只有对应私钥才能解开的“数学难题”。持有私钥的人能解开并登录;攻击者即使拿到公钥也无从下手。
1. 在自己电脑上生成密钥对
ssh-keygen -t ed25519 -C "你的名字-服务器加固"
-t ed25519:现代、短小而安全的密钥算法。-C:备注,方便日后辨认。- 一路回车即可,可以不设密码短语。
查看公钥。Windows(PowerShell):
type $env:USERPROFILE\.ssh\id_ed25519.pub
Mac / Linux:
cat ~/.ssh/id_ed25519.pub
复制以 ssh-ed25519 AAAA... 开头的一整行,中间不能有换行。不带 .pub 的是私钥,切勿外传。
2. 把公钥安装到服务器
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
权限陷阱:.ssh 目录必须是 700,authorized_keys 必须是 600,属主必须是本人。权限过松时 SSH 会直接拒绝使用它登录,而且不给出任何报错。
3. 铁律:先验证密钥能登录,再禁用密码
ssh study@服务器公网IP
能直接登入且不要求输入密码,说明密钥配置成功。失败则回控制台检查公钥、权限、用户名。验证成功之前,绝对不要进行下一步。
4. 为老师配置巡检账号 teacher
绝对不要把私钥发给老师。 正确做法是:老师持有自己的密钥对,你只把老师的公钥安装到服务器上。
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
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 可用"
teacher 没有密码,而 Rocky 规定 wheel 组成员使用 sudo 必须输入本人密码,所以单独写免密规则。visudo -c 必须执行:sudo 配置写错,所有账号的 sudo 都会失效,包括 study。万一如此,用 VNC 以 root 登录修复。
四、加固 sshd 配置
sudo vi /etc/ssh/sshd_config
PubkeyAuthentication yes
PasswordAuthentication no
PermitRootLogin no
MaxAuthTries 3
ClientAliveInterval 300
ClientAliveCountMax 2
AllowUsers study teacher
PubkeyAuthentication yes:允许密钥登录,本章加固的基础。PasswordAuthentication no:禁止密码登录,务必确认密钥能登录后再改。PermitRootLogin no:禁止 root 直接远程登录,缩小攻击面。MaxAuthTries 3:单次连接最多 3 次认证尝试,拖慢暴力破解。ClientAliveInterval 300/ClientAliveCountMax 2:每 300 秒探测客户端,连续 2 次无响应就断开,清理空闲会话。AllowUsers study teacher:登录白名单,写错用户名或漏掉 teacher,对应的人就会被挡在门外。
sudo sshd -t
sudo systemctl reload sshd
sshd -t 没有输出就代表语法正确;reload 不会断开当前连接,比 restart 安全。
五、两道门:安全组与主机防火墙
- 安全组:阿里云平台层防火墙,管“公网流量能不能进入实例”。
- 主机防火墙 firewalld:操作系统内部防火墙,管“流量到达实例后,放不放行到具体服务”。
两层相互独立、都需要配置,原则都是最小化:只开必须的门。
sudo firewall-cmd --permanent --add-service=ssh
sudo firewall-cmd --reload
sudo firewall-cmd --list-all
Rocky 上最容易被忽略的细节:修改规则时必须加 --permanent,再执行 --reload,否则规则在重启后会失效。
安全组入方向规则:必须保留 SSH(TCP 22),删掉它本机 SSH 和 Workbench 会同时中断,只剩 VNC 能进;删除或收紧用不到的端口;ICMP-IPv4 可以保留,用于 ping 和连通性诊断。
安全组按“协议 + 端口”两个维度控制。TCP / UDP 才有端口概念;ICMP 是网络层诊断协议,本身不使用端口,控制台端口栏只能填 -1/-1 或显示“任何”,这只是占位符,不代表所有端口都被打开。放行 ICMP 只是让别人能 ping 通你的机器,既无法登录,也无法传输数据。
查看实际监听的端口,与安全组规则对照:
sudo ss -tlnp
六、fail2ban:让服务器自动反击
前面的加固是“被动”防守。fail2ban 持续盯着登录日志,发现某个 IP 反复失败尝试登录,就自动把它封禁一段时间。
sudo dnf install -y epel-release
sudo dnf install -y fail2ban
规范做法是在 jail.d/ 下新建 .local 文件,而不是直接修改主配置文件 jail.conf,这样软件升级时配置不会被覆盖。
sudo vi /etc/fail2ban/jail.d/sshd.local
[sshd]
enabled = true
backend = systemd
maxretry = 3
findtime = 600
bantime = 3600
连起来读就是一句话:10 分钟内失败 3 次,就把这个 IP 封禁一小时。
backend = systemd 是 Rocky 9 的关键:新系统日志由 systemd 统一管理,网上许多旧教程仍在读取 /var/log/secure,那种写法在这里不生效。
sudo systemctl enable --now fail2ban
sudo fail2ban-client status sshd
重点看 Banned IP list,列出的就是被服务器自动封禁的攻击者 IP。名单暂时为空不代表操作有误,只是还没被扫描器盯上;规则已生效,挂一段时间自然会出现记录。
七、验证与提交
- 能通过控制台 VNC 以 study 登录(
tty显示/dev/tty1)。 - 从自己电脑
ssh study@公网IP能登录,且不需要输入密码。 - 用密码登录会被拒绝。
- root 无法直接登录。
sudo sshd -t没有报错。sudo firewall-cmd --list-all里能看到 ssh,且没有多余端口。sudo fail2ban-client status sshd显示规则正在运行。- teacher 账号已装好老师的公钥。
sudo -u teacher sudo -n true成功,teacher 可免密使用 sudo。
提交方式:只需要交给老师主机的公网 IP。老师会用自己的私钥,通过你安装好的 teacher 公钥登录检查。任何时候都不要把自己的私钥发给任何人。
八、遇到问题怎么办
- SSH 连不上:用阿里云控制台 VNC 登录,把
sshd_config改回来,再sudo sshd -t验证、sudo systemctl reload sshd生效。 - 密钥登录总要求输入密码:99% 是权限问题。检查
~/.ssh是否 700、authorized_keys是否 600、属主是否本人。 - 老师连不上:多半是
AllowUsers里漏了 teacher,或 teacher 的.ssh目录属主没有改回 teacher。 - sudoers 语法错误:用 VNC 以 root 登录,修正或删除
/etc/sudoers.d/teacher,再执行visudo -c。 - firewalld 改了不生效:检查是不是忘了
--permanent或忘了--reload。
网站上线:域名解析与 Nginx 个人主页
为已备案域名配置解析,安装 Nginx,发布带备案号的个人主页。
一、从 IP 到域名:三个环节
DNS(域名系统)负责把域名翻译成 IP 地址。要让别人通过域名看到你的主页,需要打通三个环节:
- DNS:让域名指向你的服务器 IP。
- 开门:让安全组和防火墙放行网页访问(80 端口)。
- Nginx:在服务器上运行一个程序,接收请求并把主页发出去。
添加解析记录时会遇到三个字段:记录类型(A 记录,指向 IPv4 地址)、主机记录(@ 代表域名本身,www 代表 www.域名)、TTL(缓存时长)。
nslookup 你的域名
nslookup www.你的域名
二、为网站开门
服务器要对外提供网页,需要开放 HTTP 使用的 80 端口。两层门都要开。
阿里云安全组:添加规则,协议 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
为自己的站点单独建目录:
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:
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
四、排障实验:403 Forbidden 与权限
如果 Nginx 工作进程无法读取文件,会返回 403。排查思路:先看错误日志找原因,再用 ls -l 核对权限。
sudo tail -3 /var/log/nginx/mysite_error.log
网页文件至少需要 644,目录至少需要 755,Nginx 才能正常读取。
chmod 644 /var/www/mysite/index.html
给网站加上安全锁:HTTPS 与证书自动续期
申请免费 HTTPS 证书,让网站从“不安全”变为带安全锁的加密网站,并配置自动续期。
一、HTTPS 与证书的原理
HTTPS 解决两个问题:加密(传输内容变成密文)和身份认证(证明服务器真实身份)。认证依靠数字证书。
本章使用 Let's Encrypt,通过 HTTP-01 验证。三个前提:域名正确解析、80 端口对外开放、Nginx 能把验证文件发出去。
二、开放 443 端口
按照最小化原则,开放 HTTPS 使用的 443 端口。注意:80 端口不能关,跳转和续期都要用到。
sudo firewall-cmd --permanent --add-service=https
sudo firewall-cmd --reload
三、申请证书
安装 certbot 并使用 webroot 方式申请证书:
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
四、配置 Nginx 启用 HTTPS
将站点配置分为 80 端口(做跳转和 ACME 验证)和 443 端口(提供内容):
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;
}
}
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;
}
}
sudo nginx -t
sudo systemctl reload nginx
五、配置自动续期
sudo systemctl enable --now certbot-renew.timer
systemctl list-timers 'certbot*'
配置 deploy 钩子,让续期后自动重载 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 certbot renew --dry-run