Documentation Home
MySQL 8.0 参考手册  / 第 6 章 安全  / 6.4 安全组件和插件  / 6.4.7 MySQL 企业防火墙  /  6.4.6.3 使用 MySQL 企业防火墙

6.4.6.3 使用 MySQL 企业防火墙

在使用 MySQL Enterprise Firewall 之前,请按照第 6.4.6.2 节“安装或卸载 MySQL Enterprise Firewall”中提供的说明进行安装。此外,MySQL Enterprise Firewall 不与查询缓存一起工作;如果启用了查询缓存,则将其禁用(请参阅 第 8.10.3.3 节,“查询缓存配置”)。

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

启用或禁用防火墙

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

[mysqld]
mysql_firewall_mode=ON

修改my.cnf后重启服务器使新设置生效。

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

SET GLOBAL mysql_firewall_mode = OFF;
SET GLOBAL mysql_firewall_mode = ON;
分配防火墙权限

安装防火墙后,将适当的权限授予 MySQL 帐户或用于管理它的帐户:

  • 授予系统数据库EXECUTE中防火墙存储过程的权限 。mysql这些可能会调用管理功能,因此存储过程访问也需要这些功能所需的特权。

  • 授予SUPER权限以便可以执行防火墙管理功能。

防火墙概念

MySQL 服务器允许客户端连接并从它们接收要执行的 SQL 语句。如果启用了防火墙,服务器会将每个不会立即因语法错误而失败的传入语句传递给它。根据防火墙是否接受该语句,服务器执行它或向客户端返回错误。本节描述防火墙如何完成接受或拒绝声明的任务。

防火墙配置文件

防火墙使用配置文件注册表来确定是否允许语句执行。配置文件具有以下属性:

  • 一个许可名单。白名单是一组规则,用于定义配置文件可接受的语句。

  • 当前的操作模式。该模式使配置文件能够以不同的方式使用。例如:可以将配置文件置于训练模式以建立白名单;白名单可用于限制语句执行或入侵检测;该配置文件可以完全禁用。

  • 适用范围。范围指示配置文件适用于哪些客户端连接。

    防火墙支持基于帐户的配置文件,这样每个配置文件都与特定的客户端帐户(客户端用户名和主机名组合)相匹配。例如,您可以注册一个帐户配置文件,其白名单适用于来自 的连接, admin@localhost并注册另一个帐户配置文件,其白名单适用于来自 的连接 myapp@apphost.example.com

最初,不存在配置文件,因此默认情况下,防火墙接受所有语句,并且对 MySQL 帐户可以执行的语句没有影响。要应用防火墙保护功能,需要明确的操作:

  • 向防火墙注册一个或多个配置文件。

  • 通过为每个配置文件建立白名单来训练防火墙;也就是说,配置文件允许客户端执行的语句类型。

  • 将经过训练的配置文件置于保护模式以加强 MySQL 以防止未经授权的语句执行:

    • MySQL 将每个客户端会话与特定的用户名和主机名组合相关联。这种组合就是会话帐户

    • 对于每个客户端连接,防火墙使用会话帐户来确定哪个配置文件适用于处理来自客户端的传入语句。

      防火墙只接受适用的配置文件白名单允许的语句。

防火墙提供的基于配置文件的保护可以实现以下策略:

  • 如果应用程序具有独特的保护要求,请将其配置为使用未用于任何其他目的的帐户,并为该帐户设置配置文件。

  • 如果相关应用程序共享保护要求,请将它们全部配置为使用相同的帐户(因此使用相同的帐户配置文件)。

防火墙语句匹配

防火墙执行的语句匹配不使用从客户端收到的 SQL 语句。相反,服务器将传入的语句转换为规范化的摘要形式,防火墙操作使用这些摘要。语句规范化的好处是它可以使用单一模式对相似的语句进行分组和识别。例如,这些语句彼此不同:

SELECT first_name, last_name FROM customer WHERE customer_id = 1;
select first_name, last_name from customer where customer_id = 99;
SELECT first_name, last_name FROM customer WHERE customer_id = 143;

但它们都具有相同的规范化摘要形式:

SELECT `first_name` , `last_name` FROM `customer` WHERE `customer_id` = ?

通过使用规范化,防火墙白名单可以存储摘要,每个摘要与从客户端收到的许多不同语句相匹配。有关规范化和摘要的更多信息,请参阅第 25.10 节,“性能模式语句摘要”

警告

max_digest_length系统变量设置为零会禁用摘要生成,这也会禁用需要摘要的服务器功能,例如 MySQL Enterprise Firewall。

配置文件操作模式

