Skip to content

Repository files navigation

SafeVPS

面向公网 Linux VPS 的可验证安全基线。

一条 Bash 脚本完成最小权限防火墙、SSH 暴力破解防护、自动安全更新与真实封禁验证;变更过程带独占锁,每次执行前创建可校验快照。

Shell checks Release Bash Firewall Fail2Ban License

快速开始 · 配置模型 · 更多功能 · 安全机制 · 运维参考

简体中文 · 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 会话中擅自自动回滚防火墙;由操作者确认当前连接状态后恢复更可控。

移除 SafeVPS 管理配置

sudo bash setup_server_security.sh --remove-managed

清理前会创建快照,并要求输入 REMOVE。该模式不卸载软件包、不删除历史快照、不重置共享防火墙默认策略;最小 SSH 规则会作为可恢复安全通道保留,避免远程自锁,并能在下次正式配置或快照恢复时被精确替换。确认第二次 SSH 登录正常后,也可自行删除该保留规则。

为什么使用 SafeVPS

目标 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.conf
PORT_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.sh

firewalld 模式只添加并记录 SSH、TCP、UDP 端口,不修改 zone target 或富规则;target 为 ACCEPT 时拒绝执行。服务未运行时会先通过 firewall-offline-cmd 将 SSH 写入默认 zone 再启动;服务已运行时,所选 zone 必须处于激活状态。它不实现 UFW 的出站邮件阻断,因此必须设置 BLOCK_MAIL_OUT=0。两个后端不能同时启用;切换后端前先用原后端执行 --remove-managed

1. 入站端口

模式 自动保护 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

2. Fail2Ban 策略

策略 统计窗口 失败次数 封禁时间 建议用途
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;经过堡垒机或四层代理时,服务器只能封禁日志中实际出现的代理地址。

3. 更多安全功能

更多功能默认选择 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.sh

Note

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[输出状态与暴露审计]
Loading

任何关键配置校验失败都会停止流程;Fail2Ban、SSH、sysctl、journald 和 auditd 的变更都具有针对性的恢复处理。

安全机制

SSH 防失联

SSH 端口按以下顺序确定:

  1. 显式设置的 SSH_PORT
  2. 当前 SSH_CONNECTION 中的服务器端口
  3. sshd -T 返回的全部配置端口
  4. 无法检测时回退到 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.rulesuser6.rules;恢复这类快照时会还原重置前的完整 UFW 用户规则。

Docker 边界

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 zhen;也可使用 --lang en
SAFEVPS_CONFIG 等同于 --config 的配置文件路径
ASSUME_YES 0 跳过交互确认
FIREWALL_BACKEND ufw ufwfirewalld;切换前先清理原后端规则
FIREWALLD_ZONE public firewalld 端口写入的 zone
PORT_MODE 交互;无人值守 minimal minimalpresetcustom
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 relaxedstandardstrictcustom
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 高级兼容参数:baselineauditoffcustom
SYSCTL_HARDENING 0 应用保守型 sysctl 配置
SECURITY_AUDIT 0 输出扩展审计报告
SSH_HARDENING_PROFILE off basicstrictoff
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,创建注释为 SSHSSH 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 登录。

About

No description, website, or topics provided.

Resources

Security policy

Stars

8 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages