一个模块化的 Bash 工具包,用于在比赛时间压力下加固 Debian/Ubuntu 系列系统。在多个赛季的 CyberPatriot 全国青少年网络防御竞赛 中构建并不断完善,最近在 2025 年半决赛中获得了 Linux 组别的白金级别。
这不是一个通用合规框架。它是一个针对六小时限时演练的检查清单自动化工具:它正确、快速且幂等地完成 Linux 加固过程中可脚本化的绝大部分工作,记录它触及的所有内容,并将需要判断的决策留给运行它的人。
CyberPatriot 的 Linux 轮次会根据一份评分标准对实时镜像进行评分,该标准奖励一组相当可预测的加固步骤——账户卫生、密码策略、防火墙配置、服务暴露、文件权限、补丁级别——在严格的时间限制下,通常事先不知道具体植入了哪些漏洞。在倒计时下手工正确地完成这份检查清单,正是团队因拼写错误和遗漏步骤而丢掉容易得分的地方,而不是因为未知内容。
这个工具包最初是在这种压力下编写的一个单一整体脚本。本仓库是该脚本的重写:相同的检查清单覆盖范围,重构为小型、单一用途的模块,更易于阅读、测试和独立推理,每个非显而易见的决策都追溯到特定的 CIS Benchmark 章节或 NIST SP 800-53 控制项(参见 安全控制与参考)。
flowchart TD
A[bin/harden.sh] --> B[lib/common.sh<br/>logging, backups, run wrapper]
A --> C[Service-role prompts<br/>or --config file]
A --> D[lib/packages.sh<br/>updates, attack-tool removal]
A --> E[lib/firewall.sh<br/>default-deny + ufw]
A --> F[lib/ssh.sh]
A --> G[lib/services.sh<br/>samba/ftp/mail/http/mysql/dns]
A --> H[lib/users.sh<br/>account review, hidden UID 0]
A --> I[lib/kernel.sh<br/>sysctl hardening]
A --> J[lib/pam.sh<br/>password policy, lockout]
A --> K[lib/filesystem.sh<br/>permissions, cron, banners]
A --> L[lib/monitoring.sh<br/>fail2ban, auditd, rkhunter]
A --> M[lib/forensics.sh<br/>baseline snapshot]
D & E & F & G & H & I & J & K & L & M --> N[(~/hardening-run/<br/>log + backups + baseline)]
每个模块都由 bin/harden.sh 加载,它负责参数解析、服务角色问卷和执行顺序。模块之间不直接相互调用,每个模块中每个改变状态的命令都通过 lib/common.sh 中的 run() 包装器执行,这为整个项目提供了一个统一的地方来实现 dry-run 支持、一致的日志记录和非致命错误处理。
git clone <this-repo>
cd cyberpatriot-linux-hardening
sudo ./bin/harden.sh
系统会询问你一系列关于机器角色的简短是/否问题(是否需要 Samba、FTP、SSH、Web 服务器等),然后它会无人值守地运行上述模块。日志、一整套带时间戳的配置备份以及系统基线快照会写入 ~/hardening-run/。
在实际轮次中,跳过每个软件包的确认提示,并从准备好的答案文件中回答角色问题,而不是现场输入:
cp examples/config.env.example my-machine.env
# edit my-machine.env for this box's actual role
sudo ./bin/harden.sh --config my-machine.env --auto-approve
想在实际改动任何东西之前确切了解它会做什么?
sudo ./bin/harden.sh --dry-run --config my-machine.env
| 模块 | 作用 |
|---|---|
lib/packages.sh | 完整系统更新;自动移除密码破解和漏洞利用工具;在移除双用途工具(nmap、Wireshark、netcat)和遗留服务(VNC、NFS、telnet)之前先进行审查 |
lib/firewall.sh | 通过 ufw 实现默认拒绝入站 / 默认允许出站,并显式阻止一个已知的常见后门端口 |
lib/ssh.sh | 现代加密算法/KEX/MAC,禁止 root 登录,连接和会话限制——或者如果角色不需要 SSH,则完全移除它 |
lib/services.sh | Samba、FTP、邮件、打印、MySQL、HTTP、DNS:如果角色需要,则安装并进行最低限度加固;如果不需要,则清除并用防火墙隔离 |
lib/users.sh | 交互式审查现有账户(管理员权限、删除、密码重置),检测隐藏的 UID-0 账户和空密码 |
lib/kernel.sh | 网络栈和内核自我保护 sysctl 设置(源路由、ICMP 重定向、ASLR、ptrace 范围、dmesg/kptr 限制) |
lib/pam.sh | 通过 pam_pwquality/pam_pwhistory 实现密码复杂度和历史记录,通过 pam_faillock 实现账户锁定,在 login.defs 中设置密码时效 |
lib/filesystem.sh | 核心文件权限、cron/at 限制、最小化 rc.local、法律登录横幅、只读 SUID/全局可写/无主文件扫描 |
lib/monitoring.sh | 默认启用 fail2ban 和 auditd;ClamAV 和完整的 rkhunter/chkrootkit 扫描为可选(参见 比赛安全注意事项) |
lib/forensics.sh | 用户、进程、监听端口和已安装软件包的只读快照,供后续比较 |
tools/find-port-owner.sh 和 tools/list-nonstandard-users.sh 是用于同类分类工作的小型独立实用工具,可独立于主脚本使用——用法参见它们的头部注释。
一个加固脚本如果破坏了它本应保护的机器,在限时轮次中比无用更糟糕。一些默认设置反映了这一点,在你无人值守运行之前值得理解:
SSH_PASSWORD_AUTH=no),但这里的默认值倾向于避免在还没有人配置密钥时把团队锁在自己机器之外。INSTALL_CLAMAV、RUN_BASELINE_SCAN),因为它们是此脚本能执行的两个最慢的操作,且两者本身都不会改变系统状态。如果你的检查清单要求它们,或者你有空闲时间,请开启它们。~/hardening-run/baseline/listening_ports.txt。docs/security-controls.md。如果你不预先回答,bin/harden.sh 会交互式地询问机器的服务角色。要跳过提示,请复制 examples/config.env.example,填写实际角色,并通过 --config 传入。文件中遗漏的任何变量都会回退到交互式提示,因此部分填写的配置文件也可以。
sudo ./bin/harden.sh --config my-machine.env
标志:
| 标志 | 效果 |
|---|---|
--config FILE | 从 env 文件加载角色/策略答案 |
--dry-run | 记录将要采取的每个操作;不做任何更改 |
--auto-approve | 跳过每个软件包的清除确认提示 |
.
├── bin/harden.sh orchestrator: parses args, asks role questions, runs modules in order
├── lib/
│ ├── common.sh logging, backups, idempotent file edits, the run() wrapper
│ ├── packages.sh updates, attack-tool removal
│ ├── ssh.sh SSH install/removal and hardening
│ ├── services.sh samba/ftp/telnet/mail/printing/mysql/http/dns
│ ├── firewall.sh ufw default-deny posture
│ ├── users.sh account review, hidden UID 0 / empty password detection
│ ├── kernel.sh sysctl hardening
│ ├── pam.sh password policy, account lockout
│ ├── filesystem.sh permissions, cron, rc.local, banners, anomaly scan
│ ├── monitoring.sh fail2ban, auditd, rkhunter, chkrootkit, ClamAV
│ └── forensics.sh read-only system baseline snapshot
├── tools/
│ ├── find-port-owner.sh resolve a listening TCP port to a process path
│ └── list-nonstandard-users.sh flag UID >= 1000 accounts not on an expected list
├── docs/
│ ├── security-controls.md every hardening decision, mapped to its source standard
│ └── editor-cheatsheet.md small editor commands worth remembering under pressure
├── examples/config.env.example annotated template for non-interactive runs
└── .github/workflows/shellcheck.yml lint on every push/PR
每个脚本在推送时都会通过 GitHub Actions(.github/workflows/shellcheck.yml)使用 ShellCheck 进行 lint。要在打开 PR 之前在本地检查:
shellcheck lib/*.sh bin/*.sh tools/*.sh
bin/harden.sh --dry-run 本身也是一个测试:它会在不触及文件系统或安装任何东西的情况下,演练每个模块的控制流和日志记录,是在真正运行之前针对一次性 VM 对更改进行健全性检查的最快方法。关于新模块的完整期望(幂等性、通过 run() 路由破坏性操作,以及为任何新的加固步骤引用来源),请参见 CONTRIBUTING.md。
每个模块的头部注释和 docs/security-controls.md 都引用了每个决策背后的具体标准章节。全程使用的主要来源:
| 标准 | 来源 |
|---|---|
| CIS Ubuntu Linux Benchmark | https://www.cisecurity.org/benchmark/ubuntu_linux |
| NIST SP 800-53 Rev. 5 | https://csrc.nist.gov/pubs/sp/800/53/r5/upd1/final |
| DISA STIG for Ubuntu | https://public.cyber.mil/stigs/downloads/ |
| Mozilla OpenSSH modern configuration guidelines | https://infosec.mozilla.org/guidelines/openssh |
| CyberPatriot National Youth Cyber Defense Competition | https://www.uscyberpatriot.org/ |
引用的检测工具(未内置,通过 apt 安装):
fail2ban、
Linux Audit / auditd、
rkhunter、
chkrootkit。Lynis
和 OpenSCAP 被推荐作为后续的独立审计,本项目不会自动运行它们。
关于每一项背后的完整理由,请参见 docs/security-controls.md。
MIT。参见 LICENSE。