VPS 安全加固清单:首次登录后的 12 个步骤

按顺序执行的 12 个加固步骤——密钥、默认拒绝防火墙、自动补丁、fail2ban、经演练的恢复——免 KYC Core VPS 年付每月仅 $4.80 起。
按顺序执行的 12 个加固步骤——密钥、默认拒绝防火墙、自动补丁、fail2ban、经演练的恢复——免 KYC Core VPS 年付每月仅 $4.80 起。
默认配置本身就是漏洞
要问什么才真正攻陷 VPS 服务器,答案平淡得让人尴尬:不是针对内核的零日漏洞,而是密码认证没关、root 密码没扛过一次自动化扫描。一台新拿到公网 IPv4 的机器,开机几分钟内就会遭到暴力破解扫描,而每一次尝试都在猜默认安装所接受的唯一凭据。下面的顺序正是为这种不对称而设——一个无聊的默认设置,能挡住的攻击比你事后安装的任何花哨工具都多。
这些扫描噪音背后的机制是经济逻辑。僵尸网络之所以持续扫描整个 IPv4 空间,是因为猜密码太便宜;任何让猜密码变贵的措施都能把僵尸网络过滤掉,而任何让它变得不可能的措施则能把一切过滤干净。仅密钥认证让猜密码从“昂贵”变成“不可能”,默认拒绝防火墙把大部分攻击面变得不可见,自动补丁则封住剩余的漏洞。这些都不复杂——难点在于执行顺序和坚持到底,而不是工具本身。
人们常见的顺序错误是:先装监控栈、加固 nginx、调优数据库——全部排在密钥配置之前。机器从镜像完成那一刻起就暴露在外,大约是付款后 60 seconds,扫描不会等你喝完咖啡才来。再精心打磨几周的应用层工作,也扛不住糟糕的第一小时,因为攻击者不会等你的路线图。
这份清单上的一切都能在头三十分钟内完成,而且步骤经过排序,每一步都在缩小下一步的风险面。哪怕你只做前两步——密钥和防火墙——也已经消除了真正让大多数服务器阵亡的故障模式。剩下的都是纵深,而纵深正是本页的主题;文末的回顾会把全部内容压缩成一段可直接运行的命令序列。
VPS $4.80* 起(年付期限),存储 1–5 TB NVMe 年付折合 $24/月起,带 IPMI 的独立服务器 $39.20/月起。加密货币账单,免 KYC。
立即启动先配密钥,再关上密码之门
第一步是添加你的 SSH 公钥并禁用 root 的密码认证——赶在任何其他操作接触网络之前。用 ssh-keygen -t ed25519 生成一对现代密钥,用 ssh-copy-id 或追加到 ~/.ssh/authorized_keys 的方式安装公钥,然后在 sshd_config(5) 中设置 PasswordAuthentication no 和 PermitRootLogin prohibit-password,并重载 sshd。从那一刻起,开机几分钟内就开始的流量就变成永远无害的噪音。
这里的机制是消除凭据而非保护凭据:仅密钥的服务器没有密码可猜,日志里每天出现的尝试就成了没有任何成功路径的噪音。RFC 4253 定义了密钥所依赖的传输协议;但实践要点更简单——密钥从不通过网络传输,所以网络上没有任何东西能截获它,日志里也没有任何东西能泄露它。同时创建一个用于日常工作的具名 sudo 用户,把 root 留给控制台和救援场景。
这一步的坑在于把自己锁在门外。重载 sshd 时保持托管面板的控制台开着,并在关闭第一个终端之前用第二个终端测试登录。面板控制台是那条带外通道,它能把一个 sshd 手误从“重装机器”变成“五分钟修复”,也正是这个失误可以挽回的原因——这是托管层的属性,而不是你配置的属性。
密钥管理的生命周期比初始配置更长:每人一把密钥,每个自动化账号一把,每把密钥都带上标明归属者的注释,任何密钥不在两台笔记本之间共享。增加队友只是往 authorized_keys 里追加一行,而不是一场仪式;有人离职时,删掉对应的那一行就是完整的吊销。这个特性——具名密钥、具名用户、单行删除——正是第一天多花的 10 分钟在日后每次审计中都物有所值的原因。
通过隧道而非直接暴露 22/tcp 来访问机器,是这一步的升级版——WireGuard 指南从头到尾讲了一遍。无论选哪种方式,身份问题就算解决了;下一个攻击面是机器对陌生人应答的一切,而这份清单比大多数人真正跑一次审计前想象的要短。
默认拒绝是一份清单,不是一台设备
防火墙不是你安装的产品,而是你维护的策略。把它设为默认拒绝,只放行确需联网的内容:22/tcp(或你改过的端口)、web 的 80/tcp 和 443/tcp,以及每个真正需要联网的运行中服务一个端口。nftables wiki 有十分钟入门语法,而 nft list ruleset 能显示实际生效的规则——那有时和你以为的不一致,而这两者之间的差距正是事故滋生之地。
放行之前先审计:ss -tulpn(ss(8))列出每一个监听中的套接字及其背后的进程。任何绑定在 0.0.0.0 上而你说不出名字的东西,要么是你忘记的服务,要么是你从未有意安装的服务——两种答案都需要处理,只是其中一种更令人安心。管理界面和数据库绑定到 127.0.0.1,或藏进上一节的隧道之后;任何公开应答的东西都必须有一个你能脱口而出的存在理由。
默认拒绝的典型翻车点:漏掉已建立连接(established)的规则,机器能收到 SYN 却永远无法完成握手——直到有人逐行读完规则手册,才能结束那令人困惑的五分钟。第二个经典案例:面板防火墙和虚拟机内防火墙意见不一致,而更严格的一方悄悄胜出。当两层规则冲突时,你要在事故发生之前、而不是事故之中弄清楚哪一层说了算,所以选定一层来维护,并把另一层记录为只读。
一套你能背下来的极简规则,胜过一套你凌晨三点无法调试的聪明规则——这是设计约束,不是认输。网络攻击面收敛之后,剩余的噪音就是仍然穿透到你选择暴露的服务上的那部分——这更多是个日志问题而非安全问题,而日志问题有便宜的解法。
让暴力破解噪音变得可读
防火墙之后,任何公网机器的认证日志一小时内就会塞满失败尝试。fail2ban 就是为了让这些可读而生:它盯着 /var/log/auth.log,按来源统计失败次数,并指示防火墙在一段时间内丢弃惯犯。装上它,然后用 fail2ban-client status sshd 看着封禁名单增长——这是整条链路端到端有效的证明,而且当你发现互联网上有多少流量就是这样时,它还是一种小小的日常满足感。
这里的机制是骚扰定价,而不是预防:仅密钥认证已经让猜密码不可能,所以 fail2ban 的贡献是日志卫生和带宽节省,严格来说不算安全。把 bantime 和 findtime 设得有点牙口——一小时,而不是五分钟——并把你自己的地址加白名单,这样连续三次手误粘贴错密钥就不会在最糟糕的时刻把你锁在自己的机器之外。
过滤器在值得信任之前应该做一次冒烟测试:用 fail2ban-regex 跑一批真实日志样本,确认模式匹配你的发行版实际写入的格式——不同版本各有差异。一个匹配 0 行的 jail 会无声地永远运行下去,提供盾牌的安心感和漏勺的覆盖率。花两分钟用正则工具,就能回答仪表盘永远回答不了的问题。
常见的翻车点:bantime 短到同一台主机立刻回归;给机器上根本不存在的服务启用了 jail;还有那个永恒的经典——通过一个 NAT 边缘把自己身后的所有人一起封了。当整套 jail 框架对机器来说过于隆重时,sshguard 是更轻量的替代品;但无论哪个工具,都胜过第三个选项——出于义务每周阅读成千上万条登录失败日志。
身份、攻击面、噪音都处理完之后,这台机器已经比互联网上的绝大多数服务器更难进入了。剩下的风险运行在一个你无法很好掌控的时钟上:软件本身,无论是否有人攻击它都会老化。这就是补丁问题,而它的解法是把你的日历从流程中彻底移除。
没有日历的补丁
你的发行版每发布一个 CVE,都是一个你迟早会错过的提醒。无人值守升级消除了这个“错过”:在 Debian 系系统上,apt install unattended-upgrades 会启用每日自动运行,自动拉取安全补丁——Debian wiki 记录了确切的行为——而 /etc/apt/apt.conf.d/50unattended-upgrades 文件决定什么算安全更新。首次启用之后,机器会按你永远不必记住的时间表自行打补丁。
这个机制有一个自动化无法跨越的缺口:内核。打了补丁的内核会留在内存里等待重启,而 /var/run/reboot-required 就是提示有待重启的标志——每周检查一次,或者按你自选的固定周期重启。Debian 安全门户是安全公告的来源;机器不需要你去读它们,只需要偶尔重启,这是你能买到的最便宜的安全人力。
验证一次自动化,而不是默认它在工作:unattended-upgrade --dry-run --debug 会显示下一次运行将拉取什么,而它实际做了什么的历史记录累积在 /var/log/unattended-upgrades/ 下,可与 50unattended-upgrades 中的设置对照。你从未亲眼看过运行的自动化只是一个勾选项;你看过一次、且有日志可对照的自动化才是真正的控制——而且在发行版每次小版本发布后复查一遍,能让它保持诚实。
常见翻车点:混用软件源直到 apt 出现损坏的包;在大改动期间“临时”停用无人值守服务却再也不启用;还有 EOL 版本——停止支持的发行版不再接收自动化所读取的安全源,机器看上去仍在维护,而补丁早已悄然停止。二阶翻车:在大白天重启繁忙服务,而放在深夜重启用户根本察觉不到。
补丁保护的是你运行的软件;接下来两步保护的是它下面的数据——一份副本放在别处,一份副本没有密钥就无法读取。两者之中,人们跳过的是前者,而决定糟糕的一天究竟变成一场不便还是一次终结的,恰恰是前者,所以先做它。
没恢复过的备份只是传闻
把快照调度成变更前的回滚手段,再在另一台机器的不同存储上放一份异地副本,然后——这一步区分了备份和希望——往一个临时目录跑一次恢复,证明整条链路有效。rsync -a --delete 同步到第二位置,加上周期性全量快照,能覆盖大多数小型服务器;而 crontab -e(crontab(5))无需安装任何新东西就能把两者都调度起来。
这里的机制是爆炸半径控制。一台被攻陷或损坏但恢复流程经过测试的机器,是一次 15-minute 的事故;同一台机器若备份从未测试,则可能是全损,因为未经测试的备份总以最“友好”的方式失效——任务在三月份悄悄停了,目标盘在六月份满了,加密密钥就躺在它本该保护的那块盘上。这些失效在需要副本的那一天之前全都不可见,这正是演练不可省略的原因。
验证让闭环完成:每次演练之后,把恢复出来的目录树与预期对比,并记录整个流程耗时,因为恢复时长这个数字,是未来的你在 3 a.m. 真正需要的那个。一个不知道恢复时长的备份,是一份缺了核心参数的方案。把这个数字写在调度表旁边,每季度用同一套流程刷新,让方案和它的数字一起老化,而不是各自漂移。
备份方案的常见翻车点:所有东西都活在同一台物理机上(快照不是备份);异地副本的凭据放在攻击者能读到的地方;以及从未演练过哪怕一次的恢复。季度是演练的诚实节奏——把它放进日历、挨着重启检查项,并把跳过一个季度视为一次检查失败,而不是一次延期。
恢复还框定了自动化无法预防的失效模式的损害:操作失误——这才是生产数据的真正主要死因。最后一层防御再次改变赌局:没有密钥就无法读取的数据,是任何被偷走的磁盘都无法交出的数据,无论谁把它带出大楼。
加密磁盘,开机后再解锁
把敏感的静态数据放进一个开机后才打开的 LUKS 容器,那么断电状态下磁盘被物理窃取或被整盘镜像时,得到的是密文而不是你的数据库。cryptsetup 项目维护着这套工具:cryptsetup luksFormat 构建容器,/etc/crypttab 在开机时声明它,cryptsetup luksOpen 把它挂起来。整套模式就是一段配置加一个口令,它把“磁盘被偷”从事故变成了一件无所谓的小事。
无头(headless)问题才是真正的设计约束:开机时输入的口令需要有地方可输。在 dedicated 档位上,IPMI 给了你那块控制台——远程 KVM、虚拟介质,一应俱全——这正是加密 dedicated 裸机如此简单的原因:租一台 Forge,牌价 $49/mo,年付为 $39.20/mo,解锁只是每次重启后的一次远程控制台会话,而机器关机时,那 2 x 1 TB 的 NVMe 就静静躺在加密之后无法读取。在 VPS 上,服务商控制台扮演同样角色,只是带宽小一些。
像保护数据一样保护 LUKS 头部:cryptsetup luksHeaderBackup 写出的那个小文件能在容器损坏时救活它,而头部和口令双双丢失则会让对话永久终结。把这份备份存在机器之外,并遵循与口令本身相同的保管规则。两件东西、2 个位置,加密层就变得无聊了——而这正是本清单其余部分追求的那种无聊。
常见翻车点:等机密已经在未加密盘上落过脚之后才启用加密——想保险就得轮转数据或重装镜像;swap 留在容器之外;还有口令管理。一个没人能找回来的口令,会在下一次断电循环时把安全特性变成数据丢失,所以对任何重要的东西来说双人保管并不夸张,而写在同一块盘上的口令根本不叫保管。
磁盘锁好之后,剩下的攻击面根本不在机器上:而是那块能重置机器、修改其 DNS、读取其流量元数据的面板。世上最强的 sshd_config 也扛不住一个薄弱的托管账号——这正是下一节的主题。
面板也是攻击面
托管面板能重置机器、修改 DNS,因此无论你的虚拟机多么干净,它都是攻击面。创建账号当天就在面板上启用 2FA,并用对待 root 同样的纪律对待它的凭据。这里的免 KYC 账号模式——一个令牌,或一个邮箱加 12-character 密码——把整个身份重担压在那唯一一串凭据上;这是“令牌加密码管理器”的理由,而不是反对这个模式本身的理由。
这里的机制是权限集中。任何持有面板权限的人都能重建虚拟机(你的 LUKS 口令能幸存,运行状态不能)、改走它的 DNS、并读取最多保留 24h 的连接元数据。这比一把被偷的 SSH 密钥的权限更大,而且更容易被钓鱼——因为邮件到的时候看起来像账单问题而非安全事件。这正是第二因素必须落在面板账号上、而不只是落在机器上的原因。
恢复路径值得和登录路径同等审计:哪些邮箱能重置面板密码,而这些邮箱自己有没有第二因素?一个只保存在密码管理器中的令牌——管理器本身开着 2FA、抽屉里留一份纸质副本——能在那些靠邮件重置链接的方案全军覆没的场景中幸存。把这条链条画一次;最薄弱的一环几乎总是那个没人记得面板也能触达的邮箱。
常见翻车点:团队共用面板登录;因为“虚拟机已经加固了”而不开 2FA;恢复邮箱本身没有第二因素。每当人员名单变动时复查面板权限——离职时刻正是这一层在现实中失守的时刻,而如果你在离职之前而不是之后做审计,整个过程只要五分钟。
面板、密钥、防火墙、补丁、备份、磁盘:六层,全都属于你,没有一层高深莫测。第七个问题——服务器要不要装杀毒软件——对服务器来说答案真正反直觉,因为基础操作系统几乎从来不是那种重要的感染路径,而弄清扫描真正有价值的地方,会改变你部署它的目的。
扫描你接收的,而不是你对外提供的
Linux 服务器基础系统上的杀毒软件大多是做戏:发行版仓库对软件包有签名,而服务器常见的感染路径不是路过的二进制,而是你从别人那里接收的内容。扫描器真正挣饭碗的地方是上传、邮件队列和用户生成的文件——在接收目录上放一个 ClamAV 级别的扫描器,在上传时或按计划运行,就能在大多数廉价恶意载荷被执行之前截住它们的投递层。
这里的机制是划定范围。扫描跨越信任边界的东西——用户提交的文件、到达的邮件、解包的归档——是站得住脚的;每小时扫描操作系统只会找出有签名的二进制,浪费本可以留给业务负载的 CPU。如果这台机器接受别人客户稍后会下载的上传文件,那么接收扫描加从独立域名提供下载,就是两步真正重要的动作,而 freshclam 让 /var/lib/clamav 里的特征码保持最新,则是第一步有任何价值的前提。
部署位置遵循同样的边界逻辑:让接收目录与任何会执行的东西分开——把 /srv/uploads/ 以 noexec 挂载并从独立主机名提供,是最低要求。扫描找到载荷;隔离让它们无法动弹,于是迟到的检测也找不到任何可运行的东西。两者合起来覆盖了大多数廉价投递链——那种每天都来、而在挂载标志正确时执行次数为 0 的东西。
常见翻车点:没人查看的隔离区——没有响应的检测只是装饰;三月份就停止更新的特征码;以及把扫描当成那些无聊层面的替代品。没有任何扫描器能补偿密码认证或缺补丁的内核,而这份清单的顺序就是那句话的顺序。在搭建隔离区之前先定好谁来查看它,否则就别搭。
这就是全部的栈,而它会衰减:人员变动、服务新增、防火墙清单一个端口一个端口地长胖。加固不是一种状态,而是一张日程表——而这张日程表,就像操作顺序一样,才是值得写下来的部分。下一节就是那份记录,其后的回顾则是可运行的版本。
清单也会按日程衰减
第一到第九步在架构变更之前都是“设置即忘”;衰减藏在其余的检查里。每季度重新验证备份恢复;每上一个新服务就重读防火墙;人员名单每变动一次就复查面板权限。点一台 Core,牌价 $6/mo、年付 $4.80/mo,当一次性演练机,在动生产环境之前对着它把整份清单重跑一遍;一场每月只花 $4.80/mo 的演练才是真的会发生的演练——这就是全部诀窍。
顺手把配置本身也做快照:把 nft list ruleset 存进版本控制之下的文件,让每一次变更都成为可评审的 diff;没人能 diff 的规则集,也是没人能审计的规则集。同样的技巧也适用于 sshd 配置和 crontab。只活在内存里的配置会随机器一起消亡,而只要前后文件都在,每次事故都能缩成一次 5 分钟的对比。
衰减的机制是无证人盯着的漂移:五月新增的一个服务带着防火墙缺口、一条没人记得批准过的 sudo 规则、一个悄悄写满的备份目的地。什么都不会报警,因为什么都没坏——直到其中某一天变成了事故,届时三者都会在事后复盘里被发现,而在那之前一个也发现不了。季度演练就是那位证人,而它只有足够便宜、能熬过忙碌的季度,才算真正有效。
复查的常见翻车点:它变成一份没人打开的文档。把每项周期性检查绑定到一个会自行触发的扳机上——日历触发恢复演练,部署清单触发防火墙重读,人事流程触发面板权限复查——这张日程表就能活得比写下它的人更久,而以年而非以周计的日程表,才是唯一算数的版本。
在任何新机器上跑完整序列,你就越过了让大多数服务器阵亡的故障模式;在 oldest 那台机器上每季度跑一次,你就能一直待在那里。下面的时间线把本页的全部内容压缩成命令实际执行的顺序——这正是你会想在第二个终端里打开的那种形态。
加固清单:按执行顺序
第一分钟:密钥。ssh-keygen -t ed25519,公钥写入 ~/.ssh/authorized_keys,在 /etc/ssh/sshd_config 设置 PasswordAuthentication no,建一个日常用的具名 sudo 用户,并在关掉第一个终端之前先测试第二个终端。在新会话证明自己之前,面板控制台一直开在一个标签页里,因为带外访问正是让这份清单上后来每一个失误都可挽回而非致命的东西——而且 30 分钟的预算对生产机和演练机同样成立。
第五分钟:防火墙——默认拒绝,然后放行 22/tcp、80/tcp、443/tcp 和每个真实服务一个端口,用 ss -tulpn 和 nft list ruleset 确认。第十分钟:装好 fail2ban,bantime 以小时计,你自己的地址进白名单;并从 /etc/apt/apt.conf.d/50unattended-upgrades 启用无人值守升级。这两步从此不再需要你做任何决定——这正是把它们放在早期做完的意义。
第二十分钟:快照已排程,异地副本开始流动,一次恢复已演练进临时目录,让链路是被证明的而非被假设的。敏感数据放进开机后才打开的 LUKS 容器,口令的保管处在它所保护的那块盘之外。第一天晚上:托管面板开 2FA,对一切接受上传的入口做接收扫描,把季度演练写进日历并挂上一个真正的提醒。
长期维护,按同样顺序:/var/run/reboot-required 每周看一次;每上一个新服务就重读防火墙;人员名单每变动一次就复查面板权限。这些都不聪明,而这正是要点——密钥、一份简短的放行清单、自动补丁、一次测试过的恢复、一块加密的磁盘、一个双因素的面板。顺序之所以重要,是因为每一步都在缩小下一步的风险;日程之所以重要,是因为没有日程,每一步都会漂移;而现在这三十分钟加上每季度一小时,就是越过那些终结大多数服务器的故障模式的全部代价。
VPSbit 会帮我加固服务器吗?
不会——root 权限本身就是产品,这让加固的决定权和收益都握在你自己手里。目录里的任何套餐都不会预置这份清单;它是系统管理员在任何 Linux 机器上都会执行的基础线,而且这里的每一步都在你自己的会话中运行,而不是服务商的——这也是这些技能能迁移到你将来租的任何其他服务器上的原因。
密码登录真的默认就不安全吗?
在每一个公网 IP 上它都是薄弱默认值:首次开机几分钟内暴力破解尝试就开始,而且永不停止,因为对僵尸网络来说扫描整个 IPv4 空间成本极低。仅密钥认证是本页性价比最高的单一步骤——赶在防火墙之前、赶在更新之前做掉它,并在切换设置时保持面板控制台开着,让手误始终可以挽回。
Linux VPS 需要杀毒软件吗?
对基础系统来说很少需要,因为有签名的发行版仓库并不是常见的感染路径。要扫的是你从别人那里接收的东西:上传、邮件队列和用户生成的文件——放在接收目录上的 ClamAV 级别扫描器,能抓住真正到达的东西。没有人查看隔离区的检测只是装饰,所以部署之前先定好由谁来查看。
清单应该多久重跑一次?
第一到第九步在架构变更之前一直有效。备份恢复每季度演练一次;每上一个新服务就重读防火墙;人员名单每变动一次就复查面板权限——每项检查都绑定到一个会自行触发的扳机,而不是绑在记忆上,因为忙碌的季度最先删掉的就是记忆。
LUKS 能用在 VPS 上吗,还是只能在 dedicated 上?
两者都可以。在 VPS 上,服务商控制台扮演开机口令的输入角色;在 dedicated 档位上,IPMI 提供完整的远程控制台和虚拟介质,让开机后的解锁成为例行操作,即使无人值守的重启也一样。这套模式——容器开机后打开、密钥保管在盘外、swap 放进容器——两种情况下完全相同。
最快毁掉这一切的方式是什么?
一块无人看守的托管面板:它能重建机器、改走 DNS,并且活得比虚拟机内的所有控制都久。创建账号当天就启用 2FA;恢复通道不要落在任何自身没有第二因素的邮箱上;每当有队友离职就重新审计面板权限——离职正是这一层在现实中失守的时刻。