数据库端口暴露在公网上,无异于把保险柜放在大街上。攻击者使用的扫描工具可以在24小时内遍历全部IPv4地址空间,一旦发现默认端口响应,就会立即启动漏洞利用程序。这不是概率问题,而是时间问题。解决这个问题的核心思路只有一条:让端口从公网上消失,同时对内网访问保持可用。下面直接讲具体怎么做。

更改默认端口是第一步,但别指望它保平安

MySQL默认3306,PostgreSQL默认5432,SQL Server默认1433,Oracle默认1521,Redis默认6379,MongoDB默认27017。这些数字在攻击者眼里就是明牌。修改默认端口能过滤掉90%以上的自动化扫描,因为大多数扫描脚本只探测常见端口。以MySQL为例,编辑配置文件/etc/mysql/mysql.conf.d/mysqld.cnf,找到port = 3306这一行,改成五位数以上的高位端口,比如40001。改完后重启服务,立即用netstat -tlnp检查新端口是否生效。但要注意,端口号不要超过65535,也不要使用1024以下的系统保留端口。修改端口后,所有客户端连接字符串都得同步更新,这个工作量在大型集群里不小,所以很多团队偷懒不干。实际上,用配置管理工具批量下发新连接串,半小时就能搞定。改端口是成本最低的防护手段,但它只能防扫描,防不住针对特定IP的端口全量探测。如果攻击者铁了心要搞你,用nmap -p 1-65535扫一遍,你的高位端口照样暴露。所以这只是第一层过滤,不能当作唯一防线。

绑定内网IP,让数据库只监听本地回环或内网地址

数据库安装后默认往往监听0.0.0.0,也就是所有网络接口。这意味着只要服务器有公网IP,数据库端口就直接暴露。修改配置文件里的bind-address参数,把它设置为127.0.0.1或者内网IP地址,比如192.168.1.100。以PostgreSQL为例,postgresql.conf里listen_addresses = 'localhost'就只允许本机连接。如果应用服务器和数据库不在同一台机器上,就设置为内网IP,确保数据库只监听内网网卡。改完后重启数据库,用外部IP测试连接,应该直接拒绝。这个操作简单到离谱,但大量生产环境就是没做。很多云服务器默认给了公网IP,用户装完数据库直接就用,等于把数据库挂在了公网上。绑定内网IP后,即使防火墙规则配错了,数据库也不会响应公网请求,多了一层兜底保护。

用iptables或云安全组做IP白名单,从网络层直接掐断

操作系统层面的防火墙规则是最硬的防线。iptables可以精确到源IP和端口,只放行业务服务器的IP访问数据库端口。假设数据库端口是40001,业务服务器IP是192.168.1.10和192.168.1.11,规则这样写:

iptables -A INPUT -p tcp -s 192.168.1.10 --dport 40001 -j ACCEPT
iptables -A INPUT -p tcp -s 192.168.1.11 --dport 40001 -j ACCEPT
iptables -A INPUT -p tcp --dport 40001 -j DROP

顺序很重要,先放行白名单IP,最后一条DROP掉所有其他来源的请求。保存规则用iptables-save,确保重启后不丢失。如果是云环境,直接在安全组里配置入方向规则,只允许业务子网的IP段访问数据库端口,其他全部拒绝。安全组比iptables更优先,流量还没到服务器就被拦截了。很多人只配了安全组就以为万事大吉,但安全组规则一旦被人误删或者API泄露被篡改,数据库就裸奔了。所以安全组和iptables双保险才是正确姿势。另外,白名单要定期审计,离职员工的IP、下线的服务器IP要及时剔除。

SSH隧道和VPN组网,让数据库端口彻底从公网消失

如果业务服务器和数据库服务器不在同一个内网,比如跨机房或者混合云架构,直接暴露数据库端口风险太大。用SSH隧道可以建立一个加密的转发通道。在业务服务器上执行:

ssh -L 40001:127.0.0.1:40001 -N -f dbuser@数据库服务器IP

这条命令把本地40001端口映射到数据库服务器的40001端口,业务代码连接127.0.0.1:40001就等于连接远程数据库,所有流量走SSH加密通道,数据库服务器上根本不需要开放40001端口给公网。生产环境建议用autossh保持隧道不断线。如果业务规模大,可以用WireGuard或者ZeroTier组建虚拟内网,把所有服务器放进同一个加密网络里,数据库端口只在这个虚拟网卡上监听。这样做的好处是数据库完全不需要公网IP,端口扫描工具连目标都找不到。组网时注意密钥管理,私钥泄露等于内网大门敞开。

端口敲门技术,让端口平时处于隐身状态

端口敲门是一种更高级的隐藏手段。数据库端口默认被防火墙DROP,外部扫描时就像不存在一样。只有按特定顺序访问几个指定端口后,防火墙才临时放行数据库端口给这个来源IP。比如设定敲门序列为访问10001、10002、10003端口,用knockd实现:

