1. MySQL 连接控制(connection_control)介绍

MySQL 服务端包含一个插件库,可以自定义安装各类插件,connection_control 插件也是其中一种,主要用来控制客户端在登录操作连续失败一定次数后的响应的延迟,该插件可有效的防止客户端暴力登录的风险,该插件包含以下两个组件:

  • CONNECTION_CONTROL:用来控制登录失败的次数及延迟响应时间。
  • CONNECTION_CONTROL_FAILED_LOGIN_ATTEMPTS:将登录失败的操作记录至 information_schema系统库中。

连接控制插件文件的基本名称为 connection_control 。每个平台的文件名后缀有所不同(对于 Unix 和类 Unix 系统为 .so ,对于 Windows 为 .dll )。

2. MySQL 连接控制(connection_control)安装

2.1 命令行安装

INSTALL PLUGIN CONNECTION_CONTROL SONAME 'connection_control.so';
INSTALL PLUGIN CONNECTION_CONTROL_FAILED_LOGIN_ATTEMPTS SONAME 'connection_control.so';

示例

# 动态安装 connection_control 插件
mysql> INSTALL PLUGIN CONNECTION_CONTROL SONAME 'connection_control.so';
Query OK, 0 rows affected (0.04 sec)
mysql> INSTALL PLUGIN CONNECTION_CONTROL_FAILED_LOGIN_ATTEMPTS SONAME 'connection_control.so';
Query OK, 0 rows affected (0.01 sec)

2.2 配置文件安装

在MySQL的my.cnf配置文件中增加如下选项,修改完上面的配置文件之后,则需要重新启动MySQL服务。

[mysqld]
plugin-load-add=connection_control.so

2.3 永久启用

为了避免插件的功能被删除,我们可以在MySQL的my.cnf配置文件中声明强制启用“Connection-Control”插件,从而避免被删除。

[mysqld]
plugin-load-add=connection_control.so
connection-control=FORCE_PLUS_PERMANENT
connection-control-failed-login-attempts=FORCE_PLUS_PERMANENT

当增加了上面两行配置之后,再次尝试卸载Connection-Control插件的时候,会出现如下的错误提示:

mysql> uninstall plugin CONNECTION_CONTROL;
ERROR 1702 (HY000): Plugin 'CONNECTION_CONTROL' is force_plus_permanent and can not be unloaded
mysql> uninstall plugin CONNECTION_CONTROL_FAILED_LOGIN_ATTEMPTS;
ERROR 1702 (HY000): Plugin 'CONNECTION_CONTROL_FAILED_LOGIN_ATTEMPTS' is force_plus_permanent and can not be unloaded

3. MySQL 连接控制(connection_control)验证

mysql> select plugin_name, plugin_status, plugin_type, plugin_library load_option from information_schema.plugins where plugin_name like '%CONTROL%' \G
*************************** 1. row ***************************
  plugin_name: CONNECTION_CONTROL
plugin_status: ACTIVE
  plugin_type: AUDIT
  load_option: connection_control.so
*************************** 2. row ***************************
  plugin_name: CONNECTION_CONTROL_FAILED_LOGIN_ATTEMPTS
plugin_status: ACTIVE
  plugin_type: INFORMATION SCHEMA
  load_option: connection_control.so
2 rows in set (0.00 sec)

4. MySQL 连接控制(connection_control)删除

UNINSTALL PLUGIN CONNECTION_CONTROL;
UNINSTALL PLUGIN CONNECTION_CONTROL_FAILED_LOGIN_ATTEMPTS;

示例

mysql> uninstall plugin CONNECTION_CONTROL;
Query OK, 0 rows affected, 1 warning (0.00 sec)
mysql> uninstall plugin CONNECTION_CONTROL_FAILED_LOGIN_ATTEMPTS;
Query OK, 0 rows affected (0.00 sec)

5. 配置用户锁定

5.1 配置参数详解

