TiDB 数据库基于客户端 IP 的黑白名单访问控制
TiDB 数据库支持基于客户端来源 IP 的访问控制。开启黑白名单功能后,可以通过系统表 mysql.whitelist 配置允许或拒绝连接的 IP 网段,从而限制哪些客户端可以连接到当前 TiDB Server。
这个功能适用于需要按来源地址控制数据库接入范围的场景。例如:
- 只允许办公网段或业务网段的客户端连接数据库。
- 阻止来自特定 IP 网段的客户端连接数据库。
- 在同一套规则中同时配置允许与拒绝项,其中拒绝规则优先。
使用前提与开启方式
使用该功能前,需要满足以下条件:
- 全局系统变量
pkdb_whitelist已开启。 - 已在系统表
mysql.whitelist中配置黑白名单规则。
部署时开启插件
在 TiDB 配置文件中开启 enable-whitelist-plugin:
enable-whitelist-plugin = true
客户端中开启全局系统变量
可以通过以下语句查看并开启全局系统变量:
SHOW GLOBAL VARIABLES LIKE 'pkdb_whitelist';
SET GLOBAL pkdb_whitelist = ON;
规则表说明
黑名单与白名单规则都存储在系统表 mysql.whitelist 中,通过 action 字段区分规则类型。
通过 SHOW CREATE TABLE mysql.whitelist; 查询到的表结构如下:
CREATE TABLE `whitelist` (
`id` int NOT NULL AUTO_INCREMENT,
`name` varchar(16) DEFAULT NULL,
`list` text DEFAULT NULL,
`action` enum('accept','reject') DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `name` (`name`)
);
各字段的含义如下:
id:规则 ID,自增主键。name:规则名称,仅用于标识和管理规则,不参与匹配逻辑。list:IP 规则列表,使用 CIDR 格式表示,可填写一个或多个网段,多个网段使用英文逗号分隔。action:规则动作。accept:白名单规则。reject:黑名单规则。NULL:当前实现中按accept处理,但不建议依赖该默认行为,建议显式填写accept或reject。
匹配逻辑
黑白名单功能的匹配逻辑如下:
- 黑名单与白名单都不存在: 允许所有客户端连接。
- 只有白名单: 仅允许命中白名单规则的客户端连接;未命中的客户端会被拒绝。
- 只有黑名单: 命中黑名单规则的客户端会被拒绝;未命中的客户端可以连接。
- 同时存在黑名单与白名单: 先检查黑名单;如果客户端 IP 命中任意黑名单规则,则拒绝连接;如果未命中黑名单规则,则允许连接,此时不会再继续用白名单做限制。
换句话说,在当前实现中:
- 只要存在黑名单规则,黑名单就具有更高优先级。
- 当黑名单存在时,白名单不会再对“未命中黑名单的连接”继续收紧范围。
规则格式要求
mysql.whitelist.list 字段中的规则需要满足以下要求:
- 必须使用 CIDR 格式,例如
10.2.106.0/24、10.2.106.238/32、2001:db8::/32。 - 支持同时配置多个 CIDR,多个规则之间使用英文逗号分隔。
- 支持 IPv4 和 IPv6。
- 不建议填写裸 IP,例如
10.2.106.238。当前实现会将这类值视为无效规则并忽略。
SQL 示例
以下示例使用两个客户端地址说明规则行为:
- 客户端 A:
10.2.106.10,命中10.2.106.0/24 - 客户端 B:
10.2.100.10,不命中10.2.106.0/24
示例 1:只有白名单
先开启黑白名单功能,并清空旧规则:
SET GLOBAL pkdb_whitelist = ON;
DELETE FROM mysql.whitelist;
插入白名单规则:
INSERT INTO mysql.whitelist(name, list, action)
VALUES ('office_net', '10.2.106.0/24', 'accept');
查看当前规则:
SELECT id, name, list, action FROM mysql.whitelist;
返回结果类似如下:
+----+------------+---------------+--------+
| id | name | list | action |
+----+------------+---------------+--------+
| 1 | office_net | 10.2.106.0/24 | accept |
+----+------------+---------------+--------+
连接结果如下:
- 客户端 A: 命中白名单规则,允许连接。
- 客户端 B: 未命中白名单规则,拒绝连接。
示例 2:只有黑名单
先清空旧规则:
DELETE FROM mysql.whitelist;
插入黑名单规则:
INSERT INTO mysql.whitelist(name, list, action)
VALUES ('blocked_net', '10.2.106.0/24', 'reject');
查看当前规则:
SELECT id, name, list, action FROM mysql.whitelist;
返回结果类似如下:
+----+-------------+---------------+--------+
| id | name | list | action |
+----+-------------+---------------+--------+
| 2 | blocked_net | 10.2.106.0/24 | reject |
+----+-------------+---------------+--------+
连接结果如下:
- 客户端 A: 命中黑名单规则,拒绝连接。
- 客户端 B: 未命中黑名单规则,允许连接。
示例 3:同时存在黑名单与白名单
先清空旧规则:
DELETE FROM mysql.whitelist;
同时插入白名单和黑名单规则:
INSERT INTO mysql.whitelist(name, list, action)
VALUES
('allow_net', '10.2.106.0/24', 'accept'),
('deny_host', '10.2.106.10/32', 'reject');
查看当前规则:
SELECT id, name, list, action FROM mysql.whitelist;
返回结果类似如下:
+----+-----------+----------------+--------+
| id | name | list | action |
+----+-----------+----------------+--------+
| 1 | allow_net | 10.2.106.0/24 | accept |
| 2 | deny_host | 10.2.106.10/32 | reject |
+----+-----------+----------------+--------+
连接结果如下:
- 客户端
10.2.106.10: 命中黑名单规则,拒绝连接。 - 客户端
10.2.106.20: 未命中黑名单规则,允许连接。 - 客户端
10.2.100.10: 未命中黑名单规则,允许连接。
从这个示例可以看到,当黑名单与白名单同时存在时,系统会先检查黑名单;只要没有命中黑名单,连接就会被放行,而不会再继续按白名单限制。
注意事项与限制
- 该功能只控制新建连接: 黑白名单检查发生在客户端建立连接的阶段,已经建立的连接不会因此被主动断开。
- 规则匹配基于客户端来源 IP: 规则表中的
name字段不参与连接匹配。 - 规则格式必须为 CIDR: 裸 IP 不带掩码的写法不会按有效规则处理。
- 支持 IPv4 和 IPv6: 例如
10.2.106.0/24和2001:db8::/32都可以使用。 action = NULL: 当前实现按accept处理,但建议显式设置为accept或reject。- 拒绝连接时的客户端报错信息可能不同: 不同客户端工具、不同操作系统下,可能表现为连接失败、握手失败或连接中断类错误。
- 规则变更后的生效方式: 当前文档暂不展开说明规则修改后的在线生效行为,建议在实际使用前先结合当前版本验证。
排查建议
如果发现规则未按预期生效,可以按以下方式检查:
SHOW GLOBAL VARIABLES LIKE 'pkdb_whitelist';
SELECT id, name, list, action FROM mysql.whitelist;
同时建议检查 TiDB Server 日志,确认是否存在因黑白名单拒绝连接的记录。