服务器被攻击!完整安全加固清单汇总

服务器被攻击!完整安全加固清单汇总

服务器被黑不是小概率事件。只要服务器暴露在公网,每时每刻都在被扫描、被尝试弱口令、被探测漏洞。安全加固不是"用不用心"的问题,而是"有没有做"的问题。这篇文章给出一份完整的 Linux 服务器安全加固清单,涵盖账户安全、SSH 加固、防火墙配置、服务安全、日志审计、入侵检测等核心环节。每个条目都讲解为什么要做、怎么做、不做的风险是什么,让初中级运维工程师能照着操作、落地执行。

1. 什么时候需要做安全加固

安全加固应该在服务器上线前就完成,而不是等到被黑之后。以下几个节点必须做安全加固:

  • 新服务器交付后、上线前:服务器默认配置面向易用性,不面向安全。

  • 系统重装或重大变更后:系统变更可能重置安全配置。

  • 漏洞爆发后:如 OpenSSH RCE(CVE-2024-6387)、Linux 内核提权漏洞等。

  • 通过等保测评前:等级保护要求明确的安全基线。

  • 服务器被黑后复盘时:被黑说明存在安全缺口,需要亡羊补牢。

本文适用于 CentOS/RHEL 7/8/9、Ubuntu 18.04/20.04/22.04、Debian 10/11/12 等主流发行版。

2. 加固前的准备工作

加固是高风险操作,配置错误可能导致服务器无法登录或服务中断。操作前必须完成以下准备:

2.1 备份当前配置

复制代码
# 备份所有即将修改的配置文件
mkdir /opt/security-hardening-backup-$(date +%Y%m%d)
cd /opt/security-hardening-backup-$(date +%Y%m%d)

# 备份系统关键配置
cp /etc/ssh/sshd_config ./sshd_config.bak
cp /etc/pam.d/system-auth ./system-auth.bak
cp /etc/login.defs ./login.defs.bak
cp /etc/fstab ./fstab.bak
cp /etc/sysctl.conf ./sysctl.conf.bak
cp /etc/rsyslog.conf ./rsyslog.conf.bak
cp /etc/hosts.allow ./hosts.allow.bak
cp /etc/hosts.deny ./hosts.deny.bak
cp /etc/passwd ./passwd.bak
cp /etc/shadow ./shadow.bak
cp /etc/group ./group.bak
cp -r /etc/iptables* ./iptables.bak 2>/dev/null || true

# 备份 systemd 服务列表
systemctl list-units --type=service --all > services-backup.txt

# 记录当前运行的进程和网络连接(基线)
ps auxf > processes-backup.txt
netstat -tulnp > listening-ports-backup.txt
ss -tulnp > ss-backup.txt

# 记录当前用户和权限
cat /etc/passwd > users-backup.txt
cat /etc/group > groups-backup.txt
getent shadow > shadow-backup.txt

echo"Backup completed. Files are in /opt/security-hardening-backup-$(date +%Y%m%d)"

2.2 创建云服务器快照(强烈建议)

云服务器(阿里云、腾讯云、AWS 等)支持创建快照,这一步不能省:

复制代码
# 阿里云 CLI 创建快照(需要先安装 aliyun CLI 并配置 AK)
aliyun ecs CreateSnapshot --DiskId disk-xxx --Description "pre-security-hardening-$(date +%Y%m%d)"

# 腾讯云 CLI
# qcloudcli cvm CreateSnapshot --instanceId ins-xxx --snapshotName "pre-hardening-$(date +%Y%m%d)"

# AWS CLI
# aws ec2 create-snapshot --description "pre-hardening-$(date +%Y%m%d)" --volume-id vol-xxx

快照是服务器磁盘的完整副本,出问题可以回滚,比备份配置文件更保险。

2.3 准备紧急救援方式

确保你还有除了 SSH 以外的登录方式:

  • 云控制台 VNC/远程登录(应急入口)

  • 物理服务器使用 IPMI/iLO/iDRAC

  • 提前准备一个可以通过云控制台执行的脚本

2.4 测试窗口

安全加固最好在维护窗口进行,确保:

  • 业务低峰期,不会影响太多用户

  • 有足够时间排查加固后的异常

  • 有人值守,出问题能及时响应

  • 已经通知相关方(业务方、Leader)

3. 账户与密码安全

3.1 检查是否有弱密码账户

复制代码
# 列出所有系统账户(非登录、非服务账号除外)
awk -F: '{print $1, $3, $7}' /etc/passwd | grep -vE "(nologin|false|sync)" | head -50

# 检查是否有空密码账户
awk -F: '($2=="") {print $1}' /etc/shadow

# 检查密码策略
cat /etc/login.defs | grep -E "(PASS_MIN_LEN|PASS_MAX_DAYS|PASS_MIN_DAYS|PASS_WARN_AGE)"

# 查看当前密码策略(CentOS/RHEL)
authconfig --test | grep password
# 或
pam_cracklib --test

3.2 设置密码策略

修改 /etc/login.defs(对新用户生效):

复制代码
# /etc/login.defs
PASS_MAX_DAYS   90        # 密码最长使用 90 天
PASS_MIN_DAYS   7         # 密码最少使用 7 天才能修改
PASS_MIN_LEN    12        # 密码最小长度 12 位(注意:实际由 PAM 模块控制)
PASS_WARN_AGE   14        # 密码到期前 14 天警告

修改 PAM 模块密码策略(对现有用户也生效,CentOS/RHEL):

复制代码
# /etc/security/pwquality.conf 或 /etc/pam.d/password-auth
# 找到 password requisite pam_pwquality.so 行,改为:
password requisite pam_pwquality.so try_first_pass local_users_only retry=3 \
    minlen=12 dcredit=-1 ucredit=-1 lcredit=-1 ocredit=-1 \
    enforce_for_root

