数据库外部访问拦截的核心从来不只是“开个防火墙”那么简单。多数生产环境的事故复盘里,根因都指向同一个盲区:管理员以为只对公网入口做了限制,却忽略了云厂商的负载均衡、只读副本、数据迁移服务以及内部运维跳板机同样暴露了数据库端口。真正有效的拦截配置,必须从网络边界、身份认证、协议特征和审计追踪四个层面同时收紧,任何单一策略都容易被绕过。

先界定“外部访问”的边界

在配置拦截之前,需要明确哪些流量属于“外部”。如果数据库部署在云上,公网IP直连是最明显的外部访问,但专线对端的第三方合作网络、跨VPC的另一个业务系统、甚至同VPC内被入侵的Web容器,都应当视为外部。安全配置的默认原则是:数据库只信任应用服务器所在的子网,其余来源一律拒绝。这个原则要落实到安全组、网络ACL和数据库自带的访问控制列表三层,而不是只依赖其中一层。

网络层拦截:安全组与ACL的配合

安全组是有状态防火墙,配置“允许”规则后,回包自动放行。网络ACL是无状态防火墙,入站和出站都要单独写规则。很多人只配安全组,结果在跨子网访问时出现意外放行。正确做法是:安全组只对应用服务器子网开放数据库端口,例如MySQL的3306、PostgreSQL的5432、Redis的6379、MongoDB的27017;网络ACL则在子网边界再叠加一层拒绝规则,显式丢弃来自0.0.0.0/0对数据库端口的访问请求。两层规则叠加后,即使安全组被误改成全放行,ACL仍然能兜底。

对于使用云负载均衡暴露数据库的场景,需要特别注意负载均衡器本身的安全组。很多团队把数据库挂在内网负载均衡后面,却给负载均衡器配置了公网IP,或者在负载均衡器的安全组里误加了0.0.0.0/0的入站规则。检查时要把负载均衡器的监听端口、转发规则和后端健康检查端口全部纳入清单,健康检查端口如果对外开放,同样可能被利用做端口探测。

数据库自身访问控制

网络层拦截只能挡住未授权来源的TCP连接,但挡不住已经进入内网的恶意流量。数据库自身的账户体系必须配合做来源限制。MySQL和PostgreSQL都支持在账户层面绑定允许登录的主机地址。MySQL的user表里Host字段不要使用通配符“%”,除非该账户确实需要从任意主机登录。PostgreSQL的pg_hba.conf文件要显式配置允许的IP段,并把认证方式从trust改成scram-sha-256或更严格的证书认证。Redis如果对外提供服务,必须设置requirepass,并且禁止使用默认端口,同时关闭CONFIG命令的远程执行权限。

一个常见问题是:开发人员为了方便,给应用账户配置了“%”的Host,然后依赖安全组做限制。一旦安全组规则被误操作删除,数据库就完全暴露。更稳妥的做法是双重限制:账户Host绑定到应用服务器子网的具体IP段,同时安全组只放行该子网。这样即使某一层失效,另一层仍然有效。

协议特征与端口隐藏

外部扫描工具通常会先做端口探测,再尝试识别数据库版本。修改默认端口能降低被自动化扫描命中的概率,但不能作为主要安全手段。更有效的是在网络层对数据库协议做深度识别。部分云防火墙和主机防火墙支持基于应用协议的访问控制,例如只允许符合MySQL握手特征的流量通过,丢弃其他流量。对于自建数据库,可以在主机防火墙iptables或nftables里配合string模块匹配特定协议特征,但这种方式对加密协议效果有限,且维护成本较高。

如果业务允许,建议将数据库完全置于私有子网,不分配公网IP,也不通过公网负载均衡暴露。所有外部访问需求通过堡垒机或VPN网关进入内网后再访问数据库。堡垒机本身要启用多因素认证、会话录制和命令审计,并且只允许从公司办公网出口IP访问。这个链路虽然增加了运维复杂度,但能把数据库的暴露面降到最低。

只读副本与数据迁移服务的盲区

云数据库的只读副本经常被忽略。主实例做了严格的安全组限制,但只读副本可能因为创建时默认配置,绑定了公网IP或者开放了更宽松的安全组。攻击者如果拿到只读副本的连接地址,同样可以拖走全部数据。检查时要遍历所有实例,包括只读副本、灾备实例、临时克隆出来的实例,确保它们的网络配置和主实例一致。

