MySQL 本身并不具备直接阻止指定 IP 连接的功能,想要禁止某个 IP 访问 MySQL 服务器,必须借助 iptables 或 firewalld 在网络层拦截 TCP 握手,同时结合 bind-address 与 user@host 的精确匹配,并启用 skip_name_resolve,确保基于 IP 的访问控制判断更准确。

mysql 自身没有“屏蔽指定 IP 连接”的配置选项,仅依赖 GRANT 或 DROP USER 也无法真正阻断 TCP 握手。只要目标 IP 仍能向 3306 端口发送数据包,MySQL 就会响应 SYN,甚至返回 Access denied for user,这反而会暴露数据库服务确实存在。
用 iptables 在网络层 DROP 最有效
这是唯一能够确保对方“根本无法建立连接”的方式,关键在于必须在 TCP 三次握手开始前完成拦截。
iptables -I INPUT -s 203.0.113.45 -p tcp --dport 3306 -j DROP:其中 -I 表示插入到链首,避免被前面已有的 ACCEPT 规则提前放行- 不要遗漏
--dport 3306:如果不指定端口,可能会误伤 SSH、HTTP 等其他服务端口 - 封禁后应立即验证:
telnet 203.0.113.45 3306正常情况下应表现为超时或无响应;如果返回Connection refused,说明 MySQL 已经响应,代表防火墙规则未生效 - 持久化保存:
iptables-sa ve > /etc/iptables/rules.v4(Debian/Ubuntu)或service iptables sa ve(CentOS 6)
firewalld 用户请用 rich rule 拒绝而非丢弃
对于使用 firewalld 的服务器,rich rule 是更常见的做法。其默认策略更偏向“拒绝并返回通知”,便于排查问题;不过在生产环境中,通常建议使用 reject 并配合 --permanent 保存规则。
firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="203.0.113.45" port port="3306" protocol="tcp" reject'- 务必带上
--permanent,否则服务器重启后规则会失效 - 执行
firewall-cmd --reload使配置正式生效 - 测试方法同上:
telnet 203.0.113.45 3306不应获得任何有效响应
别指望 GRANT 或 DROP USER 拦连接请求
这类 MySQL 权限命令只负责控制认证后的登录权限,对连接建立前的握手阶段完全不起作用。常见误区包括:
- 执行
REVOKE ALL ON *.* FROM 'user'@'203.0.113.45':如果这个user@host组合本来就不存在(例如实际只有'user'@'%'),那么这条命令即使不报错,也不会产生实际效果 - 只删除
'root'@'203.0.113.45',却保留了'root'@'%':攻击者依旧可能从该 IP 使用 root 账户登录 MySQL - 误以为
bind_address = 127.0.0.1就万无一失:它只是限制 MySQL 的监听地址,与“禁止某个 IP 访问”不是同一回事;一旦改成0.0.0.0或某个内网 IP,对外访问控制仍然要依赖防火墙策略
Host 字段不是黑名单,是白名单匹配逻辑
MySQL 中的 host 字段本质上表示“允许从哪些来源连接”,属于白名单匹配机制,而不是黑名单拦截逻辑。它仅支持 % 和 _ 这类通配符,并不支持 CIDR、正则表达式或子网掩码。
'app'@'192.168.1.%'会匹配所有以 192.168.1 开头的字符串(包括192.168.1.999,而 MySQL 可能会静默截断为192.168.1.99)'app'@'192.168.1.0/24'属于无效写法,会被 MySQL 当作普通字面量处理,几乎无法匹配成功- 如果希望某个用户只能从指定 IP 连接数据库,就必须显式创建
'app'@'203.0.113.45',并删除所有过于宽泛的账号,例如'app'@'%' - 修改完成后必须执行
FLUSH PRIVILEGES,否则新的权限规则不会立即生效
真正可靠的 MySQL IP 访问控制,始终依赖三层协同:防火墙规则、bind-address 的监听范围,以及 user@host 的精确匹配。任何一层缺失,都可能留下被绕过的风险。尤其要注意 DNS 反向解析带来的干扰——启用 skip_name_resolve=ON 后,MySQL 只会按照原始 IP 进行比对,这样在限制指定 IP 连接 MySQL 时会更稳定、更可控,也更便于运维排查。
