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 处理,但不建议依赖该默认行为,建议显式填写 acceptreject

匹配逻辑

黑白名单功能的匹配逻辑如下:

  • 黑名单与白名单都不存在: 允许所有客户端连接。
  • 只有白名单: 仅允许命中白名单规则的客户端连接;未命中的客户端会被拒绝。
  • 只有黑名单: 命中黑名单规则的客户端会被拒绝;未命中的客户端可以连接。
  • 同时存在黑名单与白名单: 先检查黑名单;如果客户端 IP 命中任意黑名单规则,则拒绝连接;如果未命中黑名单规则,则允许连接,此时不会再继续用白名单做限制。

换句话说,在当前实现中:

  • 只要存在黑名单规则,黑名单就具有更高优先级。
  • 当黑名单存在时,白名单不会再对“未命中黑名单的连接”继续收紧范围。

规则格式要求

mysql.whitelist.list 字段中的规则需要满足以下要求:

  • 必须使用 CIDR 格式,例如 10.2.106.0/2410.2.106.238/322001: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/242001:db8::/32 都可以使用。
  • action = NULL 当前实现按 accept 处理,但建议显式设置为 acceptreject
  • 拒绝连接时的客户端报错信息可能不同: 不同客户端工具、不同操作系统下,可能表现为连接失败、握手失败或连接中断类错误。
  • 规则变更后的生效方式: 当前文档暂不展开说明规则修改后的在线生效行为,建议在实际使用前先结合当前版本验证。

排查建议

如果发现规则未按预期生效,可以按以下方式检查:

SHOW GLOBAL VARIABLES LIKE 'pkdb_whitelist'; SELECT id, name, list, action FROM mysql.whitelist;

同时建议检查 TiDB Server 日志,确认是否存在因黑白名单拒绝连接的记录。

相关文档