4、应用与服务安全:Web服务安全加固(Nginx/Apache)、数据库安全(Redis/MySQL)、容器安全(Docker安全配置、镜像扫描)、API安全(认证、限流、审计)
这一章内容比较多,但都是实打实的硬功夫。说白了,边缘网关上的应用和服务就是你的“脸面”,攻击者最先摸到的就是它们。我这些年做安全评估,十次里有八次都是从Web服务或者API捅进去的。咱们一个一个来拆解。
核心思路:应用与服务安全不是装个防火墙就完事了。你得从配置、通信、权限、运行时四个维度去卡。少一个维度,就等于给攻击者留了后门。
4.1 Web服务安全加固(Nginx / Apache)
Web服务是边缘网关最常用的入口。Nginx轻量、高性能,Apache稳定、模块丰富。但不管用哪个,默认配置基本等于裸奔。
4.1.1 版本隐藏与信息泄露
攻击者拿到版本号,就能精准搜索漏洞。我见过太多人直接暴露 Server: nginx/1.18.0,这不是等着被捅吗?
- Nginx: 在
http块里加server_tokens off;,再配合more_set_headers 'Server: Unknown';(需要 ngx_headers_more 模块)。 - Apache: 修改
httpd.conf,设置ServerTokens Prod和ServerSignature Off。
我的习惯: 我还会把默认的404、500错误页面也换掉。默认页面经常带出版本信息,甚至框架路径。换成一张纯白页面,啥信息都不给。
4.1.2 禁用不安全方法与目录限制
PUT、DELETE这些方法,对外接口基本用不上。开着就是给人上传webshell用的。
# Nginx 配置示例
if ($request_method !~ ^(GET|HEAD|POST)$) {
return 405;
}
# Apache 配置示例
<LimitExcept GET POST HEAD>
Deny from all
</LimitExcept>
另外,.git、.env、backup 这些目录必须屏蔽。我曾经在客户现场,直接通过 /.git/config 把整个源码拖下来了。
4.1.3 HTTPS 与 HSTS 强制
边缘网关走公网,明文HTTP就是找死。TLS 1.2 是底线,TLS 1.3 最好。证书用 ECC 曲线,性能比 RSA 好不少。
| 配置项 | 推荐值 | 说明 |
|---|---|---|
| ssl_protocols | TLSv1.2 TLSv1.3 | 禁用 SSLv3、TLSv1.0、TLSv1.1 |
| ssl_ciphers | ECDHE+AESGCM:!aNULL:!MD5 | 优先使用前向安全套件 |
| ssl_prefer_server_ciphers | on | 服务端决定加密顺序 |
| add_header Strict-Transport-Security | "max-age=63072000; includeSubDomains" | 强制HSTS,两年有效期 |
注意: 开启HSTS前,确保全站HTTPS已经稳定。否则一旦浏览器记住,HTTP就再也回不去了。我见过有人没配好证书就开HSTS,结果整个站点废了三天。
4.2 数据库安全(Redis / MySQL)
边缘网关上的数据库,经常存设备凭证、业务数据。Redis和MySQL是两大主力,但默认配置的漏洞多得吓人。
4.2.1 Redis 安全加固
Redis 默认监听 0.0.0.0:6379,无密码。这简直是给攻击者送大礼。我记得有一次渗透测试,直接连上Redis,用 CONFIG SET dir /root/.ssh 写公钥,秒拿服务器权限。
- 绑定内网IP:
bind 127.0.0.1 192.168.1.100,别绑0.0.0.0。 - 设置强密码:
requirepass YourStrongPassword!,别用redis123这种。 - 禁用危险命令: 用
rename-command把FLUSHALL、CONFIG、EVAL重命名或禁用。 - 以低权限用户运行: 创建
redis用户,只给数据目录的读写权限。
# redis.conf 关键配置
bind 127.0.0.1 192.168.1.100
requirepass MyEdge@2024!
rename-command FLUSHALL ""
rename-command CONFIG "EDGE_CONFIG_CMD"
rename-command EVAL ""
4.2.2 MySQL 安全加固
MySQL 的问题通常是弱口令、空口令、权限过大。边缘网关资源有限,但安全不能省。
| 检查项 | 操作 | 我的经验 |
|---|---|---|
| 匿名用户 | DELETE FROM mysql.user WHERE User=''; | 默认就有一个匿名用户,删掉 |
| root远程登录 | DELETE FROM mysql.user WHERE User='root' AND Host NOT IN ('localhost'); | root 只允许本地socket登录 |
| 测试数据库 | DROP DATABASE IF EXISTS test; | test库默认所有人可访问 |
| 密码策略 | INSTALL PLUGIN validate_password SONAME 'validate_password.so'; | 强制密码复杂度,长度至少12位 |
避坑指南: 我曾经遇到一个项目,MySQL 的 general_log 没关,结果日志文件把磁盘撑爆了。边缘网关的存储本来就小,记得检查 log_warnings 和 general_log 的配置。
4.3 容器安全(Docker安全配置、镜像扫描)
边缘网关现在大量用容器化部署。Docker 确实方便,但安全配置跟不上,容器就成了“带壳的漏洞”。
4.3.1 Docker 守护进程安全
Docker 的 socket 文件 /var/run/docker.sock 是最高权限入口。谁拿到它,谁就能控制宿主机。
- 不要暴露 Docker API: 除非必要,别把
-H tcp://0.0.0.0:2375开出来。我见过有人为了方便管理,直接暴露2375端口,结果被挖矿程序扫到,整个集群沦陷。 - 使用 TLS 认证: 如果必须远程管理,用
--tlsverify开启双向认证。 - 限制容器特权: 运行容器时加
--security-opt=no-new-privileges,防止容器内提权。
4.3.2 容器运行时安全配置
默认的 Docker 容器跑在 root 下,这很危险。攻击者一旦突破应用,直接就是 root 权限。
# 推荐的安全运行参数
docker run -d \
--name edge-service \
--user 1000:1000 \ # 以非root用户运行
--read-only \ # 根文件系统只读
--cap-drop=ALL \ # 丢弃所有capability
--cap-add=NET_BIND_SERVICE \ # 只添加需要的capability
--security-opt=no-new-privileges \
--memory="256m" \ # 限制内存
--cpus="0.5" \ # 限制CPU
your-image:tag
警告: --privileged 参数在边缘网关上绝对不要用。它等于把宿主机内核完全交给容器。我见过有人为了调试方便加了 --privileged,结果容器被入侵后,攻击者直接加载内核模块,宿主机彻底失控。
4.3.3 镜像扫描与漏洞管理
基础镜像里经常藏着高危漏洞。比如 Alpine 的 libcrypto 库,或者 Ubuntu 的 bash 漏洞。你不能假设官方镜像就是安全的。
- 使用 Trivy 扫描: 轻量、快速,适合边缘网关的CI/CD流程。
- 选择最小基础镜像: 优先用
alpine:3.19或distroless镜像,减少攻击面。 - 定期更新基础镜像: 每周重新构建一次,确保包含最新安全补丁。
# Trivy 扫描命令示例
trivy image --severity HIGH,CRITICAL --ignore-unfixed your-image:tag
# 输出示例(假设发现漏洞)
# +----------------+------------------+----------+-------------------+
# | LIBRARY | VULNERABILITY ID | SEVERITY | INSTALLED VERSION |
# +----------------+------------------+----------+-------------------+
# | libssl1.1 | CVE-2024-1234 | CRITICAL | 1.1.1k-1 |
# | libcrypto1.1 | CVE-2024-5678 | HIGH | 1.1.1k-1 |
# +----------------+------------------+----------+-------------------+
我的习惯: 我会在 CI 流水线里加一步:如果扫描出 CRITICAL 漏洞,直接阻断构建。别想着“先上线再补”,边缘网关一旦上线,升级镜像比云端麻烦十倍。
4.4 API安全(认证、限流、审计)
边缘网关的API是设备与云端通信的桥梁。认证、限流、审计,这三件事做不好,API就是敞开的城门。
4.4.1 API 认证
别用简单的 API Key 了。边缘网关设备多,Key 泄露是迟早的事。我建议用 JWT + 双向 TLS。
- JWT: 使用 RS256 或 ES256 算法,私钥签名,公钥验证。设置较短的过期时间(比如15分钟),配合 refresh token。
- 双向 TLS(mTLS): 设备端和服务端互相验证证书。适合 IoT 场景,安全性最高。
- API Key + 签名: 如果设备性能有限,至少用 HMAC-SHA256 对请求体签名,防止重放攻击。
# JWT 验证中间件示例(伪代码)
function authenticate(req, res, next) {
const token = req.headers['authorization']?.split(' ')[1];
if (!token) return res.status(401).send('Missing token');
try {
const decoded = jwt.verify(token, publicKey, { algorithms: ['RS256'] });
req.user = decoded;
next();
} catch (err) {
return res.status(401).send('Invalid token');
}
}
4.4.2 限流与防滥用
边缘网关带宽有限,一个设备疯狂请求就能拖垮整个网关。限流是必须的。
| 限流策略 | 实现方式 | 适用场景 |
|---|---|---|
| 基于IP | Nginx ngx_http_limit_req_module | 防止单个IP洪水攻击 |
| 基于API Key | 应用层中间件 + Redis计数器 | 按设备/用户限流 |
| 基于时间窗口 | 滑动窗口算法(Redis Sorted Set) | 精确控制请求频率 |
| 并发连接数 | Nginx limit_conn_module | 防止慢速连接耗尽连接池 |
# Nginx 限流配置示例
http {
limit_req_zone $binary_remote_addr zone=api_limit:10m rate=10r/s;
server {
location /api/ {
limit_req zone=api_limit burst=20 nodelay;
proxy_pass http://backend;
}
}
}
避坑指南: 我曾经遇到一个案例,限流配置只做了IP维度,结果攻击者用肉鸡池每个IP只发一个请求,轻松绕过。后来我改成IP + API Key 双维度限流,才堵住这个口子。
4.4.3 审计日志
出了安全问题,没有日志等于没有线索。审计日志要记录谁、什么时间、做了什么、结果如何。
- 记录内容: 请求时间、源IP、API路径、请求方法、状态码、响应时间、用户标识。
- 不要记录敏感信息: 密码、Token、身份证号等必须脱敏或加密存储。
- 日志轮转: 边缘网关存储有限,设置日志大小限制和保留天数(建议至少30天)。
- 集中收集: 如果条件允许,把日志发送到远程日志中心,防止本地日志被攻击者删除。
# 审计日志格式示例(JSON)
{
"timestamp": "2024-03-15T10:30:00Z",
"source_ip": "192.168.1.50",
"method": "POST",
"path": "/api/v1/device/data",
"status": 200,
"response_time_ms": 45,
"user_id": "device_12345",
"user_agent": "EdgeDevice/1.0"
}
4.5 本章知识体系总览
下面这张图把本章的核心逻辑串起来了。从Web服务到数据库,再到容器和API,每个环节都有对应的加固要点。你可以把它贴在工位上,做安全巡检时对照着看。
好了,这一章的内容就这些。Web服务、数据库、容器、API,每个点都值得你花时间去检查自己的环境。别想着一次性搞定所有,先从最薄弱的环节入手——比如看看你的Redis有没有设密码,Nginx有没有暴露版本号。安全加固是个持续的过程,慢慢来,但别停下来。