第 9 章 · 服务器安全加固
本章把「怎么样的服务器才是安全的」变成可执行的清单:SSH 加固、防火墙策略、补丁更新、SELinux/AppArmor、审计日志、入侵检测与应急响应。学完你能给自己的每一台服务器做一次完整加固,并知道被攻击时从哪里找证据。
本章目录
9.1 安全基线十项 9.2 SSH 加固 9.3 防火墙策略 9.4 更新与补丁 9.5 账号与权限审计 9.6 SELinux / AppArmor 9.7 auditd 审计 9.8 入侵检测与日志取证 9.9 应急响应 自测题9.1安全基线十项(新服务器落地清单)
1最小安装
不装图形、不装用不到的服务;装机后 systemctl list-units --type=service 清理可疑自启。
2SSH 加固
密钥登录、禁密码、禁 root 直登、改端口(见 9.2)。
3防火墙默认拒绝
只放行必要端口;数据库等内网服务只对信任 IP 开放。
4及时打补丁
apt/dnf 定期升级;开启自动安全更新。
5最小权限
服务用独立账号、sudo 精确授权(第 5 章)。
6文件权限
密钥 600、配置 644、无 777;排查 setuid。
7日志与审计
确保 auth 日志、auditd、日志远程/定期备份。
8Fail2ban 防爆破
登录失败自动封 IP(见 9.2)。
9SELinux/AppArmor 开启
别一装就 disable,学会按日志放行。
10备份与恢复演练
数据与配置定期备份,并真的恢复过(第 17 章)。
Lynis(apt install lynis / dnf install lynis)可对系统自动审计打分并给出建议;配合第 10 章的监控工具,就是「面板给的安全感」的可靠替代。
9.2SSH 加固(第一优先,被爆破的绝对重灾区)
攻击日志里 90% 的噪音是 SSH 爆破。加固后这些请求会直接消失或被打回去。
Port 2222 # 换端口(防扫描噪音;云安全组同步放行)
PermitRootLogin no # 禁止 root 直接登录(用普通用户+sudo)
PasswordAuthentication no # 禁用密码登录,只用密钥
PubkeyAuthentication yes
MaxAuthTries 3 # 登录尝试上限
LoginGraceTime 30 # 登录超时 30 秒
AllowUsers alice bob # 白名单用户(强烈建议)
ClientAliveInterval 120 # 心跳保活(断开僵死连接)
ssh 试一次),再禁密码;② 改完先 sshd -t 验证语法再 restart;③ 永远保持一个「后备通道」(云控制台 VNC)以防把自己锁在门外。失败重连会把自己锁死 —— 用 tmux + 测试连接双保险。
Fail2ban:自动封禁爆破 IP
sudo apt install fail2ban # Ubuntu;Rocky: dnf install fail2ban
sudo systemctl enable --now fail2ban
# 配置在 /etc/fail2ban/jail.local(覆盖默认 jail.conf)
# [sshd] enabled=true maxretry=5 bantime=1h
sudo fail2ban-client status sshd # 看封禁情况(几小时就被爆破几十次的常态)
sudo fail2ban-client set sshd unbanip 1.2.3.4 # 手动解封误封 IP
9.3防火墙策略最佳实践(默认拒绝 + 白名单)
- 入站默认拒绝:只放行 22(或你的 SSH 端口)、80/443;其他业务端口按需。
- 内网服务只对信任 IP:数据库 3306、Redis 6379、面板端口绝不暴露公网 —— 这是「被脱库」的第一大原因。
- 出站也默认拒绝(进阶):服务器被攻破后攻击者想外连下载工具会被挡。
- 云安全组 + 系统防火墙双保险:云控制台安全组是第一道,服务器 ufw/firewalld 是第二道。
具体命令见第 8 章 8.5(ufw / firewall-cmd)。
9.4更新与补丁:把漏洞关在门外
# Ubuntu:安装并启用 unattended-upgrades(默认已装)
sudo dpkg-reconfigure --priority=low unattended-upgrades
sudo apt list --installed | grep unattended
# Rocky:dnf-automatic 定时自动安装安全更新
sudo dnf install dnf-automatic
sudo systemctl enable --now dnf-automatic.timer
# 手动检查是否有安全更新(Ubuntu 特有)
sudo apt update && apt list --upgradable
apt-get -s upgrade | grep security
9.5账号与权限审计:清理后门入口
cat /etc/passwd | grep -v nologin | grep -v false # 能登录的账号清单
awk -F: '$3==0 {print $1}' /etc/passwd # UID=0 账号(理论上只能有 root)
cat /etc/sudoers.d/* 2>/dev/null; grep -r "" /etc/sudoers.d/
find / -perm -4000 -type f 2>/dev/null # setuid 后门排查
lastlog | head -20 # 各账号最后登录
last -f /var/log/wtmp | head # 登录历史
删除不用的账号:userdel -r;离职人员立刻删账号/改密钥;云厂商默认的初始用户(如 ubuntu、rocky)可以保留但要换密钥。
9.6SELinux(Rocky)与 AppArmor(Ubuntu):强制访问控制
- 传统权限(第 5 章)是「自主访问控制」(用户自己决定);SELinux/AppArmor 是强制访问控制:即使 root 也被约束 —— 服务被攻破后也动弹不得。
- Rocky 默认 SELinux=Enforcing。很多新手「装完服务连不上」就是被它拦的。正确做法不是关闭,而是看日志放行:
getenforce # Enforcing/Permissive/Disabled
sudo ausearch -m avc -ts recent # 最近被拒的操作(avc 拒绝日志)
sudo grep "avc: denied" /var/log/audit/audit.log | tail
# 确认是 SELinux 拦截后,放行(示例:给 httpd 开放端口/目录)
sudo semanage port -a -t http_port_t -p tcp 8080
sudo semanage fcontext -a -t httpd_sys_content_t "/data/web(/.*)?"
sudo restorecon -Rv /data/web
# 真拿不准时:临时 Permissive 观察(setenforce 0),修好再开回 Enforcing
AppArmor(Ubuntu):类似但基于路径配置,aa-status 查看,/etc/apparmor.d/ 配置。Ubuntu 上多数服务默认 profile,冲突时看 journalctl 的 AppArmor 拒绝记录。
9.7auditd:系统级审计(谁动了什么)
auditd 记录「谁在什么时间对什么文件/命令做了什么」,是取证与合规的核心。
sudo apt install auditd # Ubuntu;Rocky: dnf install audit
sudo systemctl enable --now auditd
# 规则:监控 /etc/passwd、/etc/shadow 的写入与 /bin 改动
sudo auditctl -w /etc/passwd -p wa -k passwd_watch
sudo auditctl -w /etc/shadow -p wa -k shadow_watch
sudo auditctl -l # 查看规则
sudo ausearch -k passwd_watch # 查谁改过 passwd(证据!)
# 永久规则写 /etc/audit/rules.d/audit.rules
9.8入侵检测与日志取证:被攻击了怎么查
第一步:看登录与认证日志(攻击最常留痕的地方)
# Ubuntu: /var/log/auth.log;Rocky: /var/log/secure
sudo tail -100 /var/log/auth.log # 最近登录/失败
sudo grep "Failed password" /var/log/auth.log | awk '{print $(NF-3)}' | sort | uniq -c | sort -rn
# ↑ 统计爆破来源 IP 排行(你问的「知道哪里攻击的」就是这个)
sudo grep "Accepted" /var/log/auth.log # 成功登录记录(重点核对是不是自己)
last -i | head # 登录会话历史(IP)
lastb -i | head # 失败登录(爆破记录)
who / w # 当前在线用户(发现陌生会话=已被入侵迹象)
第二步:入侵迹象快速体检
top / htop # 异常高 CPU 进程(挖矿病毒特征:CPU 100% + 陌生进程名)
ps aux --sort=-%cpu | head # 按 CPU 排名的进程
ss -tunap # 陌生对外连接(挖矿外连矿池、反弹 shell)
crontab -l; ls /etc/cron.* # 被植入的定时任务后门
ls -la /tmp /dev/shm # 攻击者爱放文件的目录(可执行文件可疑)
cat /etc/rc.local 2>/dev/null
systemctl list-units --type=service --state=running # 陌生服务
find / -name "*miner*" -o -name "*xmrig*" 2>/dev/null
rkhunter --check # 根套件扫描(dnf/apt 安装后先 rkhunter --update)
sudo chkrootkit # 同类扫描工具
last -20 # 登录历史里的异常时段
第三步:服务被攻击的具体案例怎么看
tail -100 /var/log/nginx/access.log
grep -E "\.(php|jsp|asp)" access.log | awk '{print $1}' | sort | uniq -c | sort -rn
grep -iE "union|select|/etc/passwd|\.\./" access.log # SQL注入/路径穿越特征
grep -E '" (400|403|404|500|502) ' access.log | tail # 异常状态码
find /data/web -name "*.php" -newer /data/web/index.html # 最近新增的 php(webshell 特征)
grep -r "eval\|base64_decode\|shell_exec" /data/web --include="*.php" # 一句话木马特征函数
9.9应急响应流程:确认被入侵后按这个走
应急响应的原则是「先保住证据和止损,再谈修复」。很多新手一上来就删文件重装,攻击者怎么进来的永远不知道 —— 下个月还会再来。第 15 章会从攻防视角再深化。
本章自测题
- 说出安全基线里最优先的 4 项。
- sshd_config 里禁 root 直登、禁密码登录、换端口分别怎么写?改完先做什么验证?
- Fail2ban 的作用与核心配置项(maxretry/bantime)。
- 数据库端口(3306)为什么不能暴露公网?正确做法?
- Rocky 装完服务连不上,如何判断是不是 SELinux 并放行?
- auditd 监控 /etc/shadow 被修改,写出规则与查询命令。
- 如何统计「失败登录来源 IP 排行」?(完整命令)
- 发现服务器被入侵,前 3 步动作是什么?
参考答案
1. SSH 加固、防火墙默认拒绝、及时补丁、最小权限(外加日志审计与备份)。
2. PermitRootLogin no / PasswordAuthentication no / Port 2222;改完 sshd -t 验语法再 restart,且先确认密钥登录可用。
3. 登录失败超阈值自动封禁 IP;maxretry=失败次数阈值,bantime=封禁时长。
4. 3306 暴露公网=数据库可被全网爆破/脱库;正确做法:防火墙只放行信任 IP,或仅内网访问。
5. getenforce 看状态,ausearch -m avc 看拒绝日志,确认后 semanage 放行端口/目录;不要直接关闭。
6. auditctl -w /etc/shadow -p wa -k shadow_watch;ausearch -k shadow_watch。
7. sudo grep "Failed password" /var/log/auth.log | awk '{print $(NF-3)}' | sort | uniq -c | sort -rn
8. 保留证据(日志/快照不删)→ 断外联止损 → 备份现场,再定位根因。