6.4.6.3 使用 MySQL 企业防火墙

在使用 MySQL 企业防火墙之前,请按照第 6.4.6.2 节“安装或卸载 MySQL 企业防火墙”中提供的说明进行安装。另外,MySQL Enterprise Firewall 不能与查询缓存一起使用。禁用查询缓存(如果已启用)(请参见第 8.10.3.3 节“查询缓存配置”)。

本节介绍如何使用 SQL 语句配置 MySQL 企业防火墙。另外,MySQL Workbench 6.3.4 或更高版本提供了用于防火墙控制的图形界面。参见MySQL 企业防火墙接口

要启用或禁用防火墙,请设置mysql_firewall_mode系统变量。默认情况下,在安装防火墙时启用此变量。要显式控制防火墙的初始状态,可以在服务器启动时设置变量。例如,要在选项文件中启用防火墙,请使用以下几行:

[mysqld]
mysql_firewall_mode=ON

也可以在运行时禁用或启用防火墙:

mysql> SET GLOBAL mysql_firewall_mode = OFF;
mysql> SET GLOBAL mysql_firewall_mode = ON;

除了全局打开/关闭防火墙模式之外,在防火墙中注册的每个帐户都有其自己的操作模式。对于处于记录方式的帐户,防火墙会学习应用程序的“指纹”,即可接受的语句模式,这些语句模式一起构成白名单。经过培训后,将防火墙切换到保护模式,以使 MySQL 能够防止偏离指纹的语句对 MySQL 的访问。要进行其他培训,请根据需要将防火墙切换回记录模式,以使用新的语句模式更新白名单。可以采用入侵检测模式,将可疑语句写入错误日志,但不拒绝访问。

防火墙按帐户维护白名单规则,从而可以实施以下保护策略:

  • 对于具有独特保护要求的应用程序,请将其配置为使用未用于任何其他目的的帐户。

  • 对于相关且共享保护要求的应用程序,请将它们配置为一组以使用同一帐户。

防火墙操作基于将 SQL 语句转换为规范化摘要形式的操作。防火墙摘要类似于性能模式使用的语句摘要(请参阅第 25.10 节“性能模式语句摘要”)。但是,与性能架构不同,与摘要相关的相关系统变量是max_digest_length

对于来自注册帐户的连接,防火墙会将每个传入的语句转换为规范化形式,并根据帐户模式进行处理:

  • 在记录模式下,防火墙将规范化的语句添加到帐户白名单规则中。

  • 在保护模式下,防火墙将规范化的语句与帐户白名单规则进行比较。如果存在匹配项,则该语句通过,服务器 continue 对其进行处理。否则,服务器将拒绝该语句,并向 Client 端返回错误。如果启用了mysql_firewall_trace系统变量,则防火墙还将拒绝的语句写入错误日志。

  • 在检测模式下,防火墙像在保护模式下一样匹配语句,但是在不拒绝访问的情况下将不匹配的语句写入错误日志。

模式为OFF或未在防火墙中注册的帐户将被其忽略。

要使用 MySQL 企业防火墙保护帐户,请按照以下步骤操作:

  • 注册该帐户并将其置于记录模式。

  • 使用注册的帐户连接到 MySQL 服务器并执行要学习的语句。这将构建该帐户的已接受对帐单白名单。

  • 将注册帐户切换为保护模式。

