VPS服务器搭建7层防护图:可行做法与顺序
来源: 飞翔小编 2026/11/4 15:13:05 浏览量:0
一、七层模型:每层防的是不同的攻击者

先说清楚这套分层有什么用。安全问题之所以让人无从下手,是因为把不同性质的问题混在了一起——改密码、装防火墙、备份数据库,这些动作之间没有逻辑关系,你只能靠别人的清单硬记。
按层拆开之后,每一层有明确的防御目标、配置手段和验证方法,层与层之间是递进关系:下层失效了,上层的配置仍然有效;反过来,上层做得再好,下层塌了照样被攻破。
| 层级 | 防的是什么 | 核心手段 | 验证方式 |
|---|---|---|---|
| 第一层 商家与物理 | 宿主机被入侵、邻居租户越权 | 选商家、快照、救援模式 | 控制台可见 |
| 第二层 网络 | 端口被扫、流量被攻击 | 防火墙、安全组、限流 | 外部端口扫描 |
| 第三层 主机系统 | 提权、后门植入、漏洞利用 | 补丁、最小化服务、审计 | 版本与更新检查 |
| 第四层 身份认证 | 暴力破解、凭证泄露 | 密钥、2FA、权限分离 | 禁用密码测试 |
| 第五层 应用与 Web | SQL 注入、XSS、越权 | 输入校验、限流、响应头 | 安全头与日志检查 |
| 第六层 容器编排 | 容器逃逸、镜像投毒 | 最小权限镜像、只读挂载 | 镜像与权限审计 |
| 第七层 数据与备份 | 数据被删、被加密勒索 | 异地备份、恢复演练 | 定期恢复测试 |
这张表本身就是一张检查表。从上往下读是威胁模型,从下往上搭是实施顺序——实际搭建时要从第一层开始,因为第一层决定了你的后路是否存在。
还要补充一个概念:层与层之间不是独立的,而是有依赖关系的。举个具体的例子说明这个依赖。
第一层(快照和救援模式)决定了第四层(SSH 密钥)的容错空间。如果没有第一层,你在第四层改 SSH 配置时一旦出错,就没有任何退路;有了第一层,第四层就敢做激进的改动。第五层(应用层防护)依赖第三层(系统更新),因为一个跑着两年没打补丁的 PHP,你的输入校验写得再好也可能被已知漏洞绕过。第七层(备份)依赖第二层和第三层——如果暴露面没收敛,攻击者会持续进来,备份再多也只是不停地恢复。
这个依赖关系决定了顺序不能乱。先做能降低后续操作风险的事,这是整个七层模型的核心使用方式。
还有一个判断层与层之间衔接是否正常的标准:看每一层的日志和输出能不能串起来。比如第二层记录了外部扫描的封禁,第四层的 fail2ban 记录了 SSH 爆破,第五层的应用日志记录了登录失败——这三者如果指向同一个 IP,说明多层防护同时在起作用,是好信号。如果它们的日志互相矛盾(比如防火墙显示放行但 SSH 日志里没有对应记录),说明某一层的配置没生效。
# 交叉验证:把三个层面的日志按时间对齐看
sudo journalctl -u ssh --since "1 hour ago" | grep -i "fail\|invalid" | tail -20
sudo journalctl -u ufw --since "1 hour ago" | tail -20
sudo tail -50 /var/log/nginx/access.log | grep -E " 40[13] "
二、第一层:商家与物理层,你的后路在这里

