Gotchaa Lab
返回博客
cybersecuritydevopsserver-hardeningmalaysiainfrastructure

服务器加固基础:上线前必须做完的 5 件事

2026年5月14日·阅读约 9 分钟·作者:Gotchaa Lab
服务器加固基础:上线前必须做完的 5 件事

重点摘要

  • 代码写得再干净,跑在配置错误的服务器上,门一样是开的。下面这 5 件事堵的是攻击者真正会走的门,不是那些冷门路径。
  • SSH key、防火墙、Fail2Ban、非 root 应用用户、反向代理,在一台全新 VPS 上大概 30 分钟做完,挡掉绝大部分自动化机器人流量。
  • 在 PDPA 之下,服务器上的个人资料由你的公司负责。基础加固是底线,不是可选项。

多数开发者很在意代码写得安不安全。参数化查询、输入校验、依赖扫描,一整套都做。习惯是好习惯。

然后他们把这份干净的代码,部署到一台 22 端口对全世界敞开、root 可以登录、应用用 root 跑、前面没有任何限流的服务器上。代码再干净,服务器配置错了,门一样是开的。难的那部分白做了。

下面是上线前该锁好的 5 项服务器加固基础。没有一项冷门。全部都能挡掉新 VPS 拿到 IP 后几分钟内就涌上来的那批自动化流量。

不是开发者?看这一段就好。

后面很快就进入技术细节。如果你是老板但不写代码,你不需要看懂那些命令,你只需要知道上线前该问开发团队什么。5 个问题:

  1. “服务器上的密码登录关掉了吗,改成 SSH key 了吗?”(是 / 否)
  2. “有防火墙吗?除了应用真正会用的端口,其他都关了吗?”(是 / 否)
  3. “装了 Fail2Ban 或类似的东西,去挡反复登录失败的尝试吗?”(是 / 否)
  4. “我们的应用是用普通用户跑的,不是 root 吧?”(是 / 否)
  5. “应用前面有 Nginx 或 Caddy 这类反向代理,负责 HTTPS 吗?”(是 / 否)

任何一题答“没有”或“不确定”,先别上线。这些事对懂的人来说,每一项都花不到 30 分钟。帮你架服务器的人,应该能白纸黑字确认这 5 项都做了。

1. 禁用 root 登录,改用 SSH key

一台全新 Linux VPS 的默认状态,就是最糟的状态。22 端口开着,root 可以登录,密码认证也开着。开通后几个小时内,你就会看到成千上万次登录失败记录,全是机器人在试弱的 root 密码。

两个改动就能关上这道门。

先建一个有 sudo 权限的普通用户,然后换成 SSH key 认证。在自己的电脑上用 ssh-keygen -t ed25519 生成 key,用 ssh-copy-id user@yourserver 把公钥传上服务器,登录一次确认可用,再到 /etc/ssh/sshd_config 里关掉密码登录和 root 登录:

PermitRootLogin no
PasswordAuthentication no
PubkeyAuthentication yes

sudo systemctl restart sshd 重启 SSH,并且在另一个终端确认 key 能登进去之前,原来那个会话千万别关。把自己锁在外面,你就得在凌晨两点付钱给 VPS 供应商开 console。

SSH key 不是“比较难破”。它是在任何合理时间内都不可能被暴力破解的。密码是猜得中的。这两者没得比。

2. 装好防火墙

每一个开着的端口背后都是一个服务。每个服务都有版本。每个版本都有已公开的已知漏洞。防火墙让你一句话说清“只开这几个端口,其他免谈”,不用再争。

在 Ubuntu 上,UFW 三条命令就能做掉 90%:

sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow 22/tcp     # SSH
sudo ufw allow 80/tcp     # HTTP
sudo ufw allow 443/tcp    # HTTPS
sudo ufw enable

就这样。5432 上的 Postgres、6379 上的 Redis、跑在 3000 或 8080 的应用服务器?外网一个都碰不到。你的 web 应用通过 localhost 跟它们讲话,这正是你要的。

一条昏暗的服务器走廊,大部分门都关着,只有几扇透出暖光,象征防火墙只暴露真正需要的端口 防火墙就是一条锁上门的走廊。只开应用真的要走的那几扇。

