1. 项目概述:为什么你的VPS需要一个“安全体检”
最近在折腾一台新的VPS,准备部署点个人项目。服务器刚到手,系统是最新的发行版,一切看起来都很干净。但作为一个老运维,我心里清楚,这种“干净”只是表象。默认配置里可能藏着不安全的服务,未更新的软件包可能存在已知漏洞,甚至防火墙规则都可能过于宽松。手动去检查每一项?那太费时了,而且容易遗漏。这时候,一个自动化、系统性的安全审计脚本就成了刚需。
这个“7分钟上手VPS安全审计脚本”项目,核心就是帮你快速给Linux服务器做一次全面的“安全体检”。它不是一个复杂的入侵检测系统,而是一个主动的、预防性的检查工具。通过运行一系列预定义的检查项,它能帮你快速发现系统配置中常见的安全隐患,比如不必要的开放端口、弱密码策略、存在漏洞的软件版本、可疑的用户和进程等等。对于刚拿到手的VPS、或者定期维护的服务器来说,花几分钟跑一遍这个脚本,就像给服务器做一次快速健康检查,能有效降低被“黑”的风险。
尤其对于个人开发者、初创团队或者运维新手,可能没有精力去部署企业级的安全方案,但这个脚本提供了一个轻量级、可立即上手的起点。它基于Bash编写,几乎兼容所有主流的Linux发行版(如Ubuntu, CentOS, Debian),无需安装复杂的依赖,下载即用。接下来,我会详细拆解这个脚本的设计思路、核心检查项、如何定制它以适应你的环境,以及在实际操作中我踩过的那些坑。
2. 脚本核心设计与检查逻辑拆解
一个有效的安全审计脚本,其价值不在于代码有多复杂,而在于检查项是否切中要害,以及逻辑是否清晰可扩展。我设计的这个脚本,其核心思想是“分层检查,结果聚合”,主要分为以下几个层面:
2.1 系统信息与基础配置审计
这是审计的起点,目的是了解你的“战场”。脚本会首先收集并展示系统的基本信息,如主机名、内核版本、发行版、运行时间等。这不仅能让你确认审计对象,某些信息本身也是安全线索。例如,一个运行了非常久却没有重启过的系统,可能意味着内核从未更新过,存在潜在风险。
更关键的是对基础安全配置的检查:
- 密码策略检查:通过检查
/etc/login.defs和etc/pam.d/common-password等文件,审计密码最小长度、过期时间、历史记录等策略是否符合安全规范。很多默认安装的系统,密码策略是极其宽松的。 - SSH配置审计:SSH是进入服务器的首要通道,也是攻击者的首要目标。脚本会检查
/etc/ssh/sshd_config,重点关注:PermitRootLogin:是否允许root直接登录。最佳实践是设置为no或prohibit-password。PasswordAuthentication:是否允许密码认证。在配置了SSH密钥后,建议关闭,能极大抵御暴力破解。Port:是否使用默认的22端口。修改为非常用端口能减少自动化扫描的滋扰。AllowUsers/DenyUsers:是否设置了访问白名单或黑名单。
2.2 网络与服务暴露面分析
服务器对外开放了什么,决定了攻击面有多大。这部分审计至关重要。
- 网络连接与监听端口:使用
netstat或更现代的ss命令,列出所有活跃的网络连接和监听端口。重点是找出那些监听在0.0.0.0(即所有接口)上的服务。你需要问自己:这个端口上的服务是必须对外提供的吗?如果不是,应该将其绑定到127.0.0.1或直接关闭。 - 防火墙规则检查:检查
iptables、firewalld或ufw的规则。确认是否有默认的DROP或REJECT策略,开放的必要端口是否精确,是否存在允许任意源IP访问的宽松规则。一个常见的错误是只设置了输出规则,却忘了设置严格的输入规则。 - 非必要服务排查:使用
systemctl或service命令,检查系统启动的服务。对于像telnet、rsh、vsftpd(如果不需要FTP)等古老或不安全的服务,以及像cups(打印服务)这种在服务器上通常用不到的服务,应考虑禁用并停止。
2.3 文件系统与权限安全扫描
攻击者提权或维持访问,往往依赖于不当的文件权限。
- SUID/SGID文件查找:查找设置了SUID(Set User ID)或SGID(Set Group ID)位的文件。这些文件在执行时,会以文件所有者或所属组的权限运行。如果像
find、vim、bash这样的常见命令被设置了SUID,将是严重的提权漏洞。脚本会找出这些文件,并由你判断其合理性。 - 世界可写文件检查:查找任何用户都可写(
o+w)的文件和目录,特别是在系统路径(如/usr/bin、/etc)或用户主目录下。这可能导致恶意软件植入或配置被篡改。 - 关键配置文件权限:检查
/etc/passwd、/etc/shadow、/etc/sudoers等关键文件的权限。/etc/shadow应仅对root可读,/etc/sudoers通常应为440权限。
2.4 用户账户与日志监控
异常的用户和寂静的日志,都是入侵的迹象。
- 用户账户审计:检查
/etc/passwd,寻找UID为0(root权限)的非root用户、空密码用户(x字段后无内容)、或者默认的、不使用的测试账户(如test,guest)。 - 最近登录记录:通过
last、lastb命令查看成功和失败的登录记录,分析是否有来自异常IP或时间的登录尝试。 - 日志文件检查:提示你检查重要的日志文件,如
/var/log/auth.log(Debian/Ubuntu)或/var/log/secure(CentOS/RHEL)以查看认证信息,/var/log/syslog或journalctl查看系统日志。脚本可以引导你使用grep过滤错误、失败等关键词。
注意:审计脚本本身不应直接修改系统配置。它的职责是“发现并报告”。所有修复操作,都应在你明确理解影响后,手动或在受控的自动化流程中完成。脚本的输出应该是清晰、可读的报告,明确指出问题、位置和建议操作。
3. 脚本实操:从下载到生成审计报告
理论讲完了,我们直接上手。假设你有一台刚初始化好的Ubuntu 22.04 VPS。
3.1 获取与运行审计脚本
首先,登录你的VPS。我强烈建议在一个非生产环境或刚创建的快照上先测试。
# 1. 下载脚本(这里假设脚本托管在一个安全的raw链接中,请务必从可信来源获取) wget -O security_audit.sh https://your-trusted-domain/path/to/security_audit.sh # 2. 赋予脚本执行权限 chmod +x security_audit.sh # 3. 以root权限运行(因为很多检查需要root权限才能读取所有信息) sudo ./security_audit.sh如果脚本是你自己编写的,或者是从GitHub等平台克隆的,确保先浏览一下代码,理解它将要执行什么命令,这是一种基本的安全习惯。
3.2 解读脚本输出报告
脚本运行后,会在终端输出彩色(如果支持)的格式化报告,并通常建议将结果重定向到文件以便仔细审查:
sudo ./security_audit.sh | tee audit_report_$(date +%Y%m%d_%H%M%S).txt一份典型的报告会按章节划分,例如:
[+] 系统概览
主机名: myserver 发行版: Ubuntu 22.04.3 LTS 内核版本: 5.15.0-91-generic 运行时间: 0 days, 1 hour, 23 minutes这部分正常,显示这是一台新机器。
[!] SSH 配置检查
发现潜在问题: - /etc/ssh/sshd_config: PermitRootLogin 设置为 'yes' (建议设置为 'no') - /etc/ssh/sshd_config: PasswordAuthentication 设置为 'yes' (建议在配置密钥后设置为 'no')这里标出了两个高风险项。允许root密码登录是很大的风险。
[+] 网络监听端口
LISTEN 端口: 0.0.0.0:22 -> sshd (必须,但需加固) 0.0.0.0:80 -> nginx (业务需要) 127.0.0.1:631 -> cupsd (建议:非必要服务,监听在公网)这里发现cups打印服务监听在本地回环地址,虽然不在公网,但在服务器上通常无用,可以考虑关闭。
[!] 文件权限检查
发现世界可写文件: - /tmp/test_file (临时目录,风险较低但需注意内容) - /var/www/html/upload (业务上传目录,需结合业务评估) 发现SUID文件: - /usr/bin/passwd (正常) - /usr/bin/sudo (正常) - /usr/bin/find (异常!常见命令不应设SUID)最后一个find命令的SUID位非常可疑,很可能是之前被入侵留下的后门,需要立即调查。
3.3 根据报告进行安全加固
报告不是终点,根据报告采取行动才是。以上述输出为例:
加固SSH:
sudo vim /etc/ssh/sshd_config # 找到并修改: # PermitRootLogin no # PasswordAuthentication no # 可选:Port 2222 (修改后需在防火墙开放新端口) sudo systemctl restart sshd重要:在关闭密码认证和重启SSH前,请务必确认你的SSH公钥已正确添加到
~/.ssh/authorized_keys中,否则你将无法再次登录!关闭非必要服务:
# 禁用并停止cups服务 sudo systemctl stop cups sudo systemctl disable cups # 使用`ss -tulnp`再次确认端口631已关闭处理可疑的SUID文件:
# 首先,检查这个find命令的完整性 ls -la /usr/bin/find # 对比其大小、修改时间与同版本系统是否一致 # 使用`dpkg -S /usr/bin/find`(Debian/Ubuntu)或`rpm -qf /usr/bin/find`(RHEL/CentOS)查看它属于哪个包 # 如果确认被篡改,从官方软件源重新安装 sudo apt install --reinstall findutils # Ubuntu/Debian # 或者,直接移除SUID位(如果业务确实不需要) sudo chmod u-s /usr/bin/find设置防火墙(以UFW为例):
sudo ufw default deny incoming # 默认拒绝所有入站 sudo ufw default allow outgoing # 允许所有出站 sudo ufw allow 22/tcp # 或你修改后的SSH端口 sudo ufw allow 80/tcp sudo ufw allow 443/tcp sudo ufw enable sudo ufw status verbose # 查看规则
4. 高级定制与脚本扩展
基础脚本提供了通用检查,但每台服务器的环境不同。让脚本适应你的需求,才是发挥其最大威力的关键。
4.1 添加自定义检查项
假设你的服务器上运行着一个特定的应用,其配置文件在/opt/myapp/config.ini,且该文件不应被Web用户修改。你可以在脚本的“文件权限检查”部分后添加:
echo -e "\n[+] 自定义应用配置检查" CONFIG_FILE="/opt/myapp/config.ini" if [ -f "$CONFIG_FILE" ]; then perms=$(stat -c "%a" "$CONFIG_FILE") if [ "$perms" -ne "600" ]; then echo "[!] 发现配置问题:$CONFIG_FILE 权限为 $perms,建议设置为 600 (仅所有者可读写)。" else echo "[√] $CONFIG_FILE 权限检查通过。" fi else echo "[i] 自定义配置文件 $CONFIG_FILE 不存在。" fi4.2 集成软件漏洞扫描
基础版本检查软件是否更新,但我们可以集成像lynis这样的专业审计工具,或调用系统包管理器的安全更新检查。
echo -e "\n[+] 系统安全更新检查" # 对于Ubuntu/Debian if command -v apt-get &> /dev/null; then echo "检查可用安全更新..." apt list --upgradable 2>/dev/null | grep -i security fi # 对于CentOS/RHEL if command -v yum &> /dev/null; then echo "检查安全更新..." yum check-update --security fi你也可以在脚本中调用lynis audit system并解析其关键建议,但注意lynis本身需要安装。
4.3 实现日志分析与告警
让脚本不仅能检查当前状态,还能分析历史日志,发现入侵尝试的蛛丝马迹。
echo -e "\n[+] 近期失败登录尝试分析" FAILED_LOGINS=$(grep "Failed password" /var/log/auth.log | tail -50) if [ -n "$FAILED_LOGINS" ]; then echo "最近50条失败登录记录:" echo "$FAILED_LOGINS" | awk '{print $1,$2,$3,"来自",$11,"用户",$9}' | sort | uniq -c | sort -nr echo "提示:频繁的失败尝试可能意味着暴力破解。" else echo "未在默认日志中找到失败记录。" fi更进一步,你可以让脚本在发现极端情况(如单IP大量失败尝试)时,自动调用iptables或fail2ban-client临时封禁IP。
4.4 生成HTML或邮件报告
对于需要定期巡检多台服务器的情况,文本报告可能不够直观。可以修改脚本,使其生成HTML报告,并通过邮件发送。
# 在脚本开头定义报告文件 REPORT_HTML="/tmp/security_audit_$(hostname)_$(date +%Y%m%d).html" # 输出HTML头部 cat > $REPORT_HTML << EOF <html><head><title>安全审计报告 - $(hostname)</title></head><body> <h1>服务器安全审计报告</h1> <p>主机:$(hostname)</p> <p>时间:$(date)</p> <hr> EOF # 在每个检查环节,将echo输出重定向并格式化为HTML echo "<h2>SSH配置检查</h2>" >> $REPORT_HTML if [ "$permit_root" = "yes" ]; then echo "<p style='color:red;'>[!] PermitRootLogin 为 yes,建议修改。</p>" >> $REPORT_HTML fi # ... 其他检查 # 结束HTML echo "</body></html>" >> $REPORT_HTML # 使用mail命令发送(需要配置好邮件系统) # mail -s "安全审计报告 $(hostname)" admin@yourdomain.com < $REPORT_HTML5. 常见问题、排查技巧与避坑指南
在实际使用和定制脚本的过程中,我遇到了不少典型问题,这里总结一下,希望能帮你少走弯路。
5.1 脚本运行报错或输出不完整
问题:执行脚本时提示“Permission denied”或某些命令找不到。
排查:
- 权限问题:确保用
sudo运行,或者你当前是root用户。许多系统信息文件(如/etc/shadow)只有root可读。 - 命令路径问题:脚本中尽量使用命令的绝对路径(如
/usr/bin/netstat),或者在最开始使用export PATH=/usr/bin:/bin:/sbin...定义PATH变量。不同的Linux发行版或容器环境,命令位置可能不同。 - 解释器问题:脚本首行必须是
#!/bin/bash。在某些极简系统(如Alpine Linux)中,默认shell可能是ash,某些Bash特性会不支持。
- 权限问题:确保用
问题:输出混乱,颜色代码显示为乱码。
排查:脚本中使用了ANSI颜色代码(如
\e[31m)来高亮显示。如果终端不支持,或者你将输出重定向到文件后再用cat查看,就会显示乱码。可以在脚本中增加一个判断:# 判断是否在支持颜色的终端中运行 if [ -t 1 ]; then RED='\033[0;31m' GREEN='\033[0;32m' NC='\033[0m' # No Color else RED='' GREEN='' NC='' fi echo -e "${RED}[!] 警告信息${NC}"
5.2 审计结果误报与漏报
问题:脚本报告某个服务“不安全”,但该服务是我的业务核心,不能关闭。
处理:这是审计脚本的常态。脚本的职责是提示风险,而不是做出决策。例如,它报告Nginx正在监听80端口。对于Web服务器,这是正常的。你需要结合上下文判断。一个好的脚本应该在报告时给出理由和通用建议,最终的处置权在你手中。你可以在自定义脚本时,将已知的业务必要服务(如
nginx、mysql)加入白名单,避免重复告警。问题:脚本没有发现某个已知的安全漏洞。
排查:
- 检查点过时:安全威胁在变化,脚本的检查项也需要定期更新。例如,新的漏洞(如Log4j)需要特定的检查命令。你需要关注安全社区,更新你的脚本逻辑。
- 深度不足:基础脚本主要做“配置审计”,无法进行“漏洞扫描”(如软件0day)或“行为分析”(如检测挖矿进程)。对于更深度的需求,需要集成专业工具(如ClamAV查毒、rkhunter查rootkit),或者部署HIDS(主机入侵检测系统)。
5.3 安全加固后的副作用
问题:按照脚本建议修改SSH配置并重启后,自己也被锁在服务器外面了。
避坑指南:这是最危险的坑!务必遵循以下顺序:
- 先测试,后生效:在修改
sshd_config前,先在一个新的SSH会话中测试配置是否正确:sudo sshd -t。 - 保持活动连接:在重启SSH服务 (
sudo systemctl restart sshd) 时,确保你当前用来操作的SSH连接不要断开。先在新窗口测试新配置(如用新端口、新密钥)登录成功,再关闭旧会话。 - 使用连接保活:在客户端的
~/.ssh/config里为这台服务器设置ServerAliveInterval 60,防止长时间无操作导致连接中断,而你还没来得及修复登录问题。
- 先测试,后生效:在修改
问题:关闭了某个服务后,发现另一个依赖它的服务报错了。
避坑指南:在禁用或停止一个服务前,使用
systemctl list-dependencies <service-name>查看它被哪些服务依赖,或者使用netstat -tulnp | grep :端口号查看是哪个进程在监听,确认其作用。对于不熟悉的系统服务,最好先搜索一下其功能。
5.4 脚本自身的维护与安全
- 问题:脚本放在哪里?如何更新?
- 建议:将脚本放在版本控制系统(如Git)中管理。这样你可以追踪更改,方便回滚,也能在多台服务器间同步更新。可以在服务器上通过
cron任务定期从Git仓库拉取最新脚本并执行(注意做好认证和通信安全)。 - 问题:脚本内容会不会被恶意篡改?
- 建议:这是安全脚本的悖论。确保你从可信源获取脚本,并定期校验其完整性(如对比哈希值)。如果脚本需要通过网络下载,尽量使用HTTPS链接。对于自己编写的脚本,也要严格控制其存放目录的权限。
最后,我想强调的是,这个7分钟的安全审计脚本,是一个强大的起点和辅助工具,但它绝不是安全的终点。真正的服务器安全是一个涵盖网络防火墙、系统加固、最小权限、持续监控、漏洞管理、数据备份和应急响应的完整体系。定期运行这个脚本,能帮你养成良好的安全巡检习惯,及时发现“低垂的果实”式的风险。把它集成到你的服务器初始化清单和定期维护计划中,让它成为你运维工具箱里一件趁手的“听诊器”。