[options]
UseSyslog

[openSSH]
sequence = 10001,10002,10003
seq_timeout = 10
command = /sbin/iptables -A INPUT -s %IP% -p tcp --dport 40001 -j ACCEPT
tcpflags = syn

[closeSSH]
sequence = 10003,10002,10001
seq_timeout = 10
command = /sbin/iptables -D INPUT -s %IP% -p tcp --dport 40001 -j ACCEPT
tcpflags = syn

业务服务器连接数据库前,先用knock客户端发送敲门包,端口打开后再连接。连接结束后再发一次关门序列,端口重新隐藏。这个机制对自动化扫描几乎免疫,因为扫描器不知道敲门序列。但敲门序列本身是明文传输的,如果攻击者抓包分析就能发现规律。所以端口敲门适合作为额外防护层,不能替代加密和认证。另外,敲门序列要定期更换,避免被暴力枚举。

数据库审计日志实时监控,异常连接秒级告警

前面讲的都是预防措施,但万一被突破了怎么办?数据库自带的审计功能必须开起来。MySQL的general_log记录所有连接和查询,虽然性能有影响,但安全敏感场景值得开。更精细的做法是用audit plugin,只记录登录失败、权限变更、DDL操作等关键事件。PostgreSQL的pgAudit扩展可以按会话或对象级别审计。关键是要把审计日志实时输出到集中日志平台,比如ELK或者Loki,然后配置告警规则:来自非白名单IP的连接尝试、连续登录失败超过3次、非业务时间段的数据库访问、执行了drop table或truncate等危险操作,这些情况立即推送告警到运维群。很多入侵事件都是在日志里躺了几个月才被发现,实时告警能把响应时间从月级压缩到分钟级。

账户权限最小化,每个应用只给必要的权限

就算端口被扫到、密码被猜出来,如果账户权限做了严格限制,损失也能控制在最小范围。绝对不要给应用程序用root或者superuser账号。每个微服务或应用模块单独建账号,只授予对应数据库的CRUD权限,禁止DDL操作。MySQL里这样授权:

GRANT SELECT, INSERT, UPDATE, DELETE ON app_db.* TO 'app_user'@'192.168.1.10' IDENTIFIED BY '强密码';

注意限制来源IP,即使密码泄露,攻击者从其他IP也连不上。定期审查用户权限,用SHOW GRANTS检查是否有不必要的WITH GRANT OPTION或者全局权限。生产环境禁止使用%通配符作为允许连接的主机,必须精确到IP或子网。

连接加密不能省,防止中间人嗅探

即使在内网,流量也可能被镜像或劫持。数据库连接强制启用TLS加密,MySQL和PostgreSQL都支持。以MySQL为例,在配置文件中指定证书路径:

[mysqld]
ssl-ca=/etc/mysql/certs/ca.pem
ssl-cert=/etc/mysql/certs/server-cert.pem
ssl-key=/etc/mysql/certs/server-key.pem
require_secure_transport=ON

客户端连接时加上ssl-mode=VERIFY_IDENTITY参数,确保证书校验通过才建立连接。这样即使攻击者在内网抓包,看到的也是加密数据。证书管理可以用自建CA或者Let's Encrypt,但要注意证书过期自动续期,避免业务中断。

定期渗透测试,用攻击者的视角检验防护效果

自己觉得防护到位不算数,得用真实攻击手法验证。用nmap扫描公网IP,确认数据库端口确实不响应。用masscan做全端口扫描,看高位端口是否隐藏到位。用hydra对发现的端口做弱口令爆破,检验密码强度和账户锁定策略。用sqlmap测试应用接口是否存在SQL注入,因为注入漏洞可以让攻击者绕过所有网络层防护直接操作数据库。渗透测试至少每季度做一次,每次发版后针对新接口重点测。发现的漏洞要建立修复时间表,高危漏洞24小时内必须修复。

最后一道防线:备份和灾难恢复

防护做得再好,也不能保证100%安全。数据库被删库的事件时有发生,有些是外部攻击,有些是内部误操作或者恶意破坏。定时备份是最后的救命稻草。备份策略要满足3-2-1原则:至少3份副本,存储在2种不同介质上,其中1份在异地。备份文件要加密,防止泄露后被直接还原。定期做恢复演练,验证备份文件确实可用。很多团队天天备份,真到恢复时发现备份文件损坏或者恢复流程不熟,白白浪费时间。恢复演练至少每半年做一次,记录恢复耗时,纳入运维SLA。

数据库端口隐藏与防护不是单一技术点,而是一个纵深防御体系。从端口隐藏、网络隔离、访问控制、传输加密到审计监控,每一层都在增加攻击成本。攻击者面对多层防护,大概率会转向更容易的目标。把这些措施落实到位,数据库被扫描攻击成功的概率可以降到极低。