我们做代码审查时最常看到的错误:.env 里写着 DB_HOST=0.0.0.0,Postgres “为了开发方便”监听所有网卡。这种配置滑进生产环境时,防火墙救的是你自己。

如果你的 VPS 供应商有网络层防火墙(DigitalOcean Cloud Firewalls、AWS Security Groups、Hetzner Cloud Firewall),两层都用。纵深防御是真有用,不是做样子。

3. 装 Fail2Ban

Fail2Ban 盯着你的日志文件。当某个 IP 的 SSH 登录、web 应用登录失败,或者命中你配置的任何规则,Fail2Ban 就临时加一条 iptables 规则丢掉那个 IP 的流量。默认是 10 分钟内失败 3 次,封 10 分钟。

装好并启用:

sudo apt install fail2ban
sudo systemctl enable --now fail2ban

默认配置已经保护 SSH。要给 Nginx 认证、WordPress 登录,或你自家应用的登录失败端点加自定义 jail,也就几行配置。

有两点要知道。第一,Fail2Ban 不能取代防火墙。防火墙决定什么碰得到,Fail2Ban 决定谁已经不受欢迎,两者是分层的。第二,如果你的应用在 Cloudflare 或负载均衡器后面,每个请求看起来都来自同一个代理 IP,除非你配置它从 X-Forwarded-For 读真实 IP,否则 Fail2Ban 形同虚设。先确认,再去相信那些封禁记录。

4. 永远不要用 root 跑应用

如果你的 Node、Python 或 Laravel 应用是用 sudo 启动的,理由是“这样才跑得起来”,请停手。你等于把 root 权限交给了每一个依赖、每一个 NPM 包、每一个 Composer 库。只要一次供应链被攻破(今年早些时候的 LiteLLM 事件就是新鲜例子),攻击者就拿下整台机器。

给应用建一个专用的、无特权的用户:

sudo adduser --system --group --no-create-home appuser
sudo chown -R appuser:appuser /var/www/myapp

然后用这个用户跑应用。systemd unit 文件写起来很简单:

[Service]
User=appuser
Group=appuser
WorkingDirectory=/var/www/myapp
ExecStart=/usr/bin/node server.js

万一 appuser 被拿下,攻击者拿到的是这个应用的文件和数据库凭证。这已经很糟。但他装不了 rootkit、改不了 SSH 配置、读不了其他用户的文件,也没法横向跳到机器上的其他服务。影响范围被圈在一个应用里。

Docker 上同理。Dockerfile 里写 USER nodeUSER 1000,别用默认的 root。容器本身默认不是安全边界,把它当成需要用无特权用户来跑的进程就对了。

5. 在应用前面放一个反向代理

你那个跑在 3000 端口的 Node 应用,单线程送 HTTP 送得挺开心。然后 10 个机器人发现了它,拿畸形请求猛砸,event loop 就没了。反向代理(Nginx、Caddy、Traefik)的做法是站在外网和你的应用之间,把脏活接下来。

实际拿到什么:

  • TLS termination。 Caddy 几行配置就给你 HTTPS 和自动续期的 Let's Encrypt 证书。Nginx 配 Certbot 也就 5 分钟。别再让 Node 进程去处理 SSL。
  • 响应头加固。 Strict-Transport-SecurityX-Frame-OptionsContent-Security-Policy,全在代理层加上,应用一行都不用改。
  • 限流。 Nginx 的 limit_req 能限制单个 IP 打你 /login 端点的频率。搭配 Fail2Ban,多数撞库攻击在碰到应用之前就死了。
  • 连接缓冲。 慢速客户端(Slowloris 那类攻击)耗的是代理的连接,不是你应用的。Nginx 吸收这类请求比 Node 或 Express 强得多,尤其是把 client_header_timeoutclient_body_timeoutlimit_conn 设成合理值之后。Nginx 本身不是万灵丹,但它把故障形态从“应用挂了”变成“几条代理连接被占着”。

小团队用 Caddy 最省事。Caddyfile 写几行,HTTPS、HTTP/2 和一套合理默认值就有了。要精细控制的话,Nginx 是无聊但久经考验的选择。挑一个用。别让应用直接跑在 80 或 443 端口上。