数据迁移服务是另一个高风险点。云厂商的DTS、DataWorks或者自建的DataX、Canal,通常需要源库和目标库之间建立连接。如果迁移任务配置了公网连接方式,数据库的访问入口就多了一个。迁移任务完成后,要及时释放公网连接,删除临时创建的迁移账户,并回收相关安全组规则。很多数据泄露事件发生在迁移完成后的空窗期,因为临时通道没有及时关闭。

运维跳板机与自动化平台的权限收敛

运维人员习惯通过跳板机直接连数据库执行SQL。跳板机如果被攻破,数据库的访问拦截就形同虚设。跳板机本身要限制来源IP,禁止密码登录,只允许密钥认证,并且定期轮换密钥。数据库账户方面,运维使用的账户要和应用程序账户分离,权限最小化。生产库的DDL操作建议通过审批后的工单系统执行,而不是直接给运维人员高权限账户。

自动化发布平台、监控系统、数据报表工具也会持有数据库连接凭证。这些平台通常部署在内网,但它们的Web界面可能暴露在公网。如果Web界面存在漏洞,攻击者可以借道平台的内网权限访问数据库。因此,对这类平台的访问也要做来源限制,并且数据库账户只授予必要的SELECT权限,禁止执行写操作和DDL。

审计与告警:拦截不是终点

拦截规则配置完成后,必须开启访问日志和审计。云数据库一般提供SQL审计功能,可以记录连接来源IP、执行语句、执行时间。自建数据库可以开启general_log或使用审计插件。审计日志要定期检查,重点关注:来自非预期IP的连接尝试、连续失败的认证请求、非业务时段的批量查询、以及大流量数据导出操作。

告警规则要覆盖以下场景:安全组规则被修改、数据库公网IP被开启、账户Host被修改为“%”、pg_hba.conf文件变更、以及数据库端口被扫描。这些事件应当实时推送到安全运营团队,而不是只记录在日志里。很多云平台支持配置事件告警,当检测到数据库公网访问开启时自动触发通知,甚至自动回滚配置。

配置示例:MySQL与PostgreSQL的拦截基线

以下是一个MySQL账户来源限制的配置示例,假设应用服务器子网为10.0.1.0/24:

CREATE USER 'app_user'@'10.0.1.%' IDENTIFIED BY '强密码';
GRANT SELECT, INSERT, UPDATE, DELETE ON app_db.* TO 'app_user'@'10.0.1.%';
FLUSH PRIVILEGES;

同时检查user表中是否存在Host为“%”的账户:

SELECT user, host FROM mysql.user WHERE host = '%';

对于PostgreSQL,pg_hba.conf中应配置:

# TYPE  DATABASE  USER  ADDRESS       METHOD
host    app_db    app_user  10.0.1.0/24  scram-sha-256
host    all       all       0.0.0.0/0    reject

最后一行显式拒绝所有其他来源,确保没有漏网之鱼。修改后需要执行pg_ctl reload或SELECT pg_reload_conf()使配置生效。

定期验证与红蓝对抗

配置是否有效,不能只看文档。每季度至少做一次穿透测试,模拟外部攻击者尝试连接数据库。测试项包括:从公网直接连接数据库端口、通过负载均衡器访问、尝试使用弱口令或默认账户登录、扫描只读副本和临时实例、检查数据迁移通道是否残留。测试结果要和配置基线对比,发现偏差立即整改。

红蓝对抗中,蓝队要重点验证安全组和ACL的规则顺序。云平台的安全组规则如果有多条,匹配顺序可能影响最终效果。例如一条允许规则放在拒绝规则之前,可能使拒绝规则失效。测试时要逐条验证规则的实际生效情况,而不是只看控制台显示。

数据库外部访问拦截是一项需要持续维护的工作。网络架构调整、新实例上线、人员变动、云平台功能更新,都可能引入新的暴露面。只有把拦截策略固化为基线配置,纳入自动化检查和变更管理流程,才能避免“配置一次就遗忘”带来的风险。安全配置的价值不在于规则数量,而在于每一层规则都能在实际攻击路径上发挥作用。