为了进一步保护我们的MySQL
数据库不被恶意攻击,我们可以给MySQL的登录用户增加一个保护的功能:当某一个用户输入错误密码的次数超过指定的值后,禁止这个用户再次马上发起连接请求,这个禁止的时间长短可以灵活配置,不让其再次尝试登录,从而避免用户的密码被暴力的破解。
我自己首先的疑惑是:MySQL支持这样的功能吗?答案是肯定的,MySQL
官方文档中有这样一段描述:
As of MySQL 5.7.17, MySQL Server includes a plugin library that enables administrators to introduce an increasing delay in server response to connection attempts after a configurable number of consecutive failed attempts. This capability provides a deterrent that slows down brute force attacks against MySQL user accounts. The plugin library contains two plugins:
- CONNECTION_CONTROL
checks incoming connection attempts and adds a delay to server responses as necessary. This plugin also exposes system variables that enable its operation to be configured and a status variable that provides rudimentary monitoring information.
The CONNECTION_CONTROL
plugin uses the audit plugin interface (see Writing Audit Plugins). To collect information, it subscribes to the MYSQL_AUDIT_CONNECTION_CLASSMASK
event class, and processes MYSQL_AUDIT_CONNECTION_CONNECT
and MYSQL_AUDIT_CONNECTION_CHANGE_USER
subevents to check whether the server should introduce a delay before responding to connection attempts.- CONNECTION_CONTROL_FAILED_LOGIN_ATTEMPTS
implements an INFORMATION_SCHEMA
table that exposes more detailed monitoring information for failed connection attempts.
从上面的描述中,我们可以看出这种功能在安装完成MySQL
之后是不会默认就开启的,并且这种功能是以一种插件的方式来安装到MySQL
中的。
注意:上面的两个插件CONNECTION_CONTROL
和CONNECTION_CONTROL_FAILED_LOGIN_ATTEMPTS
都需要安装才可以实现前面我们描述的需求,两者不可或缺。
所以,我们如果想要开启这个功能,前提是我们先在我们的MySQL
服务中安装这个功能插件,然后在开启这个功能。接下里然我们一起安装并且启用这个插件吧。
MySQL官方安装示例说明
在开始安装我们的Connection-Control
插件之前,我们先看下我们的MySQL
默认是安装了哪些插件。我们可以使用如下两个中的任何一个命令查看已经安装的插件有哪些。
第一个命令是显示简单的插件信息,第二个命令可以查看更详细的插件信息。
show plugins;
select * from information_schema.plugins;
示例如下:
mysql> show plugins;
+------------------------------------------+----------+--------------------+-----------------------+---------+
| Name | Status | Type | Library | License |
+------------------------------------------+----------+--------------------+-----------------------+---------+
| binlog | ACTIVE | STORAGE ENGINE | NULL | GPL |
| mysql_native_password | ACTIVE | AUTHENTICATION | NULL | GPL |
| sha256_password | ACTIVE | AUTHENTICATION | NULL | GPL |
| CSV | ACTIVE | STORAGE ENGINE | NULL | GPL |
| MEMORY | ACTIVE | STORAGE ENGINE | NULL | GPL |
| InnoDB | ACTIVE | STORAGE ENGINE | NULL | GPL |
| INNODB_TRX | ACTIVE | INFORMATION SCHEMA | NULL | GPL |
| INNODB_LOCKS | ACTIVE | INFORMATION SCHEMA | NULL | GPL |
| INNODB_LOCK_WAITS | ACTIVE | INFORMATION SCHEMA | NULL | GPL |
| INNODB_CMP | ACTIVE | INFORMATION SCHEMA | NULL | GPL |
| INNODB_CMP_RESET | ACTIVE | INFORMATION SCHEMA | NULL | GPL |
| INNODB_CMPMEM | ACTIVE | INFORMATION SCHEMA | NULL | GPL |
| INNODB_CMPMEM_RESET | ACTIVE | INFORMATION SCHEMA | NULL | GPL |
| INNODB_CMP_PER_INDEX | ACTIVE | INFORMATION SCHEMA | NULL | GPL |
| INNODB_CMP_PER_INDEX_RESET | ACTIVE | INFORMATION SCHEMA | NULL | GPL |
| INNODB_BUFFER_PAGE | ACTIVE | INFORMATION SCHEMA | NULL | GPL |
| INNODB_BUFFER_PAGE_LRU | ACTIVE | INFORMATION SCHEMA | NULL | GPL |
| INNODB_BUFFER_POOL_STATS | ACTIVE | INFORMATION SCHEMA | NULL | GPL |
| INNODB_TEMP_TABLE_INFO | ACTIVE | INFORMATION SCHEMA | NULL | GPL |
| INNODB_METRICS | ACTIVE | INFORMATION SCHEMA | NULL | GPL |
| INNODB_FT_DEFAULT_STOPWORD | ACTIVE | INFORMATION SCHEMA | NULL | GPL |
| INNODB_FT_DELETED | ACTIVE | INFORMATION SCHEMA | NULL | GPL |
| INNODB_FT_BEING_DELETED | ACTIVE | INFORMATION SCHEMA | NULL | GPL |
| INNODB_FT_CONFIG | ACTIVE | INFORMATION SCHEMA | NULL | GPL |
| INNODB_FT_INDEX_CACHE | ACTIVE | INFORMATION SCHEMA | NULL | GPL |
| INNODB_FT_INDEX_TABLE | ACTIVE | INFORMATION SCHEMA | NULL | GPL |
| INNODB_SYS_TABLES | ACTIVE | INFORMATION SCHEMA | NULL | GPL |
| INNODB_SYS_TABLESTATS | ACTIVE | INFORMATION SCHEMA | NULL | GPL |
| INNODB_SYS_INDEXES | ACTIVE | INFORMATION SCHEMA | NULL | GPL |
| INNODB_SYS_COLUMNS | ACTIVE | INFORMATION SCHEMA | NULL | GPL |
| INNODB_SYS_FIELDS | ACTIVE | INFORMATION SCHEMA | NULL | GPL |
| INNODB_SYS_FOREIGN | ACTIVE | INFORMATION SCHEMA | NULL | GPL |
| INNODB_SYS_FOREIGN_COLS | ACTIVE | INFORMATION SCHEMA | NULL | GPL |
| INNODB_SYS_TABLESPACES | ACTIVE | INFORMATION SCHEMA | NULL | GPL |
| INNODB_SYS_DATAFILES | ACTIVE | INFORMATION SCHEMA | NULL | GPL |
| INNODB_SYS_VIRTUAL | ACTIVE | INFORMATION SCHEMA | NULL | GPL |
| MyISAM | ACTIVE | STORAGE ENGINE | NULL | GPL |
| MRG_MYISAM | ACTIVE | STORAGE ENGINE | NULL | GPL |
| PERFORMANCE_SCHEMA | ACTIVE | STORAGE ENGINE | NULL | GPL |
| ARCHIVE | ACTIVE | STORAGE ENGINE | NULL | GPL |
| BLACKHOLE | ACTIVE | STORAGE ENGINE | NULL | GPL |
| FEDERATED | DISABLED | STORAGE ENGINE | NULL | GPL |
| partition | ACTIVE | STORAGE ENGINE | NULL | GPL |
| ngram | ACTIVE | FTPARSER | NULL | GPL |
| validate_password | ACTIVE | VALIDATE PASSWORD | validate_password.so | GPL |
+------------------------------------------+----------+--------------------+-----------------------+---------+
45 rows in set (0.00 sec)
从上面的结果可以看出,像mysql_native_password
、sha256_password
这些关于MySQL
用户密码的插件已经是默认安装并启用的。另外,我们都知道MySQL整体架构分为服务层和存储引擎层,而存储引擎是以插件的方式来安装在MySQL中的。从上面的结果中也可以印证这一个概念,上面我们看到有各种存储引擎,像:CSV
、InnoDB
、MEMORY
、MyISAM
、ARCHIVE等存储引擎都在插件列表中。
我们安装了插件之后,这些插件要存在于MySQL数据库服务器上面的某个目录下面,这样这些插件才能工作,那么安装这些被插件都放在哪里了呢?如果你也有这个好奇的想法,可以通过如下的命令来查看plugin_dir的值即可:
mysql> show variables like 'plugin_dir';
+---------------+--------------------------+
| Variable_name | Value |
+---------------+--------------------------+
| plugin_dir | /usr/lib64/mysql/plugin/ |
+---------------+--------------------------+
1 row in set (0.00 sec)
我们也可以到这个plugin_dir目录下面看下到底有哪些东西。在Linux服务上面进入plugin_dir,显示如下:
[root@xxx plugin]# ll -h
total 59M
-rwxr-xr-x 1 root root 102K Jun 2 2020 adt_null.so
-rwxr-xr-x 1 root root 349K Jun 2 2020 authentication_ldap_sasl_client.so
-rwxr-xr-x 1 root root 43K Jun 2 2020 auth_socket.so
-rwxr-xr-x 1 root root 919K Jun 2 2020 connection_control.so
drwxr-xr-x 2 root root 4.0K May 20 2021 debug
-rwxr-xr-x 1 root root 21M Jun 2 2020 group_replication.so
-rwxr-xr-x 1 root root 473K Jun 2 2020 ha_example.so
-rwxr-xr-x 1 root root 946K Jun 2 2020 innodb_engine.so
-rwxr-xr-x 1 root root 938K Jun 2 2020 keyring_file.so
-rwxr-xr-x 1 root root 451K Jun 2 2020 keyring_udf.so
-rwxr-xr-x 1 root root 1.3M Jun 2 2020 libmemcached.so
-rwxr-xr-x 1 root root 8.6M Jun 2 2020 libpluginmecab.so
-rwxr-xr-x 1 root root 21K Jun 2 2020 locking_service.so
-rwxr-xr-x 1 root root 53K Jun 2 2020 mypluglib.so
-rwxr-xr-x 1 root root 41K Jun 2 2020 mysql_no_login.so
-rwxr-xr-x 1 root root 22M Jun 2 2020 mysqlx.so
-rwxr-xr-x 1 root root 49K Jun 2 2020 rewrite_example.so
-rwxr-xr-x 1 root root 578K Jun 2 2020 rewriter.so
-rwxr-xr-x 1 root root 913K Jun 2 2020 semisync_master.so
-rwxr-xr-x 1 root root 157K Jun 2 2020 semisync_slave.so
-rwxr-xr-x 1 root root 205K Jun 2 2020 validate_password.so
-rwxr-xr-x 1 root root 494K Jun 2 2020 version_token.so
安装后的插件的后缀名称根据平台的不同而不同,Unix/Linux系统下,插件安装后的文件会以.so的文件存放于plugin_dir目录下面,而在Windows平台下面,则会有.dll的文件存在于plugin_dir目录下面。
我们在Linux服务器上面来安装,那么Connection-Control插件文件名称就是connection_control.so。
如果我们想在不停止MySQL对外提供访问服务的前提下来安装插件,此时,我们可以使用下面的SQL命令来安装我们需要的插件。
INSTALL PLUGIN CONNECTION_CONTROL SONAME 'connection_control.so';
INSTALL PLUGIN CONNECTION_CONTROL_FAILED_LOGIN_ATTEMPTS SONAME 'connection_control.so';
同理,卸载这两个插件的命令如下所示:
UNINSTALL PLUGIN CONNECTION_CONTROL;
UNINSTALL PLUGIN CONNECTION_CONTROL_FAILED_LOGIN_ATTEMPTS;
安装和卸载的示例如下:
mysql> INSTALL PLUGIN CONNECTION_CONTROL SONAME 'connection_control.so';
Query OK, 0 rows affected (0.22 sec)
mysql> INSTALL PLUGIN CONNECTION_CONTROL_FAILED_LOGIN_ATTEMPTS SONAME 'connection_control.so';
Query OK, 0 rows affected (0.05 sec)
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)
此时我们再去information_schema.plugins
表中查看一下已经安装的插件有哪些,结果如下:
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)
从上面的结果中可以看出已经包含了我们要安装的两个插件:CONNECTION_CONTROL
和CONNECTION_CONTROL_FAILED_LOGIN_ATTEMPTS
。此时说明我们已经安装成功了Connection-Control插件。
除了直接通过命令安装Connection-Control插件之外,我们还可以在MySQL的配置文件my.cnf
中配置启动选项。这样,MySQL在启动的时候就可以自动加载Connection-Control插件了。
在MySQL的my.cnf配置文件中增加如下选项:
[mysqld]
plugin-load-add=connection_control.so
注意:修改完上面的配置文件之后,想要使此次的修改生效,则需要重新启动MySQL服务。具体重启MySQL服务的方式参考如下命令:
systemctl restart mysqld
通过上面的install plugin的命令或者修改my.cnf配置文件来安装Connection-Control插件之后,在MySQL运行的过程中,可以通过uninstall plugin的命令删除安装的插件。
为了避免插件的功能被删除,我们可以在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
安装启用Connection-Control
功能之后,接下来我们开始配置用户在连接失败多少次之后,禁止用户登录。
在配置之前,我们先来了解一下下面这几个参数。
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
这里的配置也可以在配置文件my.cnf
中配置,也可以在MySQL的命令终端中使用set global key=value
的方式来配置。
在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服务重启之后,就会再次以配置文件中的设置为准,上次在命令行终端中配置的值将会被舍弃。
通过上面的示例我们可以看到,Connection-Control
插件对连续失败登录控制有效果的,这样做可以避免了大量的、非法连接攻击,避免了暴力破击我们的MySQL数据库密码的可能性。增加了数据库的安全系数。
原文链接