这些还是保护不了你的部分

这 5 件事挡的是机器人和懒人。挡不了的是:

  • 你代码里的 SQL injection(写参数化查询)。
  • 公开 GitHub repo 里泄露的 .env(审一遍你的提交记录)。
  • 开发者的电脑被入侵、SSH key 就在上面(给 key 设密码短语,定期轮换)。
  • 依赖里的供应链攻击(锁版本,盯 CVE 通报)。
  • 手上有你这套技术栈零日漏洞的、有心的攻击者。

加固是底线。应用安全是另一个问题,它住在你的代码、CI pipeline 和依赖管理里。我们之前写过 vibe coding 的安全风险AI 工具的供应链攻击。想看应用层那一面,可以读这两篇。

PDPA 这一层

如果你的马来西亚公司在这台服务器上存了任何个人资料(姓名、IC 号码、电话、电邮,任何能识别到人的东西),PDPA 你想不想面对都得面对。2024 年修正案对达到门槛的事件设了 72 小时通报窗口,而“我们把 root SSH 开着”这种理由,监管方不会觉得情有可原。

基础加固不是合规的万灵丹。但因为省掉它而出事,是最快触发通报义务、连带赔上名声的路径之一。把这 30 分钟当成你买过最便宜的保险。

我们的看法

马来西亚中小企业和初创的部署,我们审过不少。模式很一致:应用代码干净,服务器配置薄弱。开发者被教过怎么安全地写 SQL,很少被教过怎么安全地部署。早期公司出的安全事故,大多不是从什么精巧的漏洞利用开始。它们的开头是:22 端口对全世界开着,密码登录没关,攻击者用 root:admin123 进来,然后是 6 个星期没人发现的缓慢横向移动。

解法不好看,但是快。懂的人 30 分钟就能把一台新 VPS 弄到可上线的加固状态。第一次做,给自己一小时和一份清单。

这 5 件事不会让你的服务器刀枪不入。它们会让攻击者转头去找更好下手的目标。老实说,这就是目标。

上线前想找人帮你的生产环境看一眼?我们的网络安全团队经常做这类检查。WhatsApp 找我们留个言,我们陪你把配置过一遍。不推销。

参考资料

  1. OpenSSH sshd_config Manual
  2. Ubuntu UFW Documentation
  3. Fail2Ban Official Documentation
  4. Caddy Server Documentation
  5. Nginx Rate Limiting Guide
  6. Malaysia Personal Data Protection Act (Amendment) 2024

分享这篇文章

常见问题

保护一台 Linux 服务器,最先做的三件事是什么?
先打补丁(apt update && apt upgrade),再关掉 root 的 SSH 登录、改用 SSH key,然后开防火墙(Ubuntu 上用 UFW),只放行应用真正会用到的端口。光是这三件,就能挡下新 VPS 上大部分随机扫描的机器人流量。
为什么要禁用 root 的 SSH 登录?
机器人整天在扫全网 22 端口的 SSH,拿常见密码试 root。root 一关,它们就得同时猜中一个有效用户名和一把 key,难度差了好几个数量级。做法是先建一个有 sudo 权限的用户,确认自己登得进去,再关掉 root。
有了 Fail2Ban,还需要防火墙吗?
需要。防火墙决定哪些端口能从外网碰到。Fail2Ban 是盯着日志,把反复登录失败的 IP 暂时封掉。两者解决的是不同问题,都要开。
在马来西亚,做好服务器加固就等于符合 PDPA 吗?
那只是技术层面的底线,不是全部。PDPA 还要求有政策、72 小时内通报泄露事件、部分公司要设 Data Protection Officer、和处理个人资料的供应商签合约。但省掉基础加固导致服务器被入侵,是最快让你摊上必须公开通报的一种方式。
做完这 5 件事,服务器就攻不破了吗?
不会。有心的攻击者还是可以从应用漏洞、零日、泄露的凭证或社工进来。基础加固的目标,是让你的服务器在那 99% 自动化、专挑软柿子的攻击面前显得没意思。

想为你的公司做一套这样的系统?

我们帮马来西亚企业把这类想法做成能用的软件。免费咨询,不勉强。