向防火墙注册的每个配置文件都有自己的操作模式,可从以下值中选择:

  • OFF:此模式禁用配置文件。防火墙认为它处于非活动状态并忽略它。

  • RECORDING:这是防火墙训练模式。从与配置文件匹配的客户端收到的传入语句被认为是配置文件可接受的,并成为其指纹”的一部分。 防火墙记录每个语句的规范化摘要形式,以了解配置文件可接受的语句模式。每个模式都是一个规则,规则的并集就是配置文件白名单。

  • PROTECTING:在此模式下,配置文件允许或阻止语句执行。防火墙将传入的语句与配置文件白名单进行匹配,仅接受匹配的语句并拒绝不匹配的语句。在 RECORDINGmode 中训练配置文件后,将其切换到 PROTECTINGmode 以强化 MySQL 以防止偏离白名单的语句进行访问。如果mysql_firewall_trace 启用系统变量,防火墙还会将拒绝的语句写入错误日志。

  • DETECTING:此模式检测但不阻止入侵(可疑的语句,因为它们与配置文件白名单中的任何内容都不匹配)。在 DETECTING模式下,防火墙将可疑语句写入错误日志,但在不拒绝访问的情况下接受它们。

当为配置文件分配任何上述模式值时,防火墙会将模式存储在配置文件中。防火墙模式设置操作也允许模式值为 RESET,但不会存储此值:将配置文件设置为RESET模式会导致防火墙删除配置文件的所有规则并将其模式设置为OFF

笔记

Messages written to the error log in DETECTING mode or because mysql_firewall_trace is enabled are written as Notes, which are information messages. To ensure that such messages appear in the error log and are not discarded, set the log_error_verbosity system variable to a value of 3.

As previously mentioned, MySQL associates each client session with a specific user name and host name combination known as the session account. The firewall matches the session account against registered profiles to determine which profile applies to handling incoming statements from the session:

  • The firewall ignores inactive profiles (profiles with a mode of OFF).

  • The session account matches an active account profile having the same user and host, if there is one. There is at most one such account profile.

After matching the session account to registered profiles, the firewall handles each incoming statement as follows:

  • If there is no applicable profile, the firewall imposes no restrictions and accepts the statement.

  • If there is an applicable profile, its mode determines statement handling:

    • In RECORDING mode, the firewall adds the statement to the profile allowlist rules and accepts it.

    • In PROTECTING mode, the firewall compares the statement to the rules in the profile allowlist. The firewall accepts the statement if there is a match, and rejects it otherwise. If the mysql_firewall_trace system variable is enabled, the firewall also writes rejected statements to the error log.

    • In DETECTING mode, the firewall detects instrusions without denying access. The firewall accepts the statement, but also matches it to the profile allowlist, as in PROTECTING mode. If the statement is suspicious (nonmatching), the firewall writes it to the error log.

Registering Firewall Account Profiles

MySQL Enterprise Firewall enables profiles to be registered that correspond to individual accounts. To use a firewall account profile to protect MySQL against incoming statements from a given account, follow these steps:

  1. Register the account profile and put it in RECORDING mode.

  2. Connect to the MySQL server using the account and execute statements to be learned. This trains the account profile and establishes the rules that form the profile allowlist.

  3. Switch the account profile to PROTECTING mode. When a client connects to the server using the account, the account profile allowlist restricts statement execution.

  4. Should additional training be necessary, switch the account profile to RECORDING mode again, update its allowlist with new statement patterns, then switch it back to PROTECTING mode.

Observe these guidelines for firewall-related account references:

  • Take note of the context in which account references occur. To name an account for firewall operations, specify it as a single quoted string ('user_name@host_name'). This differs from the usual MySQL convention for statements such as CREATE USER and GRANT, for which you quote the user and host parts of an account name separately ('user_name'@'host_name').

    The requirement for naming accounts as a single quoted string for firewall operations means that you cannot use accounts that have embedded @ characters in the user name.

  • The firewall assesses statements against accounts represented by actual user and host names as authenticated by the server. When registering accounts in profiles, do not use wildcard characters or netmasks:

    • Suppose that an account named me@%.example.org exists and a client uses it to connect to the server from the host abc.example.org.

    • The account name contains a % wildcard character, but the server authenticates the client as having a user name of me and host name of abc.example.com, and that is what the firewall sees.

    • Consequently, the account name to use for firewall operations is me@abc.example.org rather than me@%.example.org.