这一层不在你的服务器里,而在商家那边,但它决定了所有其他层的失败能不能被救回来。核心只有三个能力:快照、救援模式、以及 IP 资源政策。
快照是你配置改错时的后悔药。没有快照,改坏了 SSH 配置就只能提工单等人工重装,有数据的业务直接停机。购买前先确认控制台里有没有快照功能、快照保留几个、创建快照是否额外收费。
救援模式(也叫 VNC、Console、IPMI)是绕过网络直接登录系统的入口。配置防火墙把自己锁在外面时,它是唯一能进机器的路。有些商家只提供网页控制台(VNC),有些提供 IPMI 这种能直接操作操作系统的,后者更可靠。
IP 资源政策影响的是后续的架构选择:能不能附加 IP、能不能换 IP、IP 是原生还是广播。这一项在需要做多节点、灰度切换、或者 IP 被拉黑需要更换时才会用到。
# 本机虽然无法生成快照,但可以先把当前状态导出一份作为等价备份
tar czf /tmp/system-state-$(date +%Y%m%d).tar.gz \
/etc /var/www /root/.ssh 2>/dev/null
ls -lh /tmp/system-state-*.tar.gz
在广告库里能查到结构化套餐的商家,配置颗粒度差别很大,值得逐个对比。justg 的 RosCloud 系列是月付制,从 19.99 美元起逐档递增,每档带 1 个 IPv4,月付让你可以随时换机器重试;sixtynet 的洛杉矶系列是年付制,200 美元到 1600 美元不等,端口给到 2000 到 10000 Mbps,流量 5000 到 40000 GB;云途的香港与欧洲节点系列流量超额有明确的续费价格档位,最低一档 200 美元,说明其计费规则是条款化而非临时决定。itldc 在产品说明里标注了覆盖 20 个全球机房,具体位置、价格与售后需结合商品页人工核对;zenlayer 定位是面向 AI 的分布式云,在全球多地设有节点;spartanhost、tudcloud 则把 DDoS 防护 VPS 作为主要产品线。具体报价与库存以官网当日报价为准。
# 用测试机验证商家给你的后路是否真的能用(关键:别等到出事才试)
# 1. 创建快照 → 确认控制台可见
# 2. 重启机器 → 确认能从网页控制台登录
# 3. 在网页控制台里执行:ip a 看网络配置是否正常
这一层最容易被跳过,因为它是唯一一层你不在服务器里做的事。但它的价值最大——它决定了你在第三层和第四层敢做多激进的改动。
采购环节就要问清三件事:快照是否免费、保留多久、能否开机时挂载为额外磁盘。第三点尤其有用:如果快照能挂载成一块盘,你可以在上面直接读取旧数据做取证,不需要为了看数据而回滚生产机器。另外还要问救援模式是不是真的能用——有的商家的网页控制台只是个壳,只能看屏幕不能输入,得确认能不能输入命令。
同样重要的是机房的地理位置和线路属性。这一条在第七层之前都不显眼,但它决定了第二层的延迟指标能不能达标。如果你的用户在国内,而机器在洛杉矶,那么任何加固都改变不了物理延迟,你只能靠第二层的 CDN 和第四层的反向代理来缓解。这也是为什么第一层必须先定:它决定了后面所有层的效果上限。
# 确认你能连到机房,看路由路径
traceroute -n 你的目标机房IP | head -20
# 看延迟基线
mtr -r -c 50 你的目标机房IP
还有个细节:确认你的机器有没有独立的公网 IPv4。有些套餐给的是共享 IP(多个租户共用一个出口),这会带来两个问题——端口扫描时你会看到别人的服务,而且你的 IP 被拉黑时其他租户也会受影响。买之前问清楚是独享还是共享。
三、第二层:网络层,把暴露面收到最小