以下示例显示了如何在防火墙中注册帐户,如何使用防火墙了解该帐户的可接受语句,以及如何防止执行不可接受的语句。示例帐户'fwuser'@'localhost'可供访问sakila数据库中 table 的应用程序使用。 (此数据库位于https://dev.mysql.com/doc/index-other.html。)

Note

帐户名的用户名和主机名分别用之类的语句引起来,而要指定用于防火墙组件的帐户,请将其命名为单引号'fwuser@localhost'

将帐户命名为防火墙组件的单引号字符串的约定意味着您不能使用在用户名中嵌入了@字符的帐户。

使用 Management 的 MySQL 帐户执行以下过程中的步骤,但指定给由防火墙注册的帐户执行的帐户除外。对于使用注册帐户执行的语句,默认数据库应为sakila

  • 如有必要,创建要保护的帐户(选择适当的密码)并授予其对sakila数据库的特权:
mysql> CREATE USER 'fwuser'@'localhost' IDENTIFIED BY 'fWp@3sw0rd';
mysql> GRANT ALL ON sakila.* TO 'fwuser'@'localhost';
  • 使用sp_set_firewall_mode()存储过程在防火墙中注册该帐户并将其置于记录模式(如果该过程位于mysql以外的数据库中,请相应地调整该语句):
mysql> CALL mysql.sp_set_firewall_mode('fwuser@localhost', 'RECORDING');

在执行过程中,存储过程将调用防火墙用户定义的函数,这些函数可能会产生自己的输出。

  • 使用注册的帐户,连接到服务器,然后执行一些对其合法的语句:
mysql> SELECT first_name, last_name FROM customer WHERE customer_id = 1;
mysql> UPDATE rental SET return_date = NOW() WHERE rental_id = 1;
mysql> SELECT get_customer_balance(1, NOW());

防火墙将这些语句转换为摘要形式,并将其记录在帐户白名单中。

Note

在帐户以记录模式执行报 table 之前,其白名单为空,等同于“全部拒绝”。如果切换到保护模式,则将有效地禁止该帐户执行语句。

  • 此时,用户和白名单信息已缓存,可以在防火墙INFORMATION_SCHEMAtable 中看到:
mysql> SELECT MODE FROM INFORMATION_SCHEMA.MYSQL_FIREWALL_USERS
       WHERE USERHOST = 'fwuser@localhost';
+-----------+
| MODE      |
+-----------+
| RECORDING |
+-----------+
mysql> SELECT RULE FROM INFORMATION_SCHEMA.MYSQL_FIREWALL_WHITELIST
       WHERE USERHOST = 'fwuser@localhost';
+----------------------------------------------------------------------------+
| RULE                                                                       |
+----------------------------------------------------------------------------+
| SELECT `first_name` , `last_name` FROM `customer` WHERE `customer_id` = ?  |
| SELECT `get_customer_balance` ( ? , NOW ( ) )                              |
| UPDATE `rental` SET `return_date` = NOW ( ) WHERE `rental_id` = ?          |
| SELECT @@`version_comment` LIMIT ?                                         |
+----------------------------------------------------------------------------+

Note

当您以注册用户身份连接到服务器时,@@version_comment规则来自mysqlClient 端自动发送的语句。

在与应用程序使用相匹配的条件下训练防火墙非常重要。例如,给定的 MySQL 连接器可能会在连接开始时向服务器发送语句,以确定服务器的特性和功能。如果通常通过该连接器使用应用程序,则也应以这种方式训练防火墙。这使这些初始报 table 成为与该应用程序关联的帐户的白名单的一部分。

  • 使用存储过程将注册用户切换到保护模式:
mysql> CALL mysql.sp_set_firewall_mode('fwuser@localhost', 'PROTECTING');

Important

将帐户退出RECORDING模式会使其防火墙缓存数据同步到基础mysql系统数据库 table 中,以进行持久存储。如果不为正在记录的用户切换模式,则缓存的白名单数据不会写入系统 table,并且在重新启动服务器时会丢失。

  • 使用注册的帐户,执行一些可接受和不可接受的语句。防火墙将每个白名单与帐户白名单进行匹配,然后接受或拒绝。

该语句与训练语句不同,但是会产生与其中之一相同的规范化语句,因此防火墙接受它:

mysql> SELECT first_name, last_name FROM customer WHERE customer_id = '48';
+------------+-----------+
| first_name | last_name |
+------------+-----------+
| ANN        | EVANS     |
+------------+-----------+

这些语句与白名单中的任何语句都不匹配,并且每个语句都会导致错误:

mysql> SELECT first_name, last_name FROM customer WHERE customer_id = 1 OR TRUE;
ERROR 1045 (28000): Statement was blocked by Firewall
mysql> SHOW TABLES LIKE 'customer%';
ERROR 1045 (28000): Statement was blocked by Firewall
mysql> TRUNCATE TABLE mysql.slow_log;
ERROR 1045 (28000): Statement was blocked by Firewall

如果启用了mysql_firewall_trace系统变量,则防火墙还将拒绝的语句写入错误日志。例如:

[Note] Plugin MYSQL_FIREWALL reported:
'ACCESS DENIED for fwuser@localhost. Reason: No match in whitelist.
Statement: TRUNCATE TABLE `mysql` . `slow_log` '

您可以使用这些日志消息来确定攻击源。

  • 您可以将不匹配的语句记录为可疑,而不会拒绝访问。为此,将帐户置于入侵检测模式:
mysql> CALL mysql.sp_set_firewall_mode('fwuser@localhost', 'DETECTING');
  • 使用注册的帐户,连接到服务器,然后执行与白名单不匹配的语句:
mysql> SHOW TABLES LIKE 'customer%';
+------------------------------+
| Tables_in_sakila (customer%) |
+------------------------------+
| customer                     |
| customer_list                |
+------------------------------+

在检测模式下,防火墙允许执行不匹配的语句,但会在错误日志中写入一条消息:

[Note] Plugin MYSQL_FIREWALL reported:
'SUSPICIOUS STATEMENT from 'fwuser@localhost'. Reason: No match in whitelist.
Statement: SHOW TABLES LIKE ? '

Note

检测模式将消息写为 Notes,这是信息消息。为确保此类消息出现在错误日志中并且不会被丢弃,请确保将log_error_verbosity系统变量设置为值 3.

  • 要评估防火墙活动,请检查其状态变量:
mysql> SHOW GLOBAL STATUS LIKE 'Firewall%';
+----------------------------+-------+
| Variable_name              | Value |
+----------------------------+-------+
| Firewall_access_denied     | 3     |
| Firewall_access_granted    | 4     |
| Firewall_access_suspicious | 1     |
| Firewall_cached_entries    | 4     |
+----------------------------+-------+

变量分别 table 示拒绝,接受,记录为可疑以及添加到缓存中的语句数。 Firewall_access_granted计数为 4,这是因为mysqlClient 端发送的@@version_comment语句(您使用它作为注册用户进行连接的 3 次)中的每一次,加上SHOW TABLES语句在DETECTING模式下未被阻止。

如果需要对帐户进行其他培训,请再次将其切换到记录模式,然后在执行要添加到白名单的语句后,再回到保护模式。