# 含义:
# minlen=12          最小长度 12 位
# dcredit=-1        至少包含 1 个数字(dcredit 负数表示"至少")
# ucredit=-1        至少包含 1 个大写字母
# lcredit=-1        至少包含 1 个小写字母
# ocredit=-1        至少包含 1 个特殊字符
# enforce_for_root  root 用户也强制执行

Ubuntu/Debian 中编辑 /etc/security/pwquality.conf/etc/pam.d/common-password

复制代码
password requisite pam_pwquality.so retry=3 minlen=12 ucredit=-1 lcredit=-1 dcredit=-1 ocredit=-1

3.3 锁定不应登录的系统账户

很多服务会创建系统账户,这些账户不应该用于登录:

复制代码
# 锁定不需要登录的账户
for user in bin daemon news uucp games gnats smmsp nobody nfsnobody; do
    usermod -L $user 2>/dev/null && echo "Locked $user" || echo "$user not found or already locked"
done

# 检查是否还有账户是 /bin/bash 登录
awk -F: '{print $1, $7}' /etc/passwd | grep -E "bash$" | grep -v -E "^(root|admin|deploy|app):"

# 确保 root 账户不能通过 SSH 登录
# 这个在 SSH 加固部分会详细说

3.4 限制 su 命令使用

只允许特定用户使用 su 切换到 root:

复制代码
# 在 /etc/pam.d/su 中添加(默认已有注释,取消注释即可)
# auth required pam_wheel.so use_uid

# 将信任的用户加入 wheel 组
usermod -aG wheel admin_user

# 验证 wheel 组配置
grep "^wheel" /etc/group

# 测试:非 wheel 组用户不能 su -
su - admin_user  # 先切换到普通用户
su - root        # 应该报错:Permission denied

3.5 踢出已登录的异常用户

复制代码
# 查看当前登录用户
who
w
last

# 踢出异常登录(假设发现 hack user)
pkill -KILL -u hack_user

# 立即禁用该账户
usermod -L hack_user
usermod -s /sbin/nologin hack_user

4. SSH 安全加固

SSH 是服务器被入侵的最主要入口。大量攻击者用弱口令字典批量扫 SSH。SSH 加固是安全加固中最重要的一环。

4.1 修改 SSH 默认端口

SSH 默认监听 22 端口,全世界扫描器都在扫 22。改成高位端口能减少 99% 的扫描流量:

复制代码
# 编辑 /etc/ssh/sshd_config
Port 22022  # 不要用 2222,有些扫描器也会扫

# 修改后重启 SSH
systemctl restart sshd

# 注意:修改端口后,后续 SSH 连接需要指定端口
ssh -p 22022 root@server_ip

# 防火墙放行新端口(稍后防火墙部分会讲)

风险提醒:

  • 改完端口后确保当前 SSH 会话不断(新端口生效后再退出)。

  • 修改端口后监控工具(如 ansible)需要同步更新。

  • 高位端口(如 22022)可能与企业内网策略冲突,注意评估。

4.2 禁用 root 直接登录

root 是最高权限账户,禁用直接登录,强制使用普通用户 + sudo:

复制代码
# /etc/ssh/sshd_config
PermitRootLogin no

# 确保有可用的 sudo 用户
useradd -m -s /bin/bash admin_user
usermod -aG wheel admin_user
echo "admin_user:Str0ngP@ssw0rd" | chpasswd

# 测试新用户可以 sudo
ssh admin_user@server_ip
sudo -l  # 应该显示 admin_user can run commands

4.3 使用密钥登录,禁止密码登录

密钥登录从根本上杜绝了暴力破解。密码登录即使再复杂,也是可被破解的:

复制代码
# 在本地机器(你的笔记本/台式机)生成密钥对
ssh-keygen -t ed25519 -C "your_email@example.com" -f ~/.ssh/id_ed25519_server

# 将公钥上传到服务器
ssh-copy-id -i ~/.ssh/id_ed25519_server.pub -p 22022 admin_user@server_ip

# 或者手动追加
# cat ~/.ssh/id_ed25519_server.pub | ssh -p 22022 admin_user@server_ip "mkdir -p ~/.ssh && chmod 700 ~/.ssh && cat >> ~/.ssh/authorized_keys && chmod 600 ~/.ssh/authorized_keys"

# 修改 SSH 配置
# /etc/ssh/sshd_config
PubkeyAuthentication yes
PasswordAuthentication no
PermitEmptyPasswords no
ChallengeResponseAuthentication no

# 重启 SSH
systemctl restart sshd

4.4 限制可登录用户和 IP

复制代码
# /etc/ssh/sshd_config
AllowUsers admin_user deploy_user@10.0.0.0/8 admin_user@192.168.1.0/24

# 只允许特定组
AllowGroups wheel admin

# 限制 sshd 监听地址(只监听内网 IP,不监听公网)
ListenAddress 0.0.0.0  # 默认,建议改为内网地址
# ListenAddress 10.0.0.100

4.5 其他 SSH 安全参数

复制代码
# /etc/ssh/sshd_config 添加以下内容
# 禁用空密码
PermitEmptyPasswords no

# 禁用 .rhosts 文件
IgnoreRhosts yes

# 禁用基于主机的认证
HostbasedAuthentication no

# 关闭 X11 转发(除非真的需要)
X11Forwarding no

# 关闭 TCP 转发(防止 SSH 被用作代理)
AllowTcpForwarding no

# 关闭 Agent 转发
AllowAgentForwarding no

# 设置空闲超时(客户端 10 分钟无操作自动断开)
ClientAliveInterval 600
ClientAliveCountMax 2

# 限制最大认证尝试次数
MaxAuthTries 3

# 设置登录成功后的 Banner(可选,起到威慑作用)
PrintMotd yes
PrintLastLog yes

# SSH 协议版本(必须为 2)
Protocol 2

4.6 使用 fail2ban 防止暴力破解

即使做了以上加固,攻击者仍可能尝试密钥破解或内部账户弱口令。fail2ban 能自动封禁频繁尝试登录的 IP:

复制代码
# CentOS/RHEL 安装
yum install -y epel-release
yum install -y fail2ban