这一层管的是「哪些东西能被从外面碰到」。核心手段是三道闸:云安全组、系统防火墙、应用层限流。
云安全组在网络最外层,优先级最高;系统防火墙(ufw/firewalld)在内层;应用层限流是最内层。三道闸的顺序决定了谁先生效。原则是:外层先配、内层后配;先放行、再收紧。
# 外层:云控制台的安全组只放行 22/80/443
# 内层:系统防火墙按同样端口配置
MY_IP=$(echo $SSH_CLIENT | awk '{print $1}')
ufw allow from $MY_IP to any port 22 proto tcp
ufw allow 80/tcp
ufw allow 443/tcp
ufw default deny incoming
ufw default allow outgoing
ufw --force enable
ufw status verbose
# 验证:从外部机器扫自己的 IP
nmap -Pn -sT --min-rate 2000 你的VPS公网IP
验收标准是一个数字:外部扫描到的开放端口数量,应当等于业务必需端口数加一到两个管理端口。 只跑一个网站的话,期望值就是 3——22、80、443。实测发现 3306、6379 开着,立刻处理。
这一层还有两件事经常被跳过。第一是限流。安全组和防火墙只管「谁能连」,不管「连多快」。在应用层加限流,才能挡住暴力爆破和爬虫。Nginx 的 limit_req_zone 就是干这个的:
# 后台登录接口单独限流:每 IP 每分钟 10 次
limit_req_zone $binary_remote_addr zone=login:10m rate=10r/m;
location /wp-login.php {
limit_req zone=login burst=5 nodelay;
proxy_pass http://backend;
}
第二是隐藏版本信息,让扫描器的指纹匹配落空。nginx 用 server_tokens off;,Apache 用 ServerTokens Prod,PHP 用 expose_php = Off。
curl -sI https://你的域名 | grep -Ei "server|x-powered-by|x-version"
# 期望:看不到具体版本号
这一层还有第三件事常被忽略:IPv6。ufw 和 firewalld 默认同时管 IPv4 和 IPv6,但很多云安全组只配了 IPv4 规则,IPv6 地址等于开了一扇没人管的门。检查一下:
# 有没有全局 IPv6 地址
ip -6 addr show scope global
# 防火墙有没有纳管 IPv6
ufw status verbose | grep -i ipv6
# 从外部扫 IPv6 端口
nmap -Pn -6 -p 22,80,443,3306,6379 你的IPv6地址
四、第三层:主机系统层,补丁与最小化

这一层防的是「已经在机器上的代码」被利用:已知漏洞被扫描器匹配、权限配置错误导致提权、被植入的后门长期潜伏。
两个动作:打补丁和减服务。
补丁的节奏要分成安全更新和大版本升级两条线。安全更新自动化,大版本升级手动。Debian/Ubuntu 上用 unattended-upgrades 做前者。
sudo apt update && sudo apt install -y unattended-upgrades
sudo dpkg-reconfigure -plow unattended-upgrades
sudo tee /etc/apt/apt.conf.d/20auto-upgrades >/dev/null <<'EOF'
APT::Periodic::Update-Package-Lists "1";
APT::Periodic::Unattended-Upgrade "1";
APT::Periodic::AutocleanInterval "7";
EOF
# 让服务在更新后立刻重启生效,而不是等下次手动重启
sudo sed -i 's/^#*NEEDRESTART_MODE=.*/NEEDRESTART_MODE=a/' /etc/needrestart/restart.conf
减服务的意思是关掉一切不需要的进程。每一个运行中的服务都是一个潜在的被攻击面,而且不占端口的服务同样会被利用——本地提权漏洞的利用链往往需要一个本地服务配合。
# 列出所有运行中的服务
systemctl list-units --type=service --state=running
# 找出开机自启但从没被调用过的服务
systemctl list-unit-files --state=enabled | grep service | wc -l
# 检查是否有异常端口监听
ss -tulnp state listening | grep -v "127.0.0.1\|::1"
审计工具能补上手工检查的盲区。lynis 会给出一份整体的安全评分,指出缺失项;auditd 会记录所有系统调用,事后追溯入侵路径时非常有用。
# 跑一次 lynis 安全审计
sudo apt install -y lynis
sudo lynis audit system --quick
# 开启 auditd 记录敏感操作
sudo systemctl enable --now auditd
sudo auditctl -w /etc/passwd -p wa -k passwd_change
sudo auditctl -w /etc/ssh/sshd_config -p wa -k sshd_config
这一层最容易出的问题是只更新系统包,忘了手动装的东西。从第三方源装的 PHP、Node.js、数据库,各有各的更新节奏,apt 管不到它们。
# 检查 apt 之外装的东西
which -a node php python3 nginx mysql 2>/dev/null
# 每个都要单独查版本和更新方式
还有一件小事值得做:关掉不用的软件源。你装系统时选了很多组件,其中一些源从来不用,却会持续拉取更新元数据、增加攻击面,也拖慢 apt。用 apt autoremove 清理掉不再需要的包。
# 列出自动安装且不再被依赖的包
apt autoremove --dry-run
# 清理
sudo apt autoremove --purge
五、第四层:身份认证层,让猜密码这条路不存在