The following procedure shows how to register an account profile with the firewall, train the firewall to know the acceptable statements for that profile (its allowlist), and use the profile to protect MySQL against execution of unacceptable statements by the account. The example account, fwuser@localhost, is presumed for use by an application that accesses tables in the sakila database (available at https://mysql.net.cn/doc/index-other.html).

Use an administrative MySQL account to perform the steps in this procedure, except those steps designated for execution by the fwuser@localhost account that corresponds to the account profile registered with the firewall. For statements executed using this account, the default database should be sakila. (You can use a different database by adjusting the instructions accordingly.)

  1. If necessary, create the account to use for executing statements (choose an appropriate password) and grant it privileges for the sakila database:

    CREATE USER 'fwuser'@'localhost' IDENTIFIED BY 'password';
    GRANT ALL ON sakila.* TO 'fwuser'@'localhost';
  2. Use the sp_set_firewall_mode() stored procedure to register the account profile with the firewall and place the profile in RECORDING (training) mode:

    CALL mysql.sp_set_firewall_mode('fwuser@localhost', 'RECORDING');
  3. To train the registered account profile, connect to the server as fwuser from the server host so that the firewall sees a session account of fwuser@localhost. Then use the account to execute some statements to be considered legitimate for the profile. For example:

    SELECT first_name, last_name FROM customer WHERE customer_id = 1;
    UPDATE rental SET return_date = NOW() WHERE rental_id = 1;
    SELECT get_customer_balance(1, NOW());

    Because the profile is in RECORDING mode, the firewall records the normalized digest form of the statements as rules in the profile allowlist.

    Note

    Until the fwuser@localhost account profile receives statements in RECORDING mode, its allowlist is empty, which is equivalent to deny all. No statement can match an empty allowlist, which has these implications:

    • The account profile cannot be switched to PROTECTING mode. It would reject every statement, effectively prohibiting the account from executing any statement.

    • The account profile can be switched to DETECTING mode. In this case, the profile accepts every statement but logs it as suspicious.

  4. At this point, the account profile information is cached. To see this information, query the INFORMATION_SCHEMA firewall tables:

    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

    The @@version_comment rule comes from a statement sent automatically by the mysql client when you connect to the server.

    Important

    Train the firewall under conditions matching application use. For example, to determine server characteristics and capabilities, a given MySQL connector might send statements to the server at the beginning of each session. If an application normally is used through that connector, train the firewall using the connector, too. That enables those initial statements to become part of the allowlist for the account profile associated with the application.

  5. Invoke sp_set_firewall_mode() again, this time switching the account profile to PROTECTING mode:

    CALL mysql.sp_set_firewall_mode('fwuser@localhost', 'PROTECTING');
    Important

    Switching the account profile out of RECORDING mode synchronizes its cached data to the mysql system database tables that provide persistent underlying storage. If you do not switch the mode for a profile that is being recorded, the cached data is not written to persistent storage and is lost when the server is restarted.

  6. Test the account profile by using the account to execute some acceptable and unacceptable statements. The firewall matches each statement from the account against the profile allowlist and accepts or rejects it:

    • This statement is not identical to a training statement but produces the same normalized statement as one of them, so the firewall accepts it:

      mysql> SELECT first_name, last_name FROM customer WHERE customer_id = '48';
      +------------+-----------+
      | first_name | last_name |
      +------------+-----------+
      | ANN        | EVANS     |
      +------------+-----------+
    • These statements match nothing in the allowlist, so the firewall rejects each with an error:

      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
    • If the mysql_firewall_trace system variable is enabled, the firewall also writes rejected statements to the error log. For example:

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

      These log messages may be helpful in identifying the source of attacks, should that be necessary.

The firewall account profile now is trained for the fwuser@localhost account. When clients connect using that account and attempt to execute statements, the profile protects MySQL against statements not matched by the profile allowlist.

It is possible to detect intrusions by logging nonmatching statements as suspicious without denying access. First, put the account profile in DETECTING mode:

CALL mysql.sp_set_firewall_mode('fwuser@localhost', 'DETECTING');

Then, using the account, execute a statement that does not match the account profile allowlist. In DETECTING mode, the firewall permits the nonmatching statement to execute:

mysql> SHOW TABLES LIKE 'customer%';
+------------------------------+
| Tables_in_sakila (customer%) |
+------------------------------+
| customer                     |
| customer_list                |
+------------------------------+

In addition, the firewall writes a message to the error log:

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

To disable an account profile, change its mode to OFF:

CALL mysql.sp_set_firewall_mode(user, 'OFF');

To forget all training for a profile and disable it, reset it:

CALL mysql.sp_set_firewall_mode(user, 'RESET');

The reset operation causes the firewall to delete all rules for the profile and set its mode to OFF.

Monitoring the Firewall

To assess firewall activity, examine its status variables. For example, after performing the procedure shown earlier to train and protect the fwuser@localhost account, the variables look like this:

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     |
+----------------------------+-------+

这些变量分别表示拒绝、接受、记录为可疑和添加到缓存中的语句数。Firewall_access_granted 计数为 4 是因为mysql客户端每次使用注册帐户连接 3 次时@@version_comment 发送的 语句,加上未在模式中阻塞的语句。 SHOW TABLESDETECTING