# Ubuntu/Debian 安装
apt install -y fail2ban

# 配置 fail2ban(不修改 /etc/fail2ban/jail.conf,创建 local 覆盖文件)
cat > /etc/fail2ban/jail.local << 'EOF'
[DEFAULT]
bantime = 3600           # 封禁 1 小时
findtime = 600           # 10 分钟内
maxretry = 3             # 失败 3 次即封禁
ignoreip = 127.0.0.1/8 10.0.0.0/8 192.168.0.0/16  # 不封禁这些 IP

[sshd]
enabled = true
port = 22022
filter = sshd
logpath = /var/log/secure  # CentOS/RHEL
# logpath = /var/log/auth.log  # Ubuntu/Debian
maxretry = 3

[sshd-ddos]
enabled = true
port = 22022
filter = sshd-ddos
logpath = /var/log/secure
maxretry = 10
EOF

# 启动并设置开机自启
systemctl enable fail2ban
systemctl start fail2ban

# 查看被封禁的 IP
fail2ban-client status sshd
fail2ban-client banned sshd

# 手动解封某个 IP
fail2ban-client set sshd unbanip 192.168.1.100

4.7 验证 SSH 加固效果

复制代码
# 检查当前 SSH 配置是否正确
sshd -t

# 查看 SSH 监听端口
ss -tulnp | grep sshd

# 查看谁曾经登录过(用于审计)
last
lastlog | head -50

# 查看 SSH 失败登录记录
# CentOS/RHEL
cat /var/log/secure | grep -i "failed password" | tail -50
# Ubuntu/Debian
cat /var/log/auth.log | grep -i "failed password" | tail -50

# 查看 fail2ban 日志
tail -100 /var/log/fail2ban.log

5. 文件系统权限

5.1 设置 /tmp、/var/tmp 权限

攻击者经常利用 /tmp 和 /var/tmp 写入后门文件。应该将这些目录设置为 noexec、nosuid、nodev:

复制代码
# 查看当前 /tmp 挂载选项
mount | grep /tmp

# 如果 /tmp 是独立分区,添加安全挂载选项
# 编辑 /etc/fstab
UUID=xxxx-xxxx-xxxx /tmp ext4 defaults,noexec,nosuid,nodev 0 0

# 如果 /tmp 不是独立分区(大多数云服务器默认),创建一个独立的 /tmp 分区
# 先创建 2G 大小的镜像文件
dd if=/dev/zero of=/var/tmp.mount bs=1M count=2048
mkfs.ext4 /var/tmp.mount

# 备份原 /tmp 内容
cp -a /tmp /tmp.bak

# 挂载新分区
mount --bind /var/tmp.mount /tmp

