把数据库直接暴露在公网环境下,等于把保险柜放在大街上。很多运维人员习惯装好数据库就用默认配置跑业务,结果没几天就被勒索病毒洗劫一空。服务器安全配置适配数据库运行环境,核心思路就一条:最小化暴露面,分层防御。具体来说,要从操作系统层、网络层、数据库自身配置、以及持续的审计监控四个维度来构建防护体系,而不是简单地改几个端口号就完事。
操作系统层的安全加固是地基数据库跑在操作系统之上,系统本身如果被提权,数据库的访问控制形同虚设。第一步是用户隔离,绝对不要用root或administrator账户来启动数据库服务。以MySQL为例,安装完成后应创建独立的mysql用户和用户组,数据目录的权限设置为700,仅允许该用户读写。很多管理员图省事直接chmod 777,这等于把数据文件拱手送人。同时要检查umask值,确保数据库新建的文件默认权限是600而不是644。对于Linux系统,务必关闭SELinux或AppArmor中与数据库无关的模块,但不要直接整体禁用,而是针对数据库进程配置精确的策略规则。另外,操作系统的核心转储功能要限制,防止数据库崩溃时把内存中的敏感数据写到磁盘上。在/etc/security/limits.conf中设置mysql用户的core file size为0,并在数据库配置中关闭core dump功能,这样即使进程异常退出,也不会留下包含内存数据的转储文件。
网络层的纵深防御策略数据库端口直接对外开放是最常见的低级错误。正确的做法是构建多层网络隔离。首先在服务器本地防火墙,比如iptables或firewalld上,只放行来自特定内网IP段的数据库端口访问。以MySQL的3306端口为例,规则应该精确到源IP白名单,而不是开放给整个子网。如果应用服务器和数据库在同一台机器上,直接把数据库绑定到127.0.0.1,关闭远程访问。对于必须跨主机的场景,强制使用SSH隧道或VPN加密通道,数据库本身不再监听公网接口。在云环境里,安全组的配置要遵循同样的原则,只允许应用服务器的内网IP访问数据库端口,而且这个规则要定期审计,防止有人临时加了一条0.0.0.0/0的规则忘记删除。还有一个容易被忽视的点是DNS解析,数据库在做权限验证时如果用到主机名,攻击者可以通过DNS劫持来绕过IP限制。所以在创建数据库用户时,尽量使用IP地址而不是主机名,或者在数据库配置中启用skip-name-resolve,强制只用IP进行验证,这样既提升了连接速度,又堵住了DNS欺骗的缺口。
数据库自身的安全配置是核心安装完数据库后的第一步不是建库建表,而是运行安全初始化脚本。MySQL有mysql_secure_installation,PostgreSQL则需要手动处理。这个步骤至少要做五件事:删除匿名用户、删除测试数据库、禁止root远程登录、设置root密码复杂度、刷新权限表。很多人跳过这一步直接开干,结果默认的空密码账户就成了入侵者的高速公路。密码策略方面,不能只依赖应用层的密码强度验证,数据库层面要启用密码复杂度插件。MySQL 8.0自带的validate_password组件可以强制要求密码长度、混合大小写、特殊字符和数字。更关键的是密码过期策略,服务账户的密码应该定期轮换,但轮换周期不能太短导致业务中断,建议90天为一个周期,并且使用数据库自带的密码过期提醒功能。
权限管理是另一个重灾区。很多开发人员为了方便,直接给应用账户授予ALL PRIVILEGES,甚至用root账户跑业务。正确的做法是遵循最小权限原则,应用账户只授予对特定数据库的SELECT、INSERT、UPDATE、DELETE权限,连ALTER、DROP都不应该给。对于需要执行存储过程或触发器的场景,单独授予EXECUTE权限,而不是一股脑给全局权限。MySQL的权限粒度可以精确到列级别,如果某个表中有敏感字段,比如用户手机号,可以只授予查询其他字段的权限,敏感字段单独授权给特定的后台服务账户。PostgreSQL的Row-Level Security功能更强大,可以在行级别控制数据访问,多租户场景下非常实用。权限分配完成后,要定期执行权限审计,检查是否存在权限过大的账户,及时回收不再使用的账户。很多数据泄露事件追溯到最后,发现是某个离职员工的数据库账户一直没被禁用。
连接安全和传输加密不容忽视即使内网环境相对安全,数据库通信也应该强制启用TLS加密。攻击者一旦进入内网,就可以通过ARP欺骗或端口镜像的方式嗅探数据库流量,明文传输的查询语句和数据结果会全部暴露。MySQL配置TLS需要生成服务器证书和私钥,在配置文件中指定ssl-ca、ssl-cert、ssl-key的路径,然后重启服务。对于应用账户,创建时加上REQUIRE SSL参数,强制该账户必须通过加密连接才能登录。更严格的场景可以使用REQUIRE X509,要求客户端也提供证书进行双向认证。PostgreSQL的pg_hba.conf文件中,可以把认证方式从md5改为scram-sha-256,同时启用hostssl类型的连接规则,拒绝任何非加密连接。证书管理方面,自签名证书只适用于测试环境,生产环境应该使用内部CA签发的证书,并且证书有效期不宜过长,建议一年一换。证书过期会导致所有加密连接中断,所以到期前一个月就要开始走续签流程。
SQL注入防护要从数据库层面兜底应用代码的SQL注入漏洞防不胜防,即使开发团队做了代码审查和参数化查询,也难免有遗漏。数据库层面可以提供最后一道防线。MySQL Enterprise Edition自带防火墙功能,社区版可以使用ProxySQL或MaxScale等中间件来做SQL语句过滤。更轻量的方案是利用数据库的查询重写机制,比如MySQL 8.0的查询重写插件,可以定义规则拦截特定的SQL模式。例如,可以设置规则禁止不带WHERE条件的DELETE或UPDATE语句,防止全表误删。还可以限制单条查询返回的行数,防止攻击者通过SELECT *拉取整个用户表。对于存储过程,要避免使用动态SQL拼接,如果必须使用,要用数据库自带的预处理语句功能来绑定参数。PostgreSQL的函数中,可以通过设置search_path来防止函数被劫持,避免攻击者通过创建同名函数来执行恶意代码。
日志审计和异常检测是持续保障安全配置不是一劳永逸的事情,必须配合持续的监控才能及时发现异常。数据库的通用查询日志在生产环境中不建议一直开启,因为性能开销太大,但慢查询日志和错误日志必须开启,并且定期分析。MySQL的审计插件可以记录所有数据库操作,包括登录尝试、权限变更、DDL语句执行等。这些审计日志不要存放在数据库服务器本地,应该实时发送到远程的日志收集系统,防止入侵者删除日志掩盖痕迹。关键指标要设置告警,比如短时间内大量失败的登录尝试、非工作时间段的数据库连接、异常的大批量数据导出操作等。很多数据库勒索攻击的特征是先做全库导出,再加密本地文件,如果能在这个阶段及时阻断,就能避免数据丢失。另外,数据库版本要定期检查官方安全公告,高危漏洞的补丁要及时打,但升级前要在测试环境充分验证兼容性,避免补丁导致业务中断。
备份策略是最后的底线安全配置做得再好,也不能保证百分之百不被攻破,所以备份是最后的救命稻草。备份文件本身的安全同样重要,很多案例中攻击者先拿到数据库权限,然后顺藤摸瓜找到备份服务器,把备份也一并加密。备份文件应该使用独立的存储系统,通过专用账户访问,并且开启不可变存储功能,防止备份被篡改或删除。备份数据要加密存储,密钥与备份分开管理。恢复演练至少每季度做一次,很多团队天天备份但从来没恢复过,真到出事的时候发现备份文件损坏或者恢复流程不完整。对于核心业务数据库,建议采用延迟复制的方式搭建一个从库,主库被攻击后,从库的数据延迟几小时同步,这样即使主库被加密,从库还有时间窗口可以抢救数据。这个延迟从库的网络策略要更严格,不与主库在同一个安全组内,避免攻击者横向移动一并拿下。
服务器安全配置适配数据库运行环境,本质上是一个系统工程,不是装个防火墙或者改个密码就能解决的。从操作系统加固到网络隔离,从权限控制到传输加密,从日志审计到备份恢复,每一层都要扎实落地。安全与便利性永远是天平的两端,运维人员需要在其中找到适合自身业务风险的平衡点,但原则性的底线,比如最小权限、强制加密、关闭默认账户这些,一步都不能退让。
