面向公网 Linux VPS 的可验证安全基线。
一条 Bash 脚本完成最小权限防火墙、SSH 暴力破解防护、自动安全更新与真实封禁验证;变更过程带独占锁,每次执行前创建可校验快照。
快速开始 · 配置模型 · 更多功能 · 安全机制 · 运维参考
简体中文 · English
下载最新版并执行:
wget -O setup_server_security.sh https://raw.githubusercontent.com/sanrokamlan-prog/safevps/main/setup_server_security.sh && sudo bash setup_server_security.sh也可以使用 curl:
curl -fLo setup_server_security.sh https://raw.githubusercontent.com/sanrokamlan-prog/safevps/main/setup_server_security.sh
sudo bash setup_server_security.sh交互流程会先展示完整配置摘要。只有输入大写 YES 后,脚本才会创建快照并修改系统。
Important
防火墙与 SSH 变更始终存在远程失联风险。执行后请保持当前会话,使用第二个终端验证 SSH 登录,再关闭原连接。
sudo bash setup_server_security.sh --check--dry-run 是同一只读模式的别名。它会检查选定的防火墙后端、Fail2Ban、监听端口、IPv6、Docker 暴露和时间同步,不安装软件、不写入规则。
监控系统可以读取 schema v2 标准 JSON;核心基线异常时退出码为 2:
sudo bash setup_server_security.sh --check --json预演一套目标配置但不修改系统:
sudo PORT_MODE=custom TCP_PORTS="80 443" bash setup_server_security.sh --plan--plan 会执行与正式运行相同的参数解析、端口发现和安全校验,然后输出最终摘要,不创建锁文件或快照。
sudo bash setup_server_security.sh --restore-last也可以列出并恢复指定历史快照:
sudo bash setup_server_security.sh --list-backups
sudo bash setup_server_security.sh --restore 20260726T120000Z-abc123快照保存在 /var/lib/safevps/backups/,默认保留最近 10 份并通过 SHA-256 检查完整性。普通恢复只删除当前状态文件记录的 UFW 或 firewalld 规则并重建快照中的 SafeVPS 规则,不覆盖用户后来新增的其他规则,也不会卸载软件包。
快照创建后的任何失败都会输出对应的 --restore-last 命令。SafeVPS 不会在 SSH 会话中擅自自动回滚防火墙;由操作者确认当前连接状态后恢复更可控。
sudo bash setup_server_security.sh --remove-managed清理前会创建快照,并要求输入 REMOVE。该模式不卸载软件包、不删除历史快照、不重置共享防火墙默认策略;最小 SSH 规则会作为可恢复安全通道保留,避免远程自锁,并能在下次正式配置或快照恢复时被精确替换。确认第二次 SSH 登录正常后,也可自行删除该保留规则。
| 目标 | SafeVPS 的处理方式 |
|---|---|
| 防止误开端口 | 默认只放行检测到的 SSH 端口,Web/UDP 端口必须明确选择 |
| 防止 SSH 暴力破解 | UFW limit(默认后端)+ Fail2Ban 分级策略,默认 1 小时内失败 3 次永久封禁 |
| 确认封禁真实有效 | 临时封禁保留测试地址,直接检查 nftables、iptables、ipset 或 UFW 规则 |
| 避免覆盖用户规则 | 独立记录 SafeVPS 创建的 UFW/firewalld 规则,重复运行只替换这些规则 |
| 降低变更风险 | 独占运行锁、配置校验、服务就绪检查、失败回滚、完整性快照与 --restore-last |
| 覆盖双栈服务器 | 检测全局 IPv6,验证 IPv4 和 IPv6 封禁规则的写入与删除 |
| 保留运维控制权 | 高风险 SSH/sysctl/auditd 功能默认关闭,通过数字菜单显式启用 |
普通执行默认包含以下配置:
UFW deny incoming / allow outgoing
SSH 自动检测端口并应用 UFW limit
Fail2Ban strict: 1 小时内失败 3 次,永久封禁
安全更新 自动安装,不自动重启
真实封禁验证 IPv4;存在全局 IPv6 时同时验证 IPv6
配置快照 每次正式变更前创建,SHA-256 校验,默认保留 10 份
Docker 默认审计发布到全部接口的端口,不自动改转发链
脚本不会默认关闭 SSH 密码登录、关闭 root、修改 SSH 端口、改 Docker 网络或自动重启服务器。
批量服务器可以使用 root 管理的配置文件,环境变量优先于文件内容:
sudo install -d -m 700 /etc/safevps
sudo install -m 600 /dev/null /etc/safevps/config.conf
sudo editor /etc/safevps/config.conf
sudo bash setup_server_security.sh --config /etc/safevps/config.conf --plan
sudo bash setup_server_security.sh --config /etc/safevps/config.confPORT_MODE=custom
TCP_PORTS="80 443"
UDP_PORTS="51820"
FAIL2BAN_PROFILE=strict
MORE_FEATURES="1 2 3"
BACKUP_RETENTION=10解析器只接受文档列出的白名单 KEY=VALUE,不会执行 Shell 展开。文件必须归 root 所有、不能是符号链接,并且组用户和其他用户不能写入;不支持行尾注释。
仓库提供两份可直接审查的模板:UFW 最小基线 和 firewalld 最小基线。部署时用 install -m 600 放入 /etc/safevps/config.conf,再先执行 --plan。
UFW 是默认后端,也是 Debian/Ubuntu 的推荐路径。RHEL 系列可显式选择 firewalld:
sudo FIREWALL_BACKEND=firewalld FIREWALLD_ZONE=public BLOCK_MAIL_OUT=0 \
bash setup_server_security.sh --plan
sudo FIREWALL_BACKEND=firewalld FIREWALLD_ZONE=public BLOCK_MAIL_OUT=0 \
bash setup_server_security.shfirewalld 模式只添加并记录 SSH、TCP、UDP 端口,不修改 zone target 或富规则;target 为 ACCEPT 时拒绝执行。服务未运行时会先通过 firewall-offline-cmd 将 SSH 写入默认 zone 再启动;服务已运行时,所选 zone 必须处于激活状态。它不实现 UFW 的出站邮件阻断,因此必须设置 BLOCK_MAIL_OUT=0。两个后端不能同时启用;切换后端前先用原后端执行 --remove-managed。
| 模式 | 自动保护 SSH | 额外 TCP | 额外 UDP | 适用场景 |
|---|---|---|---|---|
minimal 默认 |
是 | 无 | 无 | 新服务器、后端节点、最小暴露面 |
preset |
是 | 80 443 |
10000:10010 |
Web 与实时媒体服务 |
custom |
是 | 用户输入 | 用户输入 | VPN、面板、自定义应用 |
自定义端口使用空格分隔,范围使用英文冒号:
TCP: 80 443 8000:8010
UDP: 51820 10000:10010
不要使用逗号或短横线。SSH 端口会自动保护,不需要重复填写。
无人值守示例:
sudo ASSUME_YES=1 \
PORT_MODE=custom \
TCP_PORTS="80 443 8000:8010" \
UDP_PORTS="51820" \
bash setup_server_security.sh| 策略 | 统计窗口 | 失败次数 | 封禁时间 | 建议用途 |
|---|---|---|---|---|
relaxed |
10m |
8 |
1h |
多人维护、容错优先 |
standard |
30m |
5 |
24h |
平衡容错与拦截强度 |
strict 默认 |
1h |
3 |
-1 永久 |
仅密钥或少量管理员的公网 VPS |
custom |
自定义 | 1-100 |
自定义 | 特殊业务策略 |
自定义示例:
sudo FAIL2BAN_PROFILE=custom \
FAIL2BAN_FINDTIME=2h \
FAIL2BAN_MAXRETRY=4 \
FAIL2BAN_BANTIME=7d \
bash setup_server_security.sh-1 表示永久封禁。Fail2Ban 封禁的是 SSH 日志中看到的来源 IP;经过堡垒机或四层代理时,服务器只能封禁日志中实际出现的代理地址。
更多功能默认选择 n,不改变现有 SSH、sysctl、journald 或 auditd 配置。可输入多个编号,例如 1 2 3。
| 编号 | 功能 | 默认 | 影响范围 |
|---|---|---|---|
1 |
保守型 sysctl 网络加固 | 关 | SYN Cookie、ASLR、重定向与源路由;不改转发和 rp_filter |
2 |
最终安全审计报告 | 关 | 时间同步、安全模块、失败服务、监听端口、Docker 端口 |
3 |
基础 SSH 加固 | 关 | 收紧认证次数与日志,不关闭密码/root 登录 |
4 |
严格 SSH 加固 | 关 | 仅允许公钥登录,需要密钥检查和 KEY-ONLY 二次确认 |
5 |
推荐组合 | 关 | 1 + 2 + 3 |
6 |
journald 持久化 | 关 | 最多 256MB,最长 30 天 |
7 |
auditd 关键文件审计 | 关 | 账户、shadow、sudoers、SSH 配置 |
8 |
启用现有时间同步服务 | 关 | chrony、systemd-timesyncd 或 ntpd |
9 |
可观测性组合 | 关 | 2 + 6 + 7 + 8 |
自动化选择更多功能:
sudo ASSUME_YES=1 MORE_FEATURES="1 2 3" bash setup_server_security.shNote
n 表示本次跳过,不会删除以前由 SafeVPS 启用的可选配置。需要冻结软件版本的环境可设置 AUTO_SECURITY_UPDATES=0。
flowchart LR
A[检测系统与 SSH] --> B[选择端口与封禁策略]
B --> C[显示最终摘要]
C -->|输入 YES| D[创建配置快照]
D --> E[安装并验证依赖]
E --> F[更新 SafeVPS 防火墙规则]
F --> G[校验并重启 Fail2Ban]
G --> H[验证 IPv4 / IPv6 真实封禁]
H --> I[应用已选择的扩展功能]
I --> J[输出状态与暴露审计]
任何关键配置校验失败都会停止流程;Fail2Ban、SSH、sysctl、journald 和 auditd 的变更都具有针对性的恢复处理。
SSH 端口按以下顺序确定:
- 显式设置的
SSH_PORT - 当前
SSH_CONNECTION中的服务器端口 sshd -T返回的全部配置端口- 无法检测时回退到
22并显示警告
SafeVPS 同时保护当前连接端口、sshd -T 配置端口、ListenAddress 端口和实际由 sshd 监听的 TCP 端口。严格 SSH 加固还会检查公钥内容、所有权和目录权限,通过 sshd -t 校验配置、重新加载服务并读取 sshd -T 确认参数真实生效。
服务启动后,脚本会临时封禁文档保留地址:
- IPv4:
192.0.2.0/24 - IPv6:
2001:db8::/32,仅在检测到全局 IPv6 时执行
只有 Fail2Ban 状态变化但防火墙没有对应规则时,脚本会报错。测试地址随后会自动解除,并再次确认规则已删除。
- UFW 管理状态:
/var/lib/safevps/ufw.rules - firewalld 管理状态:
/var/lib/safevps/firewalld.rules - 配置快照:
/var/lib/safevps/backups/ - 最近快照指针:
/var/lib/safevps/last-backup - 同一时间只允许一个正式配置或恢复操作运行
- 快照写入后生成 SHA-256 清单,恢复前必须通过校验
- 正式配置、恢复和清理写入 root 私有的有界操作日志,不记录 IP 或配置内容
- 默认只替换 SafeVPS 自己记录的规则
RESET_UFW=1是唯一会重置整个 UFW 规则集的选项
普通恢复不会整目录覆盖 /etc/ufw,也不会删除无法确认归属的用户规则。如果某次执行明确使用了 RESET_UFW=1,该次快照会额外保存 /etc/ufw/user.rules 和 user6.rules;恢复这类快照时会还原重置前的完整 UFW 用户规则。
Docker 发布端口可能绕过主机防火墙的常规 INPUT/OUTPUT 路径。SafeVPS 会检测发布到 0.0.0.0 或 [::] 的容器端口,但不会自动修改 Docker、iptables 或 nftables 转发链。
DOCKER_EXPOSURE_POLICY=audit 是默认值,只报告暴露;fail 会在创建快照或修改系统前中止;off 关闭该检查。fail 是部署门禁,不是容器防火墙,已有容器的网络状态不会被改变。
docker ps --format 'table {{.Names}}\t{{.Ports}}'
sudo iptables -S DOCKER-USER 2>/dev/null || true云平台安全组、Docker 转发规则、主机防火墙和应用监听必须一起审查。
| 环境 | 状态 |
|---|---|
| Debian 12/13、Ubuntu 22.04/24.04 + UFW | 正式支持;需要 Bash 4.3+、systemd 和 util-linux flock;Ubuntu 缺包时可启用官方 universe |
| RHEL / Rocky / AlmaLinux / CentOS / Fedora + firewalld | 条件支持;使用 dnf/yum,必要时启用发行版提供的 EPEL 包,并验证 zone 与 Fail2Ban action |
dnf / yum 系统 + UFW |
条件支持;软件源必须提供 UFW |
| nftables / iptables / ipset Fail2Ban action | 自动识别并验证所需命令 |
| UFW 与 firewalld 同时运行 | 拒绝正式配置,避免双重管理 |
| Arch / openSUSE / Alpine | 当前不支持 |
CI 会在 Debian/Ubuntu 官方容器验证脚本、平台识别和软件包路径;容器不具备真实 systemd 防火墙环境。firewalld 支持属于运行时条件支持,应先在新 SSH 会话可恢复的测试机上执行 --plan 和 --check。
# 只读检查
sudo bash setup_server_security.sh --check
# JSON 健康检查:健康返回 0,异常返回 2
sudo bash setup_server_security.sh --check --json
# 预演目标配置
sudo bash setup_server_security.sh --config /etc/safevps/config.conf --plan
# UFW、firewalld 与 Fail2Ban 状态
sudo ufw status verbose
sudo firewall-cmd --list-all
sudo fail2ban-client status
sudo fail2ban-client status sshd
# 解除封禁
sudo fail2ban-client set sshd unbanip 1.2.3.4
# 恢复最近快照
sudo bash setup_server_security.sh --restore-last
# 查看并选择历史快照
sudo bash setup_server_security.sh --list-backups
sudo bash setup_server_security.sh --restore <snapshot-id>
# 移除 SafeVPS 管理配置,不卸载软件包
sudo bash setup_server_security.sh --remove-managed生产环境可固定到发布标签;需要不可歧义复现时,再固定到已审核的完整提交 SHA:
VERSION="v1.2.0"
wget -O setup_server_security.sh "https://raw.githubusercontent.com/sanrokamlan-prog/safevps/${VERSION}/setup_server_security.sh"
sudo bash setup_server_security.sh --version
sudo bash setup_server_security.sh --check
sudo bash setup_server_security.sh提交级固定只需把 VERSION 换成完整的 40 位 commit SHA。升级前阅读 CHANGELOG,并在一台可恢复测试机上执行 --plan 与 --check。
环境变量参考
| 变量 | 默认值 | 说明 |
|---|---|---|
SAFEVPS_LANG |
zh |
zh 或 en;也可使用 --lang en |
SAFEVPS_CONFIG |
空 | 等同于 --config 的配置文件路径 |
ASSUME_YES |
0 |
跳过交互确认 |
FIREWALL_BACKEND |
ufw |
ufw 或 firewalld;切换前先清理原后端规则 |
FIREWALLD_ZONE |
public |
firewalld 端口写入的 zone |
PORT_MODE |
交互;无人值守 minimal |
minimal、preset、custom |
SSH_PORT |
自动检测 | 额外保护的 SSH 端口 |
TCP_PORTS / UDP_PORTS |
空 | 自定义端口或 8000:8010 范围 |
BLOCK_MAIL_OUT |
1 |
阻止出站 TCP 25/465/587 |
RESET_UFW |
0 |
1 会重置全部 UFW 规则 |
TRUST_CURRENT_SSH_IP |
0 |
把当前 SSH 客户端 IP 加入 Fail2Ban ignoreip |
FAIL2BAN_PROFILE |
strict |
relaxed、standard、strict、custom |
FAIL2BAN_FINDTIME |
策略决定 | 自定义统计窗口 |
FAIL2BAN_MAXRETRY |
策略决定 | 自定义失败次数,1-100 |
FAIL2BAN_BANTIME |
策略决定 | 自定义封禁时间,-1 永久 |
VERIFY_FAIL2BAN |
1 |
验证真实 IPv4/IPv6 防火墙封禁 |
AUTO_SECURITY_UPDATES |
1 |
自动安全更新,不自动重启 |
BACKUP_RETENTION |
10 |
保留最近 1-100 份配置快照 |
OPERATION_LOG |
1 |
记录脱敏操作结果;超过 1 MiB 时保留最近 1000 行 |
ENABLE_UBUNTU_UNIVERSE |
1 |
Ubuntu 当前源缺少 UFW/Fail2Ban 时启用官方 universe |
ENABLE_EPEL |
1 |
dnf/yum 当前源缺少 Fail2Ban 时安装可用的 epel-release |
DOCKER_EXPOSURE_POLICY |
audit |
audit 报告、fail 变更前中止、off 关闭检查 |
MORE_FEATURES |
n |
空格分隔的功能编号 1-9 |
HARDENING_PROFILE |
off |
高级兼容参数:baseline、audit、off、custom |
SYSCTL_HARDENING |
0 |
应用保守型 sysctl 配置 |
SECURITY_AUDIT |
0 |
输出扩展审计报告 |
SSH_HARDENING_PROFILE |
off |
basic、strict、off |
STRICT_SSH_CONFIRMED |
0 |
无人值守严格 SSH 模式必须为 1 |
SSH_AUTHORIZED_KEYS_USER |
root / SUDO_USER |
额外指定严格模式公钥用户 |
PERSISTENT_JOURNAL |
0 |
持久化 journald,限制 256MB / 30 天 |
ENABLE_AUDITD |
0 |
启用关键文件审计 |
ENABLE_TIME_SYNC |
0 |
启用已安装的时间同步服务 |
旧变量 UDP_RANGE 仍兼容,但新配置应使用 UDP_PORTS。
SafeVPS 管理的文件
| 路径 | 用途 |
|---|---|
/var/lib/safevps/ufw.rules |
SafeVPS UFW 规则状态 |
/var/lib/safevps/firewalld.rules |
SafeVPS firewalld 规则状态 |
/var/lib/safevps/backups/ |
执行前配置快照 |
/run/safevps.lock |
正式配置与恢复操作的独占运行锁 |
/var/log/safevps/operations.log |
root 私有的脱敏操作审计日志 |
/etc/fail2ban/jail.d/99-safevps.local |
SSH jail 与封禁策略 |
/etc/ssh/sshd_config.d/99-safevps.conf |
可选 SSH 加固 |
/etc/sysctl.d/99-safevps.conf |
可选内核网络加固 |
/etc/systemd/journald.conf.d/99-safevps.conf |
可选日志持久化 |
/etc/audit/rules.d/99-safevps.rules |
可选 auditd 规则 |
/etc/apt/apt.conf.d/52safevps-unattended-upgrades |
apt 自动安全更新 |
旧版迁移
旧版脚本可能写入 /etc/fail2ban/jail.local,创建注释为 SSH、SSH rate limit 的 UFW 规则,或默认开放 TCP 80/443 和 UDP 10000:10010。
sudo ufw status numbered
sudo sed -n '1,200p' /etc/fail2ban/jail.local 2>/dev/null新版不会自动删除无法确认归属的旧规则。确认规则完全来自旧版 SafeVPS 后再手动清理,不要在远程服务器上盲目删除 SSH 规则。
bash -n setup_server_security.sh tests/test_setup_server_security.sh tests/test_platform_smoke.sh
bash tests/test_setup_server_security.sh
shellcheck --severity=style setup_server_security.sh tests/test_setup_server_security.sh tests/test_platform_smoke.sh每次 push 和 pull request 都会运行 Bash 语法检查、行为测试与 ShellCheck,并在 Debian 12/13、Ubuntu 22.04/24.04、Rocky Linux 8/9 容器中验证 Bash、发行版识别、防火墙包以及 Fail2Ban 软件源路径。容器没有真实 systemd 防火墙环境,因此该矩阵不声称替代 VPS 上的 UFW/firewalld/Fail2Ban 集成测试。
MIT License · 变更日志 · 安全策略与私密漏洞报告
先检查,再执行;保留当前会话,验证第二次 SSH 登录。