这一层是性价比最高的。攻击者拿到你的 IP 后,第一件事是尝试 SSH 登录爆破。认证层做扎实,这条路直接消失。
三个动作:密钥登录替代密码、禁用 root 直登、限制可登录账号。
cat >> /etc/ssh/sshd_config <<'EOF'
PermitRootLogin no
PasswordAuthentication no
PubkeyAuthentication yes
MaxAuthTries 3
LoginGraceTime 30
AllowUsers deploy
EOF
sshd -t && systemctl reload sshd
# 验证生效:确认 passwordauthentication 为 no
sudo sshd -T | grep -Ei "port|passwordauthentication|permitrootlogin|allowusers|maxauthtries"
关键是先确认密钥能登进去,再关密码。顺序反了就是自锁。
# 本机生成密钥
ssh-keygen -t ed25519 -C "deploy@vps"
ssh-copy-id deploy@服务器IP
# 另开终端测试
ssh deploy@服务器IP "echo 密钥登录成功"
MaxAuthTries 3 加上 LoginGraceTime 30 让单个连接最多试三次密码、每次连接只给 30 秒。再配合 fail2ban 的自动封禁,爆破路径基本被完全堵死。
sudo apt install -y fail2ban
cat > /etc/fail2ban/jail.local <<'EOF'
[DEFAULT]
bantime = 3600
findtime = 600
maxretry = 5
bantime.increment = true
bantime.factor = 2
ignoreip = 127.0.0.1/8 ::1
[sshd]
enabled = true
EOF
sudo systemctl restart fail2ban
fail2ban-client status sshd
管理面板这类 Web 登录,再加一层双因素认证。TOTP 是最通用的一种,密钥存在密码管理器或者手机的认证器里。
# 用 oathtool 生成 TOTP 密钥,扫码绑定
pip install oathtool
oathtool --generate
# 验证
oathtool --totp -v YOUR_BASE32_SECRET
这一层还有两件事值得单独讲。
第一,权限分离。 不要用 root 跑业务应用。给应用建一个专用的系统账号,只给它需要的文件权限。这一条能挡住一类很常见的提权路径:应用有漏洞被拿下之后,攻击者拿到的是低权限账号,横向移动和持久化都更难。
# 为应用建独立账号并限制权限
sudo useradd -r -s /usr/sbin/nologin appsvc
sudo chown -R appsvc:appsvc /var/www/你的应用
sudo chmod 750 /var/www/你的应用
第二,密钥要能轮换。 密钥用久了,私钥泄露的风险会累积。设一个轮换周期(比如每半年),或者至少在换机器、换人员时轮换一次。同时保留至少两把有效密钥,轮换时先加新的、验证能登进去、再删旧的。
第三,别把「限制来源 IP」当成唯一防线。 这个策略在你换网络、换 IP、紧急救援时会把你挡在外面。正确做法是:密钥登录是主防线,来源 IP 限制是加分项,fail2ban 是兜底。三者叠加时,任何一个失效都不会导致失联。
# 确认三层都在生效
sudo sshd -T | grep -Ei "passwordauthentication|permitrootlogin|allowusers|maxauthtries"
sudo fail2ban-client status sshd
sudo ufw status verbose | grep -A2 "22/tcp"
六、第五层:应用与 Web 层,最容易被攻击的一层