connection_control_failed_connections_threshold:登陆失败次数限制。
当有任何一次登录成功后,累计失败的值将重新从0开始累计统计。如果这个值设置为0,则表示禁用统计失败的功能。
connection_control_min_connection_delay:查过失败次数后,再登录的时候,最小的重试间隔,单位为毫秒。
connection_control_max_connection_delay:查过失败次数后,再登录的时候,重大的重试间隔,单位为毫秒。取值范围为[1000,2147483647],即为[1秒,24.8天]。

注意事项:

在配置min和max的delay的值的时候,要时刻保证min<=max。比如现在的min和max的值为[1000,2000],如果你想把它们两个的值设置为[3000,5000],我们不能先修改min的值为3000,在修改max的值为5000。因为此时max的值为2000,我们是不能把min的直接设置为3000的。应该先修改max的值为5000,然后再修改min的值为3000

5.2 触发条件配置

在MySQL的配置文件中配置如下:

[mysqld]
# 最多连续4次错误登录
connection_control_failed_connections_threshold=4
# 休眠2000毫秒后再次尝试建立连接
connection_control_min_connection_delay=2000

在MySQL命令行终端中配置如下:

SET GLOBAL connection_control_failed_connections_threshold = 3;
SET GLOBAL connection_control_min_connection_delay = 5000;

注意事项:

如果配置文件和命令行中都设置的对应的值,那么命令行总的设置将会覆盖配置文件中的设置。但是在MySQL服务重启之后,就会再次以配置文件中的设置为准,上次在命令行终端中配置的值将会被舍弃。

示例:

将失败次数阈值设为 10 ,延迟最小时间设为 1 分钟,即当连续连接失败十次后,延迟响应时间最低为 1 分钟

# 初始状态

mysql> show variables like 'connection_control%';
+-------------------------------------------------+------------+
| Variable_name                                   | Value      |
+-------------------------------------------------+------------+
| connection_control_failed_connections_threshold | 10         |
| connection_control_max_connection_delay         | 2147483647 |
| connection_control_min_connection_delay         | 60000      |
+-------------------------------------------------+------------+
3 rows in set (0.01 sec)

mysql> SELECT * FROM information_schema.CONNECTION_CONTROL_FAILED_LOGIN_ATTEMPTS;
Empty set (0.00 sec)



# 故意输错密码
[root@localhost ~]# mysql -utestuser -p123
mysql: [Warning] Using a password on the command line interface can be insecure.
ERROR 1045 (28000): Access denied for user 'testuser'@'localhost' (using password: YES)



# 查看失败记录
mysql> SELECT * FROM information_schema.CONNECTION_CONTROL_FAILED_LOGIN_ATTEMPTS;
+----------------+-----------------+
| USERHOST       | FAILED_ATTEMPTS |
+----------------+-----------------+
| 'testuser'@'%' |               1 |
+----------------+-----------------+
1 row in set (0.00 sec)


# 当连续失败次数超过阈值后 再次进行连接会产生延迟 即延迟一定时间后才会返回密码是否正确

mysql> SELECT * FROM information_schema.CONNECTION_CONTROL_FAILED_LOGIN_ATTEMPTS;
+----------------+-----------------+
| USERHOST       | FAILED_ATTEMPTS |
+----------------+-----------------+
| 'testuser'@'%' |              10 |
+----------------+-----------------+

mysql> show processlist;
+---------+----------+--------------------+--------------------+---------+-------+--------------------------------------+------------------+
| Id      | User     | Host               | db                 | Command | Time  | State                                | Info             |
+---------+----------+--------------------+--------------------+---------+-------+--------------------------------------+------------------+
| 1817003 | root     | localhost          | NULL               | Query   |     0 | starting                             | show processlist |
| 1817091 | testuser | localhost          | NULL               | Connect |    16 | Waiting in connection_control plugin | NULL             |
+---------+----------+--------------------+--------------------+---------+-------+--------------------------------------+------------------+

  正常情况下,输错密码是即刻返回错误的,当连续失败次数达到阈值后,再次进行连接尝试,则会延迟响应,具体表现就是一直卡着,到延迟结束后才返回错误。information_schema 系统库中的表会记录登录失败的用户名及失败次数,当延迟发生时,从 processlist 中也可以查到正在延迟的连接。若输入密码正确,则会取消延迟、重新计数。