# 恢复内容
cp -a /tmp.bak/* /tmp/

# 设置权限
chmod 1777 /tmp

# 添加到 /etc/fstab 确保重启后生效
echo"/var/tmp.mount /tmp ext4 defaults,bind,noexec,nosuid,nodev 0 0" >> /etc/fstab

5.2 限制系统内核模块加载

防止攻击者加载恶意内核模块:

复制代码
# 禁用模块加载能力
echo"install usb-storage /bin/true" >> /etc/modprobe.d/no-usb.conf
echo"install bluetooth /bin/true" >> /etc/modprobe.d/no-usb.conf
echo"install freevxfs /bin/true" >> /etc/modprobe.d/no-usb.conf
echo"install jffs2 /bin/true" >> /etc/modprobe.d/no-usb.conf
echo"install hfs /bin/true" >> /etc/modprobe.d/no-usb.conf
echo"install hfsplus /bin/true" >> /etc/modprobe.d/no-usb.conf
echo"install squashfs /bin/true" >> /etc/modprobe.d/no-usb.conf
echo"install udf /bin/true" >> /etc/modprobe.d/no-usb.conf
echo"install dccp /bin/true" >> /etc/modprobe.d/no-usb.conf

5.3 设置 umask 默认值

收紧用户的默认文件创建权限:

复制代码
# /etc/profile 中设置更严格的 umask
# 找到 umask 那行,改为:
umask 0027  # 默认创建文件 640,目录 750

# /etc/csh.cshrc 中也修改:
set umask 0027

5.4 关键文件权限检查

复制代码
# 检查关键文件权限
chmod 644 /etc/passwd
chmod 000 /etc/shadow      # shadow 文件只有 root 可读写
chmod 644 /etc/group
chmod 640 /etc/gshadow
chmod 600 /etc/crontab
chmod 600 /etc/anacrontab
chmod 700 /var/spool/cron
chmod 600 /etc/ssh/sshd_config
chmod 644 /etc/hosts.allow
chmod 644 /etc/hosts.deny
chmod 600 /etc/rsyslog.conf
chmod 700 /etc/cron.d
chmod 700 /etc/cron.daily
chmod 700 /etc/cron.hourly
chmod 700 /etc/cron.monthly
chmod 700 /etc/cron.weekly

6. 网络层加固

6.1 防火墙基础配置

使用 iptables 或 firewalld 限制入站流量。原则:默认拒绝所有,只放行必要的端口。

使用 firewalld(CentOS/RHEL 7+):

复制代码
# 查看当前规则
firewall-cmd --list-all
firewall-cmd --list-ports
firewall-cmd --list-services

# 放行必要端口
firewall-cmd --permanent --add-port=22022/tcp    # SSH
firewall-cmd --permanent --add-port=80/tcp        # HTTP
firewall-cmd --permanent --add-port=443/tcp       # HTTPS
firewall-cmd --permanent --add-port=3306/tcp      # MySQL(如果需要从内网直接访问)
firewall-cmd --permanent --add-port=6379/tcp      # Redis(仅内网)

# 放行必要服务
firewall-cmd --permanent --add-service=http
firewall-cmd --permanent --add-service=https
firewall-cmd --permanent --add-service=ssh

# 禁止 Ping(防扫描)
firewall-cmd --permanent --add-icmp-block=echo-request

# 默认拒绝所有入站
firewall-cmd --set-default-zone=drop

# 只允许特定来源 IP 访问 SSH
firewall-cmd --permanent --zone=trusted --add-source=10.0.0.0/8
firewall-cmd --permanent --zone=trusted --add-source=192.168.0.0/16
firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="your_office_ip/32" port port="22022" protocol="tcp" accept'

# 重载防火墙
firewall-cmd --reload

# 查看生效规则
firewall-cmd --list-all

使用 iptables(Ubuntu/Debian 或 CentOS/RHEL 6):

复制代码
# 保存现有规则
iptables-save > /opt/iptables-backup-$(date +%Y%m%d).rules

# 编写规则脚本
cat > /opt/iptables-rules.sh << 'EOF'
#!/bin/bash
# 清空现有规则
iptables -F
iptables -X
iptables -t nat -F
iptables -t nat -X

# 默认拒绝所有入站
iptables -P INPUT DROP
iptables -P FORWARD DROP
iptables -P OUTPUT ACCEPT

# 允许本地回环
iptables -A INPUT -i lo -j ACCEPT
iptables -A OUTPUT -o lo -j ACCEPT

# 允许已建立连接的包
iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT

# 允许 SSH(改成你的端口)
iptables -A INPUT -p tcp --dport 22022 -j ACCEPT

# 允许 HTTP/HTTPS
iptables -A INPUT -p tcp --dport 80 -j ACCEPT
iptables -A INPUT -p tcp --dport 443 -j ACCEPT

# 允许 Ping
iptables -A INPUT -p icmp --icmp-type echo-request -j ACCEPT

# 允许来自内网的连接
iptables -A INPUT -s 10.0.0.0/8 -j ACCEPT
iptables -A INPUT -s 192.168.0.0/16 -j ACCEPT

# 记录被拒绝的包(可选,方便排查)
iptables -A INPUT -m limit --limit 5/min -j LOG --log-prefix "iptables DROP: " --log-level 4

# 保存规则
iptables-save > /etc/iptables/rules.v4
EOF

chmod +x /opt/iptables-rules.sh
/opt/iptables-rules.sh

# 查看规则
iptables -L -n -v

6.2 内核网络参数加固

修改 /etc/sysctl.conf,收紧网络层面的安全参数:

复制代码
# /etc/sysctl.conf 添加或修改以下内容

# 关闭 IP 转发(除非服务器做路由器)
net.ipv4.ip_forward = 0

# 关闭数据包转发(防止服务器成为路由跳板)
net.ipv4.conf.all.forwarding = 0
net.ipv4.conf.default.forwarding = 0

# 禁用源路由包(防止 IP 伪装攻击)
net.ipv4.conf.all.accept_source_route = 0
net.ipv4.conf.default.accept_source_route = 0

# 关闭 ICMP 重定向
net.ipv4.conf.all.accept_redirects = 0
net.ipv4.conf.default.accept_redirects = 0
net.ipv6.conf.all.accept_redirects = 0
net.ipv6.conf.default.accept_redirects = 0

# 开启 SYN Flood 防护
net.ipv4.tcp_syncookies = 1
net.ipv4.tcp_syn_retries = 2
net.ipv4.tcp_synack_retries = 2
net.ipv4.tcp_max_syn_backlog = 4096

# 禁止 ICMP Ping 广播
net.ipv4.icmp_echo_ignore_broadcasts = 1

# 忽略 ICMP Ping(可选,影响监控探活)
net.ipv4.icmp_echo_ignore_all = 0  # 建议保持 0,方便自己监控

# 禁止路由记录( traceroute 使用)
net.ipv4.conf.all.log_martians = 1
net.ipv4.conf.default.log_martians = 1

# TIME_WAIT 快速回收
net.ipv4.tcp_fin_timeout = 30
net.ipv4.tcp_tw_reuse = 1

# 最大文件描述符
fs.file-max = 6553600

# 应用配置
sysctl -p

6.3 限制核心文件访问

复制代码
# 禁止通过 ICMP 路由追踪(防止攻击者探测网络拓扑)
echo 1 > /proc/sys/net/ipv4/conf/all/accept_source_route
# 上面已经在 sysctl.conf 中设置

# 禁止修改路由表
echo 0 > /proc/sys/net/ipv4/conf/all/accept_redirects
echo 0 > /proc/sys/net/ipv6/conf/all/accept_redirects

7. 服务安全

7.1 禁用不必要的服务

服务器上不需要的服务越多,攻击面越大。检查并禁用不需要的服务:

复制代码
# 查看所有开机自启服务
systemctl list-unit-files --type=service --state=enabled

# 查看正在运行的服务
systemctl --type=service --state=running

# 常见需要检查和禁用的服务(按需调整)
# telnet-server:明文传输,应禁用
systemctl disable telnet.socket 2>/dev/null
systemctl stop telnet.socket 2>/dev/null

# vsftpd:如果不用 FTP 就禁用
systemctl disable vsftpd 2>/dev/null

# sendmail:邮件服务,如不需要就禁用
systemctl disable sendmail 2>/dev/null

# postfix:如果不用邮件就禁用
systemctl disable postfix 2>/dev/null

# cups:打印服务,云服务器不需要
systemctl disable cups 2>/dev/null

# dovecot:如果不用 IMAP/POP3 就禁用
systemctl disable dovecot 2>/dev/null

# nfslock/nfs:如果不做 NFS 文件共享就禁用
systemctl disable nfs-lock 2>/dev/null
systemctl disable nfs 2>/dev/null

# rpcbind:NFS 依赖的服务
systemctl disable rpcbind 2>/dev/null

# bluetooth:云服务器不需要蓝牙
systemctl disable bluetooth 2>/dev/null
systemctl stop bluetooth 2>/dev/null

# 确认没有不需要的服务在运行
systemctl --type=service --state=running | grep -v -E "(sshd|cron|rsyslog|systemd|dbus|network|polkit|irqbalance|sssd)"

7.2 查看监听端口

确保服务器上只有你知道的端口在监听:

复制代码
# 查看所有监听端口
ss -tulnp
# 或
netstat -tulnp

# 特别关注以下几点:
# 1. 是否有不明服务监听在高危端口(如 4444、5555 是 Metasploit 常用端口)
# 2. 是否有服务监听在 0.0.0.0(应该大部分服务只监听 127.0.0.1 或内网 IP)
# 3. 是否有服务监听在公网 IP 但不应该暴露(如数据库、Redis)

# 示例:检查非预期的监听
ss -tulnp | grep -v -E "(22|80|443|22022)"

7.3 隐藏服务版本信息

很多服务会在 banner 中显示版本号,攻击者利用版本信息查找对应漏洞:

复制代码
# Nginx 版本隐藏(在 nginx.conf 中)
server_tokens off;

# MySQL 版本隐藏
# MySQL 5.7+: 在 my.cnf [mysqld] 中
# MySQL 8.0+: 不需要单独配置,默认不显示版本

# SSH 版本(在 /etc/ssh/sshd_config 中)
# SSH 默认 banner 无法完全隐藏,但可以降级攻击者信心
# 编辑 /etc/ssh/sshd_config
# 找到 #Banner none,改为:
# Banner /etc/ssh/banner
# 创建自定义 banner 文件
echo"Welcome to Secure Server" > /etc/ssh/banner

# Redis 默认监听 6379,且无认证
# 如果必须暴露在外网,必须设置密码
# /etc/redis/redis.conf
# requirepass your_strong_password_here
# bind 127.0.0.1
# rename-command FLUSHDB ""   # 禁用 FLUSHDB 命令
# rename-command FLUSHALL ""   # 禁用 FLUSHALL 命令
# rename-command KEYS ""       # 禁止 KEYS 命令(或用 SCAN 替代)

8. SELinux/AppArmor 加固

8.1 CentOS/RHEL:启用 SELinux

SELinux 是内核级的访问控制系统,能限制被入侵后的横向移动:

复制代码
# 检查 SELinux 状态
getenforce
sestatus

# 如果是 Permissive,改为 Enforcing
# 编辑 /etc/selinux/config
SELINUX=enforcing
SELINUXTYPE=targeted

# 临时生效
setenforce 1

# SELinux 常用管理命令
# 查看文件安全上下文
ls -Z /var/www/html
ps auxZ | grep nginx

# 修改目录安全上下文(Web 目录迁移后常用)
semanage fcontext -a -t httpd_sys_content_t "/var/www(/.*)?"
restorecon -Rv /var/www

# 允许服务使用非标准端口
semanage port -a -t http_port_t -p tcp 8080

风险提醒:

  • 开启 SELinux 前要确保熟悉常见应用的配置,否则会导致服务启动失败。

  • 如果业务应用在 Permissive 模式下运行正常再切换到 Enforcing。

  • 遇到权限问题时,优先用 ausearchsealert 查看 SELinux 拒绝日志,而不是直接降级到 Permissive。

8.2 Ubuntu/Debian:配置 AppArmor

复制代码
# 检查 AppArmor 状态
aa-status

# 查看所有配置文件的加载状态
apparmor_status

# AppArmor 配置文件在 /etc/apparmor.d/
# 禁用不必要配置的激进模式(如果确认某服务不需要网络访问)
# 编辑 /etc/apparmor.d/usr.sbin.httpd 或对应的 Nginx 配置文件
# 限制网络访问:
# network inet tcp,
# deny network inet6 tcp,

9. 日志审计

9.1 配置日志集中收集

服务器被黑后,攻击者第一件事往往是清理日志。日志必须集中到远程服务器:

复制代码
# rsyslog 客户端配置,将日志发送到远程日志服务器
# /etc/rsyslog.conf 添加:
*.* @@log-server.example.com:514

# 或使用 UDP(性能好但可能丢包):
*.* @log-server.example.com:514

# CentOS/RHEL 重启 rsyslog
systemctl restart rsyslog

# Ubuntu/Debian
systemctl restart rsyslog

9.2 配置审计日志

Linux 审计守护进程(auditd)记录系统调用,是取证的重要依据:

复制代码
# 安装 auditd
yum install -y audit  # CentOS/RHEL
apt install -y auditd  # Ubuntu/Debian

# 启动并设置开机自启
systemctl enable auditd
systemctl start auditd

# 配置审计规则
# /etc/audit/rules.d/audit.rules 或 /etc/audit/audit.rules
# 记录所有修改 /etc/passwd、/etc/shadow、/etc/group 的操作
-w /etc/passwd -p wa -k identity_changes
-w /etc/shadow -p wa -k identity_changes
-w /etc/group -p wa -k identity_changes
-w /etc/gshadow -p wa -k identity_changes

# 记录所有 sudo 命令
-w /usr/bin/sudo -p x -k privileged_commands

# 记录 SSH 登录事件
-w /etc/ssh/sshd_config -p wa -k ssh_config_changes
-a always,exit -F arch=b64 -S sshd -F auid>=1000 -F auid!=4294967295 -k sshd_login

# 记录网络配置变更
-w /etc/sysconfig/network -p wa -k network_changes
-w /etc/sysconfig/network-scripts/ -p wa -k network_changes

# 记录敏感文件的执行
-a always,exit -F arch=b64 -S execve -F path=/usr/bin/wget -k network_download
-a always,exit -F arch=b64 -S execve -F path=/usr/bin/curl -k network_download
-a always,exit -F arch=b64 -S execve -F path=/usr/bin/python* -k interpreter_usage
-a always,exit -F arch=b64 -S execve -F path=/usr/bin/perl -k interpreter_usage

# 使规则生效
augenrules --load

# 查看审计日志
ausearch -k identity_changes | head -20
ausearch -k sshd_login | head -20

# 查看最近的审计事件
aureport --latest-events
aureport --auth | head -30

9.3 日志文件完整性校验

攻击者可能修改日志掩盖入侵痕迹。使用 AIDE 或 Tripwire 做文件完整性检查:

复制代码
# 安装 AIDE
yum install -y aide  # CentOS/RHEL
apt install -y aide   # Ubuntu/Debian

# 初始化 AIDE 数据库(第一次运行)
aide --init

# 移动初始数据库
mv /var/lib/aide/aide.db.new.gz /var/lib/aide/aide.db.gz

# 定期检查(手动)
aide --check

# 更新数据库(在确认系统正常后)
aide --update
mv /var/lib/aide/aide.db.new.gz /var/lib/aide/aide.db.gz

# 每天自动检查(加入 crontab)
echo"0 3 * * * /usr/sbin/aide --check" >> /etc/crontab

10. Rootkit 和后门检测

10.1 使用 rkhunter 检查 Rootkit

复制代码
# 安装 rkhunter
yum install -y rkhunter  # CentOS/RHEL
apt install -y rkhunter  # Ubuntu/Debian

# 更新特征库
rkhunter --update

# 执行检查
rkhunter --check --sk --rwo

# 关键检查项:
# - 检查文件系统中的隐藏文件
# - 检查常见的 Rootkit 特征
# - 检查可疑的 LKM(Loadable Kernel Module)
# - 检查网络连接
# - 检查系统命令是否被替换

10.2 使用 chkrootkit 检查

复制代码
# 安装 chkrootkit
yum install -y chkrootkit  # CentOS/RHEL
apt install -y chkrootkit  # Ubuntu/Debian

# 运行检查
chkrootkit | grep -v -E "(Checking|not found|Nothing found|Not tested)"

# 查看网络相关
chkrootkit -r

# 注意:有些安全软件会误报
# 如有误报,查看具体命令是否被替换
which ls
rpm -qf /bin/ls
md5sum /bin/ls

10.3 检查异常进程和网络连接

复制代码
# 查看所有进程(包括隐藏进程)
ps auxf
ps -ef

# 查看网络连接和对应进程
ss -tulnp
netstat -antp

# 检查是否有进程监听异常端口
ss -tulnp | grep -v -E "(22|80|443|22022)"

# 检查是否有到外网的异常连接(被控服务器会向外发送数据)
ss -tnp | grep -v -E "(10\.|192\.168\.|172\.(1[6-9]|2[0-9]|3[01])\.)"

# 检查是否有进程在运行但 ps 看不到(高级 Rootkit 特征)
# 如果 ps 和 /proc 里看到进程但 ss/netstat 看不到监听端口,说明可能是后门
for pid in $(ls /proc | grep '^[0-9]'); do
    if [ -f /proc/$pid/cmdline ]; then
        echo"PID $pid: $(cat /proc/$pid/cmdline | tr '\0' ' ')"
    fi
done | head -50

# 检查 crontab 是否有可疑任务
crontab -l
cat /etc/crontab
ls -la /etc/cron.d/
ls -la /var/spool/cron/
cat /etc/cron.d/* 2>/dev/null

10.4 检查 SSH authorized_keys 是否被篡改

复制代码
# 查看所有用户的 SSH authorized_keys(可能被添加了攻击者的公钥)
for user in $(cut -d: -f1 /etc/passwd); do
    keyfile="/home/$user/.ssh/authorized_keys"
    if [ -f "$keyfile" ]; then
        echo"=== $user authorized_keys ==="
        cat "$keyfile"
    fi
done

# 检查 root 的 authorized_keys(root 直接登录已被禁用,但 keys 本身也可能被篡改)
if [ -f /root/.ssh/authorized_keys ]; then
    echo"=== root authorized_keys ==="
    cat /root/.ssh/authorized_keys
fi

# 检查 SSH 登录记录(看是否有异常登录时间/IP)
last | head -30
lastlog | grep -v "Never"

11. 内核参数加固

11.1 限制进程资源使用

防止单个进程耗尽系统资源导致 DoS:

复制代码
# /etc/security/limits.conf 添加:
# 限制最大进程数
*               soft    nproc           4096
*               hard    nproc           8192

# 限制最大文件描述符
*               soft    nofile          65536
*               hard    nofile          65536

# 限制 core dump 大小(防止泄露敏感内存数据)
*               soft    core            0
*               hard    core            0

# 限制普通用户可以使用的内存
# 这个需要根据实际内存调整
# @student       hard    memlock        2097152

11.2 禁止 ICMP 重定向

复制代码
# 在 /etc/sysctl.conf 中已经配置
# 再次确认
grep -E "icmp_(echo_ignore_all|accept_redirects)" /etc/sysctl.conf

# 立即生效
sysctl -p

11.3 禁用不必要的文件系统

减少内核支持的攻击面:

复制代码
# /etc/modprobe.d/disable-filesystems.conf
install cramfs /bin/true
install freevxfs /bin/true
install jffs2 /bin/true
install hfs /bin/true
install hfsplus /bin/true
install squashfs /bin/true
install udf /bin/true
install vfat /bin/true

12. 软件更新与漏洞管理

12.1 配置自动安全更新

复制代码
# CentOS/RHEL:使用 yum-cron
yum install -y yum-cron

# 编辑 /etc/yum/yum-cron.conf
update_cmd = security
update_messages = yes
download_updates = yes
apply_updates = yes

systemctl enable yum-cron
systemctl start yum-cron

# Ubuntu/Debian:使用 unattended-upgrades
apt install -y unattended-upgrades
dpkg-reconfigure -plow unattended-upgrades
# 选择 "Yes" 启用自动安全更新

# 查看自动更新日志
tail -50 /var/log/yum.log  # CentOS
tail -50 /var/log/unattended-upgrades/  # Ubuntu

12.2 定期漏洞扫描

复制代码
# 安装 OpenVAS 或使用 yum/cve-check(CentOS)
yum install -y yum-plugin-security
yum updateinfo list security

# Ubuntu
apt install -y unattended-upgrades
/usr/lib/update-notifier/update-notifier.notify-matches-available-security-updates

# 如果有商业漏洞扫描器(Qualys、Rapid7),定期扫描生产服务器
# 扫描前通知相关方,选择维护窗口

12.3 内核升级

内核漏洞危害极大,但升级内核有风险(可能影响驱动、业务依赖):

复制代码
# CentOS/RHEL 查看可用内核
grub2-mkconfig -o /boot/grub2/grub.cfg
awk -F\' '/menuentry/ {print $2}' /boot/grub2/grub.cfg

# 安装最新版内核
yum update -y kernel

# 重启后选择新内核
reboot

# 确认使用的是新内核
uname -r

# 设置默认启动项(防止误回滚)
grub2-set-default "CentOS Linux (6.14.1-1.el8.x86_64) 8 (Core)"
grub2-mkconfig -o /boot/grub2/grub.cfg

风险提醒:

  • 内核升级必须通过测试环境验证。

  • 云服务器升级内核前确保有云控制台救援方式。

  • 升级前记录当前内核版本和启动项,保留回滚能力。

13. 监控与告警

13.1 账户变更监控

复制代码
# 监控 /etc/passwd、/etc/shadow、/etc/group 的变更
# 使用 auditd(前面已配置)记录变更
# 配合以下脚本每日比对

cat > /opt/check-accounts.sh << 'EOF'
#!/bin/bash
# 对比当日和昨日的账户数据

YESTERDAY=$(date -d "yesterday" +%Y%m%d)
TODAY=$(date +%Y%m%d)
BACKUP_DIR="/opt/security-hardening-backup"

if [ ! -f "$BACKUP_DIR/passwd.bak" ]; then
    echo"No baseline found"
    exit 1
fi

echo"=== Checking for new users ==="
diff <(sort /opt/security-hardening-backup/passwd.bak | cut -d: -f1) \
     <(sort /etc/passwd | cut -d: -f1) | grep "^>"

echo"=== Checking for removed users ==="
diff <(sort /opt/security-hardening-backup/passwd.bak | cut -d: -f1) \
     <(sort /etc/passwd | cut -d: -f1) | grep "^<"

echo"=== Checking for users with changed shells ==="
diff <(sort /opt/security-hardening-backup/passwd.bak | awk -F: '{print $1":"$7}') \
     <(sort /etc/passwd | awk -F: '{print $1":"$7}') | grep "^>"

echo"=== Checking for UID 0 users ==="
awk -F: '($3==0) {print $1}' /etc/passwd
EOF

chmod +x /opt/check-accounts.sh

# 加入 crontab 每日检查
echo"0 6 * * * root /opt/check-accounts.sh" >> /etc/crontab

13.2 新增网络连接监控

复制代码
# 监控是否有新增监听端口(可能后门监听)
cat > /opt/check-ports.sh << 'EOF'
#!/bin/bash
YESTERDAY_PORTS="/var/tmp/listening-ports-backup.txt"
TODAY_PORTS="/var/tmp/listening-ports-$(date +%Y%m%d).txt"

ss -tulnp > "$TODAY_PORTS"

if [ -f "$YESTERDAY_PORTS" ]; then
    echo"=== NEW listening ports ==="
    diff "$YESTERDAY_PORTS""$TODAY_PORTS" | grep "^>" || echo"None"
    echo"=== REMOVED listening ports ==="
    diff "$YESTERDAY_PORTS""$TODAY_PORTS" | grep "^<" || echo"None"
fi

cp "$TODAY_PORTS""$YESTERDAY_PORTS"
EOF

chmod +x /opt/check-ports.sh

13.3 Prometheus + Alertmanager 告警体系

复制代码
# node_exporter 采集系统指标
# 安装 node_exporter
wget https://github.com/prometheus/node_exporter/releases/download/v1.7.0/node_exporter-1.7.0.linux-amd64.tar.gz
tar xvf node_exporter-1.7.0.linux-amd64.tar.gz
mv node_exporter-1.7.0.linux-amd64/node_exporter /usr/local/bin/

# 创建 systemd 服务(启用 textfile collector 用于自定义指标)
cat > /etc/systemd/system/node_exporter.service << 'EOF'
[Unit]
Description=Node Exporter
After=network.target

[Service]
ExecStart=/usr/local/bin/node_exporter --collector.textfile.directory=/var/lib/node_exporter/textfile_collector
Restart=on-failure

[Install]
WantedBy=multi-user.target
EOF

systemctl daemon-reload
systemctl enable node_exporter
systemctl start node_exporter

# 创建自定义指标采集脚本,统计监听端口数量
# 通过 ss -tuln 输出统计当前监听 TCP/UDP 端口数,用于检测被控后新增监听端口
mkdir -p /var/lib/node_exporter/textfile_collector
cat > /usr/local/bin/node_sock_listen.sh << 'SCRIPT'
#!/bin/bash
OUTFILE="/var/lib/node_exporter/textfile_collector/node_sock_listen.prom"

# 统计当前监听中的 TCP 端口数量(排除回环和监听状态为空的行)
TCP_LISTEN=$(ss -tuln | grep -c "LISTEN" || echo 0)

# 统计当前监听中的 UDP 端口数量
UDP_LISTEN=$(ss -uuln | grep -c "UNCONN" || echo 0)

# 输出 Prometheus textfile 格式
cat > "${OUTFILE}.tmp" << EOF
# HELP node_sock_listen_count Number of listening sockets by protocol
# TYPE node_sock_listen_count gauge
node_sock_listen_count{protocol="tcp"} ${TCP_LISTEN}
node_sock_listen_count{protocol="udp"} ${UDP_LISTEN}
EOF
mv "${OUTFILE}.tmp""${OUTFILE}"
SCRIPT

chmod +x /usr/local/bin/node_sock_listen.sh

# 加入 crontab,每分钟执行一次
echo"* * * * * root /usr/local/bin/node_sock_listen.sh" >> /etc/crontab

# 手动执行一次测试
/usr/local/bin/node_sock_listen.sh
cat /var/lib/node_exporter/textfile_collector/node_sock_listen.prom

# 关键告警规则(Prometheus rule file)
# /etc/prometheus/rules.yml
groups:
- name: security
  rules:
# SSH 登录失败过多(需要部署 prometheus/sshd_exporter 并在 sshd 配置中启用 SyslogFacility AUTHPRIV)
  - alert: SSHBruteForce
    expr: rate(sshd_failed_authentication_total[5m]) > 10
    for: 2m
    labels:
      severity: warning
    annotations:
      summary: "SSH brute force detected"
      description: "More than 10 failed SSH auth per 5min from {{ $labels.instance }}"

# 新增监听端口(被控特征)
# 通过 node_exporter 的 textfile collector 暴露 ss -tuln 统计的监听端口数
# 自定义采集脚本(见 13.3 节)生成 node_sock_listen_count 指标
  - alert: NewListeningPort
    expr: count by (instance) (node_sock_listen_count) > on(instance) count by (instance) (node_sock_listen_count offset 1h)
    for: 5m
    labels:
      severity: critical
    annotations:
      summary: "New listening port detected on {{ $labels.instance }}"

14. 安全加固后的验证

完成加固后,必须进行验证:

14.1 加固验证清单

复制代码
# SSH 配置验证
sshd -t
ssh -p 22022 -o PreferredAuthentications=password -o PubkeyAuthentication=no admin_user@127.0.0.1
# 应该报错:Permission denied (password refused 或直接拒绝连接)

# 密钥登录应该成功
ssh -p 22022 -i ~/.ssh/id_ed25519_server.pub admin_user@127.0.0.1

# root 登录应该失败
ssh -p 22022 root@127.0.0.1
# 应该报错:Permission denied

# 防火墙验证
# 从外部 IP 访问非白名单端口应该被拒绝
# 从白名单 IP 访问应该正常

# 文件权限验证
ls -la /etc/shadow  # 应该显示 ----------

# SELinux 验证(CentOS)
getenforce  # 应该显示 Enforcing

# fail2ban 验证
fail2ban-client status sshd
# 应该显示监狱状态和规则

# 服务禁用验证
systemctl status telnet.socket  # 应该显示 inactive
systemctl status bluetooth  # 应该显示 inactive

14.2 记录加固报告

每次加固完成,必须输出加固报告,包含:

  • 加固时间、人员

  • 修改前的配置备份路径

  • 每项加固的具体操作

  • 验证结果

  • 遗留风险和后续计划

    cat > /opt/security-hardening-report-$(date +%Y%m%d).txt << 'EOF'
    安全加固报告

    日期: (date +%Y-%m-%d) 操作人: admin_user 服务器: (hostname) / $(curl -s ifconfig.me || echo"N/A")

    一、加固项目

    1. SSH 安全
      • 端口: 22 -> 22022
      • 禁用 root 登录: yes
      • 密钥登录: yes
      • fail2ban: enabled
    2. 防火墙
      • firewalld: enabled
      • 默认策略: drop
      • 放行端口: 22022, 80, 443
    3. 账户安全
      • 密码策略: minlen=12, dcredit=-1, ...
      • wheel 组限制: enabled
      • 空密码账户: 0
    4. SELinux: Enforcing (CentOS)
    5. 内核参数: 已加固(sysctl.conf)
    6. 日志审计: auditd enabled, rsyslog forwarded

    二、验证结果

    • SSH 配置语法正确
    • root 无法登录
    • fail2ban 运行正常
    • firewall-cmd 规则生效
    • 关键文件权限正确
    • 从外部 IP 实际测试(待执行)

    三、遗留风险

    • 云平台控制台登录 MFA 未配置
    • 数据库 Redis 密码需要定期轮换

    四、下次加固计划

    • 添加 AIDE 文件完整性检查
    • 配置 OSSEC 主机入侵检测
      EOF

15. 总结

安全加固不是一次性工作,而是持续的过程。核心原则要记住:

最小权限原则: 不需要的端口就不开,不需要的服务就禁用,不需要的功能就关闭。每个开放都应该是明确有理由的。

纵深防御原则: 每一层防线失效后还有下一层。SSH 密钥登录失效还有 fail2ban 封禁,防火墙失效还有 SELinux 限制,后门植入还有 auditd 记录。

可审计原则: 一切操作皆有记录,所有变更可追溯。日志不仅要在,而且不能被篡改。定期检查审计日志比被攻击后才发现要好得多。

加固后要验证: 配置改了不代表生效,要实际测试。每做一项加固,马上验证是否生效、是否影响正常功能。

保持更新: 漏洞每天都在被发现,系统每天都在运行新的攻击。安全加固是持续工作,不是做完一次就能高枕无忧。

最后提醒:加固是为了提高攻击成本,而不是让服务器完全不被攻破。再完善的加固也无法保证 100% 安全,所以日志监控、入侵检测、应急响应能力同样重要。防守是体系,加固只是第一步。

相关推荐
Aphasia31114 小时前
VPN 与内网穿透
安全
Mr_愚人派2 天前
当"Claude"不再是 Claude:一次第三方 API 代理引发的 AI 身份伪造排查实录
人工智能·安全
大树882 天前
金刚石散热越强,管路越先见顶
大数据·运维·服务器·人工智能·ai
摇滚侠2 天前
Linux CentOS7 rpm 安装 MySQL 5.7
linux·运维·mysql
霸道流氓气质2 天前
领域驱动设计(DDD)在 Spring Boot 微服务中的实践指南
运维·spring boot·微服务
小宇宙Zz2 天前
Maven依赖冲突
java·服务器·maven
DaLi Yao2 天前
【无标题】
人工智能·安全
Inhand陈工2 天前
基于台达PLC与映翰通IG502的智慧水产养殖精准投喂与远程运维解决方案
运维·人工智能·物联网·阿里云·信息与通信
Alsn862 天前
等待学习-学习目录:Docker 容器安全攻防
学习·安全·docker
网络研究院2 天前
2026年网络安全
网络·安全·法律·法规·趋势·发展