前面五层都在保护「服务器」,这一层保护的是「你的业务代码」。绝大多数实际入侵事件发生在这一层,而不是 SSH。
常见攻击面有五个:注入、XSS、文件上传、越权、CSRF。对应的防护手段:
注入靠参数化查询,不靠手动转义。XSS靠输出编码加 CSP 头。文件上传靠校验类型、限制大小、存到不可执行目录。越权靠在服务端每次查询都带上归属判断,不能信前端传来的 ID。CSRF靠 token。
# 安全响应头:这一组能挡掉相当一部分通用攻击
add_header X-Content-Type-Options "nosniff" always;
add_header X-Frame-Options "SAMEORIGIN" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
add_header Content-Security-Policy "default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; frame-ancestors 'self'" always;
add_header Permissions-Policy "geolocation=(), microphone=(), camera=()" always;
server_tokens off;
上传目录不可执行这一条值得单说。很多站被拿下不是因为代码有洞,而是因为能上传 PHP 文件然后访问它。把上传目录的执行权限去掉,这条链就断了。
location /uploads/ {
location ~ \.(php|py|sh|pl)$ { deny all; }
expires 30d;
}
应用层还有两件事:依赖更新和错误信息不外泄。生产环境关掉调试模式,异常页面不显示堆栈,因为堆栈里的文件路径和类名是攻击者最好的地图。
# 确认生产环境关闭调试
grep -rn "debug.*true\|DEBUG *= *True\|display_errors.*On" /var/www/ 2>/dev/null | head -10
# nginx 关掉错误页里的版本信息
# server_tokens off; 已在上方配置
第五层还有三个具体的点经常被漏掉。
第一,管理后台的路径与认证。 /wp-admin/、/admin/、/login 这些路径是公开已知的,扫描器会直接拿字典去撞。加上 HTTP 基本认证或者改路径,能把自动化爆破挡在门外。
第二,API 的越权检查。 很多接口只在前端隐藏了按钮,后端却没做归属判断——把 URL 里的 ID 改成别人的就能读到数据。这类漏洞是逻辑漏洞,工具扫不出来,只能靠人工审查。
# 找出所有接受用户 ID 参数的接口,人工核对是否有归属校验
grep -rn "request.GET\|request.POST\|\$_GET\|\$_POST" /var/www/ 2>/dev/null | grep -i "id\|uid\|user" | head -20
第三,依赖组件的漏洞。 用第三方库的时候,库本身的漏洞就是你的漏洞。PHP 的 composer audit、Node 的 npm audit 都能扫出已知漏洞。
cd /var/www/你的应用
composer audit 2>/dev/null | tail -20
npm audit --production 2>/dev/null | tail -20
七、第六层:容器与编排层,Docker 特有的坑

用 Docker 之后多了一层,也多了几个特有的坑。
坑一:端口映射暴露。 -p 6379:6379 直接开在公网。正确写法是 -p 127.0.0.1:6379:6379。
坑二:Docker 绕过 ufw。 Docker 启动时直接改写 iptables 的 DOCKER 链,把容器端口插到防火墙规则之前,ufw 的默认拒绝对容器端口无效。要封就得在 DOCKER-USER 链加规则。
# 找出所有映射到 0.0.0.0 的容器端口
docker ps --filter publish=0.0.0.0 --format "{{.Names}} -> {{.Ports}}"
# 在 DOCKER-USER 链里封掉
iptables -I DOCKER-USER -i eth0 -p tcp --dport 6379 -j DROP
iptables -I DOCKER-USER -i eth0 -p tcp --dport 3306 -j DROP
坑三:以 root 跑容器。 容器内的 root 如果有漏洞逃逸出来,拿到的是宿主机的 root。正确做法是用非 root 用户跑。
# Dockerfile:建一个非 root 用户
RUN adduser --disabled-password --gecos "" appuser
USER appuser
WORKDIR /app
COPY --chown=appuser:appuser . /app
坑四:镜像来源不明。 从 Docker Hub 拉一个几千 star 的镜像,镜像里可能已经被塞了东西。生产环境要用可信镜像,或者自己 build。
坑五:挂载过于宽泛。 挂载 / 或 /etc 进容器,等于把宿主机交出去。要精确挂载具体路径。
# 检查容器的挂载与权限
docker inspect --format '{{.Name}} user={{.Config.User}} mounts={{.Mounts}}' $(docker ps -q)
# 找出以 root 运行的容器
docker ps -q | xargs -r docker inspect --format '{{.Name}}: {{.Config.User}}' | grep -v "user=[a-z]"
# 检查镜像来源与更新时间
docker images --format "{{.Repository}}:{{.Tag}} {{.CreatedSince}}"
第六层还有一个容器特有的问题:secrets 不该放在环境变量或镜像里。环境变量在 docker inspect 里是明文可见的,镜像层里的文件也会跟着镜像分发。用 Docker secrets 或者挂载只读文件的方式提供凭据。
# 检查是否把敏感信息放进了环境变量
docker inspect --format '{{range .Config.Env}}{{println .}}{{end}}' 容器名 | grep -Ei "password|secret|token|key"
# 正确的做法:挂载只读文件
docker run -v /etc/你的应用/secret.env:/run/secrets/db.env:ro 你的镜像
最后一个坑:容器日志默认存放在宿主机磁盘上且无上限。写日志的容器跑久了能把根分区撑满,导致整台机器不可用。给每个容器加日志轮转限制。
docker run --log-opt max-size=10m --log-opt max-file=3 你的镜像
八、第七层:数据与备份层,最后的保险

