Linux 运维与安全专家 09 · 服务器安全加固

第 9 章 · 服务器安全加固

阶段 C预计 6–8 小时核心目标

本章把「怎么样的服务器才是安全的」变成可执行的清单:SSH 加固、防火墙策略、补丁更新、SELinux/AppArmor、审计日志、入侵检测与应急响应。学完你能给自己的每一台服务器做一次完整加固,并知道被攻击时从哪里找证据。

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 爆破。加固后这些请求会直接消失或被打回去。

/etc/ssh/sshd_config · 关键行(改完 systemctl restart sshd)
Port 2222                    # 换端口(防扫描噪音;云安全组同步放行)
PermitRootLogin no           # 禁止 root 直接登录(用普通用户+sudo)
PasswordAuthentication no    # 禁用密码登录,只用密钥
PubkeyAuthentication yes
MaxAuthTries 3               # 登录尝试上限
LoginGraceTime 30            # 登录超时 30 秒
AllowUsers alice bob         # 白名单用户(强烈建议)
ClientAliveInterval 120      # 心跳保活(断开僵死连接)
改 sshd_config 前必读 ① 先确保密钥登录已生效(另一终端 ssh 试一次),再禁密码;② 改完先 sshd -t 验证语法再 restart;③ 永远保持一个「后备通道」(云控制台 VNC)以防把自己锁在门外。失败重连会把自己锁死 —— 用 tmux + 测试连接双保险。

Fail2ban:自动封禁爆破 IP

终端 · 安装与配置 Fail2ban
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防火墙策略最佳实践(默认拒绝 + 白名单)

具体命令见第 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
原则 内核/大版本升级(如 Ubuntu 24.04→26.04)属于「计划性操作」,先在测试机验证、备份后挑低峰执行;安全补丁则越快越好。每周固定一个「更新窗口」是专业习惯。

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):强制访问控制

终端 · SELinux 排障
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
不要 setenforce 0 了事 SELinux 是 Rocky 系「为什么比 Ubuntu 安全」的重要原因。用「看日志 → 精确放行」替代「直接关闭」;确实长期用不到的才考虑 Disabled(需改 /etc/selinux/config 并重启)。

AppArmor(Ubuntu):类似但基于路径配置,aa-status 查看,/etc/apparmor.d/ 配置。Ubuntu 上多数服务默认 profile,冲突时看 journalctl 的 AppArmor 拒绝记录。

9.7auditd:系统级审计(谁动了什么)

auditd 记录「谁在什么时间对什么文件/命令做了什么」,是取证与合规的核心。

终端 · 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                   # 登录历史里的异常时段

第三步:服务被攻击的具体案例怎么看

终端 · Web 攻击痕迹
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应急响应流程:确认被入侵后按这个走

先取证,再断网,别急着删 发现入侵时的正确顺序:① 保留证据(原样复制日志/进程快照/内存转储,别清日志别重启);② 断外联(防火墙阻断陌生出站、云控制台隔离);③ 备份现场(磁盘镜像/关键日志);④ 定位根因(按 9.8 体检);⑤ 清除与加固(杀进程、删后门、改全部密码与密钥、打补丁);⑥ 恢复与复盘(从干净备份恢复,写入侵报告,堵住入口)。

应急响应的原则是「先保住证据和止损,再谈修复」。很多新手一上来就删文件重装,攻击者怎么进来的永远不知道 —— 下个月还会再来。第 15 章会从攻防视角再深化。

本章自测题

  1. 说出安全基线里最优先的 4 项。
  2. sshd_config 里禁 root 直登、禁密码登录、换端口分别怎么写?改完先做什么验证?
  3. Fail2ban 的作用与核心配置项(maxretry/bantime)。
  4. 数据库端口(3306)为什么不能暴露公网?正确做法?
  5. Rocky 装完服务连不上,如何判断是不是 SELinux 并放行?
  6. auditd 监控 /etc/shadow 被修改,写出规则与查询命令。
  7. 如何统计「失败登录来源 IP 排行」?(完整命令)
  8. 发现服务器被入侵,前 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. 保留证据(日志/快照不删)→ 断外联止损 → 备份现场,再定位根因。