惕服务器被攻击!完整安全加固清单汇总
服务器被黑不是小概率事件。只要服务器暴露在公网,每时每刻都在被扫描、被尝试弱口令、被探测漏洞。安全加固不是"用不用心"的问题,而是"有没有做"的问题。这篇文章给出一份完整的 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 锁定不应登录的系统账户
很多服务会创建系统账户,这些账户不应该用于登录:
# 锁定不需要登录的账户
foruserinbin daemon news uucp games gnats smmsp nobody nfsnobody;do
usermod -L$user2>/dev/null &&echo"Locked$user"||echo"$usernot 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 大小的镜像文件 ddif=/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 那行,改为: umask0027 # 默认创建文件 640,目录 750 # /etc/csh.cshrc 中也修改: setumask0027
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 路由追踪(防止攻击者探测网络拓扑) echo1 > /proc/sys/net/ipv4/conf/all/accept_source_route # 上面已经在 sysctl.conf 中设置 # 禁止修改路由表 echo0 > /proc/sys/net/ipv4/conf/all/accept_redirects echo0 > /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:明文传输,应禁用 systemctldisabletelnet.socket 2>/dev/null systemctl stop telnet.socket 2>/dev/null # vsftpd:如果不用 FTP 就禁用 systemctldisablevsftpd 2>/dev/null # sendmail:邮件服务,如不需要就禁用 systemctldisablesendmail 2>/dev/null # postfix:如果不用邮件就禁用 systemctldisablepostfix 2>/dev/null # cups:打印服务,云服务器不需要 systemctldisablecups 2>/dev/null # dovecot:如果不用 IMAP/POP3 就禁用 systemctldisabledovecot 2>/dev/null # nfslock/nfs:如果不做 NFS 文件共享就禁用 systemctldisablenfs-lock 2>/dev/null systemctldisablenfs 2>/dev/null # rpcbind:NFS 依赖的服务 systemctldisablerpcbind 2>/dev/null # bluetooth:云服务器不需要蓝牙 systemctldisablebluetooth 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 # 找到#Bannernone,改为: # 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。
遇到权限问题时,优先用ausearch、sealert查看 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 # 启动并设置开机自启 systemctlenableauditd 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 # 注意:有些安全软件会误报 # 如有误报,查看具体命令是否被替换 whichls 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 看不到监听端口,说明可能是后门 forpidin$(ls /proc | grep'^[0-9]');do if[ -f /proc/$pid/cmdline ];then echo"PID$pid:$(cat /proc/$pid/cmdline | tr '�' ' ')" 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(可能被添加了攻击者的公钥)
foruserin$(cut -d: -f1 /etc/passwd);do
keyfile="/home/$user/.ssh/authorized_keys"
if[ -f"$keyfile"];then
echo"===$userauthorized_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 systemctlenableyum-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 二、验证结果 --------- - [x] SSH 配置语法正确 - [x] root 无法登录 - [x] fail2ban 运行正常 - [x] firewall-cmd 规则生效 - [x] 关键文件权限正确 - [ ] 从外部 IP 实际测试(待执行) 三、遗留风险 --------- - [ ] 云平台控制台登录 MFA 未配置 - [ ] 数据库 Redis 密码需要定期轮换 四、下次加固计划 ------------- - 添加 AIDE 文件完整性检查 - 配置 OSSEC 主机入侵检测 EOF
15. 总结
安全加固不是一次性工作,而是持续的过程。核心原则要记住:
最小权限原则:不需要的端口就不开,不需要的服务就禁用,不需要的功能就关闭。每个开放都应该是明确有理由的。
纵深防御原则:每一层防线失效后还有下一层。SSH 密钥登录失效还有 fail2ban 封禁,防火墙失效还有 SELinux 限制,后门植入还有 auditd 记录。
可审计原则:一切操作皆有记录,所有变更可追溯。日志不仅要在,而且不能被篡改。定期检查审计日志比被攻击后才发现要好得多。
加固后要验证:配置改了不代表生效,要实际测试。每做一项加固,马上验证是否生效、是否影响正常功能。
保持更新:漏洞每天都在被发现,系统每天都在运行新的攻击。安全加固是持续工作,不是做完一次就能高枕无忧。
最后提醒:加固是为了提高攻击成本,而不是让服务器完全不被攻破。再完善的加固也无法保证 100% 安全,所以日志监控、入侵检测、应急响应能力同样重要。防守是体系,加固只是第一步。
-
服务器
+关注
关注
14文章
10459浏览量
91866 -
加固
+关注
关注
0文章
7浏览量
6243 -
SSH
+关注
关注
0文章
202浏览量
17868
原文标题:惕服务器被攻击!完整安全加固清单汇总
文章出处:【微信号:magedu-Linux,微信公众号:马哥Linux运维】欢迎添加关注!文章转载请注明出处。
发布评论请先 登录
linux服务器和windows服务器
为你的 Linux 服务器加把锁
租用服务器后如何进行服务器安全防护
linux系统如何登录到远程linux服务器
系统讲解Linux服务器安全加固清单
评论