前六层防的是「攻击发生」,这一层处理「攻击已经发生」。它挡不住入侵,但决定你能不能在几小时内恢复而不是几周。
备份要满足三个硬条件:异地、定期、已验证。三个缺一个,备份就等于没有。
异地指的是不在同一台服务器上,甚至不在同一个服务商。勒索软件和挖矿程序拿到 root 之后,第一件事就是找备份并删掉。放在同一台机器的备份会被一起清理。
定期指自动执行。手动备份的执行频率等于你的手动频率,通常等于没有。
已验证指你真的恢复过。没恢复过的备份,你不知道它是不是完整的。
# 备份脚本:数据库 + 站点文件 + 配置
cat > /usr/local/bin/backup.sh <<'EOF'
#!/bin/bash
set -e
DEST=/backup/$(date +%Y%m%d-%H%M)
mkdir -p $DEST
tar czf $DEST/www.tar.gz /var/www
tar czf $DEST/etc.tar.gz /etc
mysqldump --single-transaction --routines 数据库名 | gzip > $DEST/db.sql.gz
sha256sum $DEST/* > $DEST/SHA256SUMS
find /backup -maxdepth 1 -type d -mtime +14 -exec rm -rf {} +
EOF
chmod +x /usr/local/bin/backup.sh
echo "10 3 * * * root /usr/local/bin/backup.sh" >> /etc/crontab
# 同步到异地
rsync -avz --delete /backup/ 备份账号@备份服务器:/backup路径/
sha256sum 那一步值得加。校验和能在恢复前就告诉你备份有没有损坏或者被篡改。
恢复演练是这一层的核心。挑一台测试机,把备份拉过去解开,确认文件完整、数据库能导入、应用能起来、数据量对得上。
# 演练:解开备份并校验完整性
cd /tmp/restore-test && tar xzf /备份路径/www.tar.gz
sha256sum -c /备份路径/SHA256SUMS
gunzip < db.sql.gz | head -50
除了备份,这一层还要覆盖两件事:日志集中化(日志实时送到另一台机器,防止被删)和密钥分离(数据库密码、API 密钥不写在代码里,放环境变量或者密钥管理服务,代码进仓库时用 .gitignore 排除)。
# rsyslog 转发到远程日志机
echo '*.* @日志服务器IP:514' > /etc/rsyslog.d/forward.conf
systemctl restart rsyslog
第七层还有一件事经常被忽略:密钥本身也要备份和轮换。数据库密码、API 密钥、支付接口的私钥,这些东西如果只存在于某一台机器上,那台机器重装就全没了。密钥应该放在密码管理器里,有备份、有轮换周期、有访问记录。
同理,代码本身也要在版本控制里。服务器上的代码如果是手工改的、没有进 Git,那么机器出事之后你既不知道改了什么,也没法回滚。标准做法是:代码在 Git 里,服务器上只跑 git pull 部署,配置和密钥单独管理。
# 检查部署方式:是不是有版本控制
cd /var/www/你的应用 && git status 2>&1 | head -5
git log --oneline -5 2>/dev/null
# 检查敏感文件有没有被提交进仓库
grep -rn "password\|secret\|api_key" .gitignore 2>/dev/null
九、七层自检表:从下往上逐层过

把这七层压成一张可以直接勾的表。每一条都给了验证命令,跑完就知道自己缺什么。
| 层 | 检查项 | 验证命令或方法 | 通过标准 | |
|---|---|---|---|---|
| 一 商家 | 快照可用 | 控制台创建一次快照 | 能创建并看到 | |
| 一 商家 | 救援模式可用 | 重启后从网页控制台登录 | 能进系统 | |
| 二 网络 | 开放端口数 | 外部 nmap -Pn -sT 你的IP |
只剩 22/80/443 | |
| 二 网络 | 限流生效 | 压测登录接口 | 超出即返回 429 | |
| 二 网络 | 版本隐藏 | curl -sI 域名 |
无版本号 | |
| 三 系统 | 安全更新自动 | systemctl status unattended-upgrades |
active | |
| 三 系统 | 无多余服务 | systemctl list-units --type=service --state=running |
逐项确认 | |
| 三 系统 | 关键文件审计 | lynis audit system --quick |
无高危项 | |
| 四 认证 | 密码登录已禁 | `sshd -T \ | grep passwordauth` | no |
| 四 认证 | root 已禁 | `sshd -T \ | grep permitrootlogin` | no |
| 四 认证 | 自动封禁生效 | fail2ban-client status sshd |
已列出被封 IP | |
| 五 应用 | 安全响应头 | curl -sI 域名 |
五个头齐全 | |
| 五 应用 | 上传目录不可执行 | 上传测试文件访问 | 返回 403 | |
| 六 容器 | 无 0.0.0.0 映射 | docker ps --filter publish=0.0.0.0 |
空或已整改 | |
| 六 容器 | 容器非 root | docker inspect 看 User |
非空且非 root | |
| 七 数据 | 异地备份存在 | 登录备份机 ls |
有今天的目录 | |
| 七 数据 | 恢复演练 | 测试机解开校验 | sha256 全部 OK | |
| 七 数据 | 日志已外发 | 远程机 tail 日志 |
能看到实时日志 |
从上往下查还是从下往上查? 查问题的时候从上往下(先看商家能力,再看网络),修问题的时候从下往上(先收敛再加固)。这张表建议每周过一遍,不需要全跑,抽查几项保持手感就行。
怎么知道这套防护真的有效? 最直接的办法是自己攻自己的机器。在一台外部机器上,对自己的 VPS 做一次端口扫描和 Web 漏洞扫描,看看能挖出多少东西。挖出来的东西就是你防护体系的实际水位。
# 外部机器上执行:端口扫描
nmap -Pn -sV -p- --min-rate 2000 你的VPS公网IP
# Web 层漏洞扫描
nikto -h https://你的域名
# 检查常见后台路径
for p in admin wp-admin login phpmyadmin manager; do
code=$(curl -s -o /dev/null -w "%{http_code}" https://你的域名/$p)
echo "$p -> $code"
done
扫出来的东西和自检表对照,缺哪一项就补哪一项。这比任何清单都有效,因为清单是别人写的,你的机器是独一无二的。
另外可以配一条异常告警:定期从外部扫一次,发现开放的端口数量超过预期就发通知。这样哪天你不小心开了一个端口,机器会主动告诉你。
十、搭建顺序与资源分配建议

七层的正确搭建顺序不是七层自检表的顺序。实际搭建应该这样安排。
第一天(1 小时):第一层到第四层。确认快照和救援模式可用 → 改密码建普通用户 → 装密钥关密码 → 禁 root → 装 fail2ban → 配防火墙放行三个端口 → 做一次外部扫描确认。这套做完,机器的「外壳」已经成型。
第二天(1 小时):第五层和第六层。上线前把安全响应头配齐、上传目录设为不可执行、确认生产环境关闭调试。如果用 Docker,把所有端口映射改成 127.0.0.1,容器改用非 root 用户。
第三天(1 小时):第七层。配自动备份、推异地、做一次恢复演练、配日志外发。到这一步整套防护才算闭环。
之后每周:过一遍自检表的抽检项。每月:更新系统、看 fail2ban 和认证日志里有没有异常、确认备份仍然在增长。每季度:做一次完整恢复演练、复查账号清单和开放端口。
资源上怎么分配。如果你的机器只有 1 GB 内存、1 核,第七层和第六层的完整方案会有点吃力——Docker 加监控 agent 本身就要吃掉几百 MB 内存。这种情况下的取舍是:保留第一到第四层和第五层的核心(安全头 + 上传目录不可执行),第七层的备份脚本改成纯 shell + cron 而不装额外工具,第六层如果业务量小就直接不用 Docker,原生 systemd 部署反而更省资源。
如果你的机器配置宽裕(比如 8 核 16 GB 这一档),那七层可以全上,还能加更多监控组件。广告库里能查到结构化套餐的商家在这类需求上选择不少:sixtynet 的 LAX-MEDIUM 是 8 核 8 GB 内存、160 GB 硬盘、10000 Mbps 端口、20000 GB 月流量,年付 800 美元,折合每月 66.67 美元;LAX-LARGE 是 8 核 16 GB 内存、320 GB 硬盘、40000 GB 月流量,年付 1600 美元;云途的 HK.DS.S 是 128 GB 内存、6000 GB 硬盘、2000 Mbps 端口、40000 GB 月流量,每月 800 美元,配的是 SAS HDD。具体报价与库存以官网当日报价为准。
选型时和安全直接相关的两项能力是:内存够不够跑全套组件(监控 agent 加日志收集加 Docker 管理至少要留 1 GB 余量)、快照是否可用(决定你敢不敢改配置)。第二个比第一个更重要。
按你的情况,下一步该看哪家
上面讲的是判断标准,但多数人最后还是想问一句「那我该买谁」。按你的实际情况对照下面几条,直接去看对应的机型页比继续比价更快:
- 主要访客在国内、在意打开速度:先确认回程线路,再谈配置。看 iwebfusion 当前机型与价格
- 跑游戏服或实时业务:看上行抖动与防御能力,普通套餐往往不达标。看 racknerd 当前机型与价格
- 只是开发测试、临时用:按小时或月付,用完就删,别买年付。看 cloudcone 当前机型与价格
价格与库存以商家页面当日显示为准,下单前建议先确认退款窗口与是否支持按月付费。
十一、常见问题

VPS服务器搭建7层防护图,具体是哪七层? 商家与物理层、网络层、主机系统层、身份认证层、应用与 Web 层、容器与编排层、数据与备份层。前四层防的是「有人打进来」,第五六层防的是「代码有洞」,第七层处理「已经被打进来」。
七层都要做吗?小机器做不了这么多。 1 GB 内存的机器优先做第一到第四层(这四层几乎不耗资源),第五层做安全响应头和上传目录限制,第六层不用 Docker 就跳过,第七层用 shell 脚本加 cron 而不是额外工具。资源不够时,砍的是第六层和监控组件,不能砍的是第一到第四层。
层次顺序重要吗? 搭建顺序重要,必须从第一层到第七层按顺序做,因为后一层依赖前一层的成果(比如第四层的密钥登录依赖第一层确认的救援模式作为后路)。但排查问题时从上往下查,修问题时从下往上修。
第几层性价比最高? 第四层身份认证层。改几个 SSH 配置项、生成一把密钥、装一个 fail2ban,一小时内完成,就能让 SSH 爆破这条最主要的入侵路径彻底消失。
七层都做了还会被攻击吗? 会,但概率和破坏程度完全不同。七层的目标是让「自动化扫描器」完全无法利用,让「定向攻击」的成本远高于收益,让「万一失守」有备份可恢复。安全是概率和成本的游戏,不是绝对保证。
怎么知道这套防护有没有用? 两个办法:自己从外部扫描和攻击自己的机器(用 nmap 扫端口、用 nikto 扫 Web 漏洞),或者用 lynis、openscap 跑一遍基线检查。前者更直观,后者更系统。
配置这么多不会把自己搞挂吗? 会,所以第一层的快照和救援模式是整个体系的地基。另外每改一层就做一次功能验证(网站能开、接口能调、数据库能连),把风险拆成七次小的,而不是攒成一次大的。
