Documentation Home
MySQL 8.4 Reference Manual
Related Documentation Download this Manual
PDF (US Ltr) - 39.8Mb
PDF (A4) - 39.9Mb
Man Pages (TGZ) - 257.9Kb
Man Pages (Zip) - 364.9Kb
Info (Gzip) - 4.0Mb
Info (Zip) - 4.0Mb


MySQL 8.4 Reference Manual  /  ...  /  Using MySQL Enterprise Firewall

8.4.7.3 使用 MySQL 企业防火墙

在使用 MySQL Enterprise Firewall 之前,按照第8.4.7.2节,“安装或卸载 MySQL Enterprise Firewall”中的说明进行安装。

本节描述了使用 SQL 语句配置 MySQL Enterprise Firewall 的方法。另外,MySQL Workbench 6.3.4 或更高版本提供了图形化的防火墙控制界面。见MySQL 企业防火墙界面

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

[mysqld]
mysql_firewall_mode=ON

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

或者,在运行时设置并持久化防火墙设置:

SET PERSIST mysql_firewall_mode = OFF;
SET PERSIST mysql_firewall_mode = ON;

SET PERSIST为当前 MySQL 实例设置值。它也将保存该值,使其在服务器重启后继续生效。要更改当前 MySQL 实例的值,但不使其在重启后继续生效,使用GLOBAL关键字,而不是PERSIST。请参阅第15.7.6.1节,“变量赋值语法”

每次MYSQL_FIREWALL服务器插件初始化时,它从这些表加载数据到其内部缓存:

  • firewall_whitelist

  • firewall_group_allowlist

  • firewall_users

  • firewall_groups

  • firewall_membership

不重新启动服务器或重新安装服务器端插件,修改外部数据不会在插件内部反映。系统变量mysql_firewall_reload_interval_seconds使得可以强制指定时间间隔重新加载内存缓存。默认情况下,周期性间隔值设置为零,禁用重新加载。

要定期重新加载缓存,首先确保安装并启用scheduler组件(见第7.5.5节,“调度器组件”).检查组件状态:

SHOW VARIABLES LIKE 'component_scheduler%';
+-----------------------------+-------+
| Variable_name               | Value |
+-----------------------------+-------|
| component_scheduler.enabled | On    |
+-----------------------------+-------+

安装了防火墙后,在服务器启动时将mysql_firewall_reload_interval_seconds全局系统变量设置为服务器主机平台INT_MAX宏值的数字之间60和(例如:

$> mysqld [server-options] --mysql-firewall-reload-interval-seconds=40
...
2023-08-31T17:46:35.043468Z 0 [Warning] [MY-015031] [Server] Plugin MYSQL_FIREWALL 
reported: 'Invalid reload interval specified: 40. Valid values are 0 (off) or 
greater than or equal to 60. Adjusting to 60.'
...

或者在启动时将变量名前加PERSIST_ONLY关键字或@@PERSIST_ONLY.限定符来设置并持久化防火墙设置:

SET PERSIST_ONLY mysql_firewall_reload_interval_seconds = 120;
SET @@PERSIST_ONLY.mysql_firewall_reload_interval_seconds = 120;

修改变量后,重新启动服务器以使新设置生效。

安装防火墙后,授予 MySQL 账户或账户以用于管理其的适当权限。权限取决于哪个账户应该被允许执行哪些防火墙操作:

  • 授予任何需要免除防火墙限制的账户FIREWALL_EXEMPT权限。这对数据库管理员来说很有用,例如,可以避免配置错误导致管理员自己被锁定无法执行语句。

  • 授予任何需要完全管理防火墙的账户FIREWALL_ADMIN权限。某些管理防火墙函数可以由拥有FIREWALL_ADMIN已弃用的SUPER权限的账户调用,见各个函数描述中所示。

  • 授予任何需要只对自己的防火墙规则进行管理的账户FIREWALL_USER权限。

  • 授予EXECUTE权限,用于防火墙存储过程在防火墙数据库中。这些存储过程可能调用管理函数,因此存储过程访问也需要前面所需的那些函数的权限。防火墙数据库可以是MySQL Enterprise Firewall安装时创建的自定义架构或系统数据库 mysql

Note

FIREWALL_EXEMPTFIREWALL_ADMINFIREWALL_USER 权限只能在防火墙安装时授予,因为 MYSQL_FIREWALL 插件定义了这些权限。

MySQL 服务器允许客户端连接,并从它们接收要执行的 SQL 语句。如果防火墙启用,服务器将每个 incoming 语句传递给它,如果语句不立即失败,则根据防火墙接受或拒绝语句。下面描述了防火墙如何接受或拒绝语句。

Firewall Profiles

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

  • 允许列表。允许列表是定义可接受语句的规则集。

  • 当前操作模式。模式使得配置文件可以以不同的方式使用。例如:配置文件可以处于训练模式,以建立允许列表;允许列表可以用于限制语句执行或入侵检测;配置文件可以完全禁用。

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

    • 防火墙支持基于账户的配置文件,以便每个配置文件匹配特定的客户端账户(客户端用户名和主机名组合)。例如,您可以注册一个账户配置文件,该允许列表适用于来自admin@localhost的连接,还有一个账户配置文件,该允许列表适用于来自myapp@apphost.example.com的连接。

    • 防火墙支持组配置文件,可以拥有多个账户作为成员,且配置文件允许列表对所有成员都相同。组配置文件使得管理和部署更加灵活,以便将某些允许规则应用于多个账户。

初始情况下,没有配置文件,所以默认情况下,防火墙接受所有语句,并且对 MySQL 账户执行的语句无效。要应用防火墙保护功能,需要明确操作:

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

  • 为每个配置文件建立允许列表,即该配置文件允许客户端执行的语句类型。

  • 将训练好的配置文件设置为保护模式,以加强 MySQL 对未经授权语句执行的防护:

    • MySQL 将每个客户端会话与特定的用户名和主机名组合关联,这种组合称为会话账户

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

      防火墙只接受由相应配置文件允许列表所允许的语句。

大多数防火墙原则对组配置文件和账户配置文件都相同,两种类型配置文件在以下几个方面不同:

  • 一个账户配置文件的允许列表只应用于单个账户。一个组配置文件的允许列表应用于会话账户与该组中的任何成员账户。

  • 使用账户配置文件来应用允许列表到多个账户,需要注册一个配置文件-per-账户,并且将允许列表复制到每个配置文件。这样,每个配置文件都需要单独训练,因为每个配置文件都必须使用其对应的单个账户进行训练。

    一个组配置文件应用于多个账户,不需要为每个账户复制允许列表。组配置文件可以使用组成员中的任何或所有账户进行训练,也可以限定到单个成员,结果都适用于所有成员。

  • 帐户配置名称基于特定的用户名和主机名组合,取决于哪些客户端连接到 MySQL 服务器。组配置名称由防火墙管理员选择,无其他限制,只要长度在1到288个字符之间。

Note

由于组配置相比帐户配置的优势,以及一个组配置只有一个成员帐户是对该帐户的逻辑等价,建议所有新的防火墙配置都创建为组配置。帐户配置已弃用,将在未来 MySQL 版本中删除。关于将现有帐户配置迁移到组配置,请参阅将帐户配置迁移到组配置

防火墙提供的基于配置保护使得实施以下策略成为可能:

  • 如果应用程序有唯一保护要求,配置它使用不用于其他目的的帐户,然后设置该帐户的组配置或帐户配置。

  • 如果相关应用程序共享保护要求,每个应用程序与其自己的帐户相关,然后将这些应用程序帐户添加到同一个组配置中,或者配置所有应用程序使用相同的帐户,并将它们关联到该帐户的配置。

Firewall Statement Matching

防火墙执行语句匹配不使用来自客户端的 SQL 语句,而是将 incoming 语句转换为 normalize 的摘要形式,防火墙操作使用这些摘要。语句 normalize 的好处在于它使得相似语句可以被分组和识别使用单个模式。例如,这些语句彼此不同:

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;

但是它们都有相同的 normalize 摘要形式:

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

通过 normalization,防火墙可以将每个客户端发送的语句存储成匹配多种不同的摘要。关于 normalization 和摘要的更多信息,请参阅第29.10节,“性能 Schema 语句摘要和采样”

Warning

max_digest_length系统变量设置为零,禁用摘要生产,也禁用需要摘要的服务器功能,如 MySQL 企业防火墙。

Profile Operational Modes

每个注册到防火墙的 profile 都有自己的操作模式,从这些值中选择:

  • OFF: 这种模式禁用了 profile,防火墙将其视为不活动并忽略它。

  • RECORDING: 这是防火墙训练模式。来自客户端的语句,如果匹配 profile,就被认为是可接受的语句,并成为 profile 的指纹。防火墙记录每个语句的 normalized摘要形式,以学习 profile 可接受的语句模式。每个模式是一个规则,规则的并集是 profile 允许列表。

    组和账户 profile 之间的差异在于,组 profile 的语句记录可以限制到单个组成员(训练成员)发送的语句。

  • PROTECTING: 在这个模式下,配置文件允许或阻止语句执行。防火墙将 incoming 语句与配置文件的白名单进行匹配,只接受匹配的语句并拒绝不匹配的语句。在使用 RECORDING 模式训练配置文件后,切换到 PROTECTING 模式以加强 MySQL 对于不在白名单中的语句的访问控制。如果启用了mysql_firewall_trace 系统变量,防火墙还将拒绝语句写入错误日志。

  • DETECTING: 这个模式检测但不阻止入侵(因为它们不在配置文件白名单中)。在 DETECTING 模式下,防火墙将可疑语句写入错误日志,但接受它们而不拒绝访问。

当分配任何前面模式值时,防火墙将存储该模式。防火墙模式设置操作也允许 RESET 模式的值,但是这个值不会被存储:将配置文件设置为 RESET 模式将删除该配置文件的所有规则并将其模式设置为 OFF

Note

DETECTING模式下或因为mysql_firewall_trace启用时,写入到错误日志的信息消息。为了确保这些消息出现在错误日志中,不被丢弃,请确保错误日志 verbosity 设置足够包括信息消息。例如,如果您使用优先级基于的日志过滤器,如第7.4.2.5节,“Priority-Based Error Log Filtering (log_filter_internal)”中描述的那样,设置log_error_verbosity系统变量为3。

Firewall Statement Handling When Multiple Profiles Apply

为了简洁,后续介绍如何设置配置文件时假设防火墙将客户端的 incoming 语句与单个配置文件进行匹配,但防火墙操作可以更复杂:

  • 一个组配置文件可以包含多个账户成员。

  • 一个账户可以是多个组配置文件的成员。

  • 多个配置文件可以匹配给定的客户端。

以下描述涵盖防火墙操作的总体情况,包括潜在多个配置文件对 incoming 语句的处理:

如前所述,MySQL 将每个客户端会话与特定用户名和主机名组合称为session 账户。防火墙将 session 账户与注册配置文件进行匹配,以确定哪些配置文件适用于处理来自会话的 incoming 语句:

  • 防火墙忽略无效的配置文件(模式为OFF)。

  • 会话账户匹配每个包含相同用户和主机的活动组配置文件。可以有多个这样的组配置文件。

  • 会话账户匹配一个活动账户配置文件,如果存在一个。最多只有一个这样的账户配置文件。

换言之,会话账户可以匹配0或多个活动组配置文件,和0或1个活动账户配置文件。这意味着,对于给定的会话,防火墙将每个语句处理如下:

  • 如果没有适用配置文件,防火墙不限制语句并接受语句。

  • 如果有适用配置文件,那么它们的模式确定语句处理:

    • 防火墙将语句记录到每个适用配置文件中,如果该配置文件在RECORDING模式。

    • 防火墙将语句写入错误日志,用于每个适用配置文件在DETECTING模式的语句(不匹配配置文件允许列表)。

    • 防火墙接受语句,如果至少有一个适用配置文件在RECORDINGDETECTING模式(这些模式接受所有语句),或者语句匹配至少一个适用配置文件的允许列表,在PROTECTING模式。否则,防火墙拒绝语句(并将其写入错误日志,如果mysql_firewall_trace系统变量启用)。

了解这个描述后,下一节将回到单个组 profile 或单个账户 profile 的情况,并涵盖如何设置每种类型的 profile。

MySQL Enterprise Firewall 支持组 profile 注册。一个组 profile 可以有多个账户作为其成员。要使用防火墙组 profile 保护 MySQL 对于来自给定账户的 incoming 语句,按照以下步骤操作:

  1. 注册组 profile 并将其设置为 RECORDING 模式。

  2. 添加组 profile 的成员账户。

  3. 使用成员账户连接到 MySQL 服务器并执行要学习的语句。这训练了组 profile 并建立了 profile 允许列表。

  4. 添加其他要作为组成员的账户到组 profile 中。

  5. 将组 profile 切换到 PROTECTING 模式。客户端连接到服务器时,如果使用的是组 profile 的成员账户,profile 允许列表将限制语句执行。

  6. 如果需要额外的训练,切换组 profile 到 RECORDING 模式,更新其允许列表以新的语句模式,然后切换回 PROTECTING 模式。

遵循这些防火墙相关账户参考指南:

  • 注意帐户引用出现的上下文。为防火墙操作指定帐户,使用单引号字符串 ('user_name@host_name')。这与通常的 MySQL 语句,如CREATE USERGRANT,不同于在帐户名称中单独引用用户和主机部分 ('user_name'@'host_name')。

    为防火墙操作命名帐户的要求意味着你不能使用用户名称中包含@字符的帐户。

  • 防火墙根据服务器认证的实际用户和主机名称来评估语句。注册帐户时,不要使用通配符或网际组:

    • 假设存在名为 me@%.example.org 的帐户,客户端从主机 abc.example.org 连接到服务器。

    • 帐户名称包含通配符%,但服务器认证客户端的用户名为 me,主机名为 abc.example.com,防火墙看到的是这些信息。

    • 因此,为防火墙操作使用的帐户名称是 me@abc.example.org,而不是 me@%.example.org

以下过程展示了如何注册一个组-profile到防火墙中,训练防火墙知道该profile的可接受语句(其allowlist),使用profile保护MySQL对不可接受语句的执行,并添加和删除组成员。该示例使用组profile名称为 fwgrp。该示例profile假设用于应用程序客户端访问sakila 数据库(可在https://dev.mysql.com/doc/index-other.html中找到)。

使用管理MySQL账户执行本过程中的步骤,除了那些由防火墙组profile成员账户执行的步骤。为成员账户执行语句时,应该默认数据库为 sakila。(您可以根据需要调整指令。)

  1. 如果必要,创建将要成为fwgrp 组profile的账户,并授予适当访问权限。一个成员账户语句在这里展示(选择合适密码):

    CREATE USER 'member1'@'localhost' IDENTIFIED BY 'password';
    GRANT ALL ON sakila.* TO 'member1'@'localhost';
  2. 使用 sp_set_firewall_group_mode() 存储过程将组profile注册到防火墙中,并将profile置于 RECORDING(训练) 模式:

    CALL mysql.sp_set_firewall_group_mode('fwgrp', 'RECORDING');
    Note

    如果您已安装MySQL Enterprise Firewall在自定义架构中,那么请对您的系统进行相应的替换。例如,如果防火墙安装在fwdb 架构中,那么执行存储过程如下:

    CALL fwdb.sp_set_firewall_group_mode('fwgrp', 'RECORDING');

  3. 使用 sp_firewall_group_enlist() 存储过程添加初始成员账户,以便训练组profile allowlist:

    CALL mysql.sp_firewall_group_enlist('fwgrp', 'member1@localhost');
  4. 使用初始成员账户训练组-profile,连接到服务器,以便防火墙看到一个会话账户为 member1@localhost。然后执行一些语句,以便被认为是合法的profile。例如:

    SELECT title, release_year FROM film WHERE film_id = 1;
    UPDATE actor SET last_update = NOW() WHERE actor_id = 1;
    SELECT store_id, COUNT(*) FROM inventory GROUP BY store_id;

    防火墙从 member1@localhost 账户接收语句,因为该账户是 fwgrp profile 的成员,且在 RECORDING 模式下,因此防火墙将语句解释为适用于 fwgrp,并将语句的 normalize摘要形式记录到 fwgrp 允许列表中。这些规则随后应用于所有 fwgrp 成员账户。

    Note

    直到 fwgrp 组-profile 接收语句在 RECORDING 模式下,允许列表为空,这等同于““deny all.””。没有语句可以匹配空允许列表,这些结果:

    • 组-profile 不能被切换到 PROTECTING 模式。它将拒绝每个语句,实际上禁止组成员账户执行任何语句。

    • 组-profile 可以切换到 DETECTING 模式。在这种情况下,profile 接受每个语句,但将其记录为可疑语句。

  5. 在这个点上,组-profile 信息被缓存,包括名称、成员资格和允许列表。要查看这些信息,请查询性能chema防火墙表:

    mysql> SELECT MODE FROM performance_schema.firewall_groups
           WHERE NAME = 'fwgrp';
    +-----------+
    | MODE      |
    +-----------+
    | RECORDING |
    +-----------+
    mysql> SELECT * FROM performance_schema.firewall_membership
           WHERE GROUP_ID = 'fwgrp' ORDER BY MEMBER_ID;
    +----------+-------------------+
    | GROUP_ID | MEMBER_ID         |
    +----------+-------------------+
    | fwgrp    | member1@localhost |
    +----------+-------------------+
    mysql> SELECT RULE FROM performance_schema.firewall_group_allowlist
           WHERE NAME = 'fwgrp';
    +----------------------------------------------------------------------+
    | RULE                                                                 |
    +----------------------------------------------------------------------+
    | SELECT @@`version_comment` LIMIT ?                                   |
    | UPDATE `actor` SET `last_update` = NOW ( ) WHERE `actor_id` = ?      |
    | SELECT `title` , `release_year` FROM `film` WHERE `film_id` = ?      |
    | SELECT `store_id` , COUNT ( * ) FROM `inventory` GROUP BY `store_id` |
    +----------------------------------------------------------------------+
    Note

    @@version_comment 规则来自自动发送的mysql 客户端连接到服务器时。

    Important

    在应用程序使用的条件下训练防火墙。例如,为了确定服务器特征和能力,一款给定的 MySQL 连接器可能会在每个会话开始时向服务器发送语句。如果应用程序通常通过该连接器使用,那么也使用连接器来训练防火墙,以便初始语句成为与应用程序关联的组 profile 的 allowlist 一部分。

  6. 将组 profile 切换到 PROTECTING 模式:

    CALL mysql.sp_set_firewall_group_mode('fwgrp', 'PROTECTING');
    Important

    切换组 profile 出 RECORDING 模式同步其缓存数据到防火墙数据库表中,这些表提供持久的底层存储。如果您不切换模式,那么记录中的缓存数据将在服务器重启时丢失。防火墙数据库可以是 mysql 系统数据库或自定义架构(见安装 MySQL 企业防火墙)。

  7. 将组 profile 中添加其他应为成员的账户:

    CALL mysql.sp_firewall_group_enlist('fwgrp', 'member2@localhost');
    CALL mysql.sp_firewall_group_enlist('fwgrp', 'member3@localhost');
    CALL mysql.sp_firewall_group_enlist('fwgrp', 'member4@localhost');

    现在使用 member1@localhost 账户训练的组 allowlist 也适用于额外账户。

  8. 验证更新的组成员身份,查询 firewall_membership 表再次:

    mysql> SELECT * FROM performance_schema.firewall_membership
           WHERE GROUP_ID = 'fwgrp' ORDER BY MEMBER_ID;
    +----------+-------------------+
    | GROUP_ID | MEMBER_ID         |
    +----------+-------------------+
    | fwgrp    | member1@localhost |
    | fwgrp    | member2@localhost |
    | fwgrp    | member3@localhost |
    | fwgrp    | member4@localhost |
    +----------+-------------------+
  9. 使用组中的任何账户执行可接受和不可接受的语句来测试组文件。防火墙将每个语句从账户中匹配对应的profile allowlist,并接受或拒绝它:

    • 这个语句与训练语句不同,但生成的标准语句与其中之一相同,所以防火墙接受它:

      mysql> SELECT title, release_year FROM film WHERE film_id = 98;
      +-------------------+--------------+
      | title             | release_year |
      +-------------------+--------------+
      | BRIGHT ENCOUNTERS |         2006 |
      +-------------------+--------------+
    • 这些语句在allowlist中找不到匹配项,所以防火墙以错误形式拒绝每个语句:

      mysql> SELECT title, release_year FROM film WHERE film_id = 98 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 'member1@localhost'. Reason: No match in allowlist.
      Statement: TRUNCATE TABLE `mysql` . `slow_log`'

      这些日志消息可能有助于识别攻击来源,如果需要那样:

  10. 如果需要从组文件中删除成员账户,请使用sp_firewall_group_delist()存储过程,而不是sp_firewall_group_enlist()

    CALL mysql.sp_firewall_group_delist('fwgrp', 'member3@localhost');

防火墙组文件现在已经为成员账户训练了。客户端连接时,使用组中的任何账户尝试执行语句,profile保护MySQL不匹配allowlist的语句。

显示的过程只添加了一名成员到组文件前,提供更好的控制训练期限,可以限制哪些账户可以将新的可接受语句添加到allowlist。需要额外训练,可以切换profile回到RECORDING模式:

CALL mysql.sp_set_firewall_group_mode('fwgrp', 'RECORDING');

然而,这样使得组中的任何成员都可以执行语句并将其添加到白名单中。要限制额外训练到单个组成员,调用 sp_set_firewall_group_mode_and_user(),它类似于 sp_set_firewall_group_mode() 但多了一个参数指定哪个账户允许在 RECORDING 模式下训练配置文件。例如,要使得只由 member4@localhost 域名执行训练,做法如下:

CALL mysql.sp_set_firewall_group_mode_and_user('fwgrp', 'RECORDING', 'member4@localhost');

这样额外训练由指定账户执行,不需要删除其他组成员,但他们可以执行语句,但是语句不添加到白名单中。(记住,在 RECORDING 模式下其他成员可以执行任何 语句。)

Note

避免在指定账户为组配置文件的训练账户时出现意外行为,总是确保该账户是组成员。

训练后将组配置文件设置回 PROTECTING 模式:

CALL mysql.sp_set_firewall_group_mode('fwgrp', 'PROTECTING');

sp_set_firewall_group_mode_and_user() 确定的训练账户在组配置文件中保存,所以防火墙记住它,以便后续需要更多训练时使用。因此,如果你调用 sp_set_firewall_group_mode()(没有训练账户参数),当前配置文件训练账户 member4@localhost 不会改变。

如果实际想要使得组中的所有成员都可以在 RECORDING 模式下执行训练,调用 sp_set_firewall_group_mode_and_user() 并将账户参数设置为 NULL

CALL mysql.sp_set_firewall_group_mode_and_user('fwgrp', 'RECORDING', NULL);

可以通过将非匹配语句记录为可疑行为而不拒绝访问来检测入侵。首先,将组 profile 设置到 DETECTING 模式:

CALL mysql.sp_set_firewall_group_mode('fwgrp', 'DETECTING');

然后,使用成员账户执行不匹配组 profile 允许列表的语句。在 DETECTING 模式下,防火墙允许非匹配语句执行:

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

此外,防火墙还将消息写入错误日志:

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

要禁用组 profile,改变其模式到 OFF

CALL mysql.sp_set_firewall_group_mode(group, 'OFF');

要忘记所有培训并禁用 profile,重置它:

CALL mysql.sp_set_firewall_group_mode(group, 'RESET');

重置操作会导致防火墙删除该 profile 的所有规则,并将其模式设置为 OFF

MySQL Enterprise Firewall 允许注册对应于单个账户的 profile。要使用防火墙账户 profile 保护 MySQL 对来自给定账户的 incoming 语句,按照以下步骤操作:

  1. 注册账户 profile 并将其设置到 RECORDING 模式。

  2. 使用账户连接到 MySQL 服务器并执行要学习的语句。这会训练账户 profile 并建立 profile 允许列表。

  3. 将账户 profile 切换到 PROTECTING 模式。客户端使用账户连接到服务器时,账户 profile 允许列表限制语句执行。

  4. 如果需要更多培训,切换账户 profile 到 RECORDING 模式再次,更新其允许列表,然后切换回 PROTECTING 模式。

遵循防火墙相关账户参考的这些指南:

  • 注意帐户引用出现的上下文。为防火墙操作指定帐户,使用单引号字符串 ('user_name@host_name')。这与通常的 MySQL 语句,如CREATE USERGRANT,不同于在帐户名称中单独引用用户和主机部分 ('user_name'@'host_name')。

    为防火墙操作命名帐户的要求意味着你不能使用用户名称中包含@字符的帐户。

  • 防火墙根据服务器认证的实际用户和主机名称来评估语句。注册帐户时,不要使用通配符或网际组:

    • 假设存在名为 me@%.example.org 的帐户,客户端从主机 abc.example.org 连接到服务器。

    • 帐户名称包含通配符%,但服务器认证客户端的用户名为 me,主机名为 abc.example.com,防火墙看到的是这些信息。

    • 因此,为防火墙操作使用的帐户名称是 me@abc.example.org,而不是 me@%.example.org

以下过程展示了如何注册账户配置文件到防火墙中,训练防火墙了解该配置文件可接受的语句(其白名单),并使用该配置文件保护MySQL对不可接受的语句执行。示例账户fwuser@localhost,假设用于访问sakila数据库(在https://dev.mysql.com/doc/index-other.html可用).

使用管理MySQL账户执行本过程中的步骤,除了那些由fwuser@localhost账户对应的配置文件注册到防火墙的步骤。对于使用该账户执行语句时,应该默认数据库为sakila(可以根据需要调整).

  1. 如果必要,创建用于执行语句的账户(选择合适的密码),并授予对sakila数据库的权限:

    CREATE USER 'fwuser'@'localhost' IDENTIFIED BY 'password';
    GRANT ALL ON sakila.* TO 'fwuser'@'localhost';
  2. 使用sp_set_firewall_mode()存储过程将账户配置文件注册到防火墙中,并将其置于RECORDING(训练)模式:

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

    如果您已在自定义架构中安装MySQL Enterprise Firewall,那么请对您的系统进行相应的替换。例如,如果防火墙安装在fwdb架构,那么执行存储过程时请这样操作:

    CALL fwdb.sp_set_firewall_mode('fwuser@localhost', 'RECORDING');

  3. 为了训练注册账户配置,连接到服务器作为 fwuser,从服务器主机连接,以便防火墙看到一个会话账户为 fwuser@localhost。然后使用该账户执行一些语句,以被认为是合法的配置示例:

    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());

    因为配置处于 RECORDING 模式,防火墙将语句的 normalized摘要形式记录到配置允许列表中。

    Note

    直到 fwuser@localhost 账户配置收到 RECORDING 模式,它们的允许列表为空,等同于““deny all.””没有语句可以匹配空允许列表,这些结果:

    • 账户配置不能切换到 PROTECTING 模式。它将拒绝每个语句,实际上禁止账户执行任何语句。

    • 账户配置可以切换到 DETECTING 模式。在这种情况下,配置接受每个语句,但将其记录为可疑语句。

  4. 在这个点上,账户配置信息被缓存。要查看该信息,请查询 INFORMATION_SCHEMA 防火墙表:

    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 规则来自自动发送的 mysql 客户端连接到服务器时。

    Important

    在应用程序使用的条件下训练防火墙。例如,为了确定服务器特征和能力,一款给定的MySQL连接器可能会在每个会话开始时向服务器发送语句。如果应用程序通常通过该连接器使用,那么也要使用该连接器来训练防火墙,这样使得初始语句成为与应用程序关联的账户配置文件的一部分。

  5. 再次调用 sp_set_firewall_mode(),这次将账户配置文件切换到 PROTECTING 模式:

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

    RECORDING 模式切换账户配置文件同步其缓存数据到防火墙数据库表中,这些表提供持久底层存储。如果不切换模式,那么缓存数据将不会被写入持久存储,重启服务器时将丢失。防火墙数据库可以是 mysql 系统数据库或自定义架构(见Installing MySQL Enterprise Firewall)。

  6. 使用账户执行一些可接受和不可接受的语句来测试账户配置文件。防火墙将每个语句与配置文件允许列表进行匹配,并接受或拒绝它:

    • 这个语句不是训练语句,但产生了同一个normalized语句,所以防火墙接受它:

      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 allowlist.
      Statement: TRUNCATE TABLE `mysql` . `slow_log`'

      这些日志消息可能有助于识别攻击的来源,假如需要这样做。

现在,防火墙账户配置已经为 fwuser@localhost 账户训练了。客户端使用该账户连接并尝试执行语句时,配置保护 MySQL 不允许未匹配的语句。

可以通过记录不匹配语句作为可疑行为来检测入侵,而不是拒绝访问。首先,将账户配置设置为 DETECTING 模式:

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

然后,使用账户执行不匹配的语句。在 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 allowlist.
Statement: SHOW TABLES LIKE ?'

要禁用账户配置,改变其模式为 OFF

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

要忘记所有训练并禁用配置,重置它:

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

重置操作会导致防火墙删除该配置的所有规则,并将其模式设置为 OFF

要评估防火墙活动,检查其状态变量。例如,在之前的训练和保护 fwgrp 组配置后,这些变量看起来像这样:

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 客户端发送的 @@version_comment 语句,三个连接次数加上在 DETECTING 模式下未被阻止的 SHOW TABLES 语句。

MySQL 企业防火墙支持每个账户的单独配置文件,也支持每个可以应用于多个账户的组配置文件。一个组配置文件使得更方便地管理:不需要为每个账户创建单独的配置文件,并且在所有这些配置文件中重复该允许列表,而是创建一个单独的组配置文件,然后将账户添加到其中。组允许列表随后应用于所有账户。

一个只有一个成员账户的组配置文件逻辑上等同于该账户的配置文件,所以可以完全使用组配置文件来管理防火墙,而不是混用账户和组配置文件。对于新安装的防火墙,可以统一创建新的配置文件为组配置文件,避免账户配置文件。

由于组件配置提供的更大灵活性,建议创建所有新的防火墙配置文件为组件配置。账户配置已弃用,将在未来MySQL版本中删除。对于已经包含账户配置的升级,MySQL企业防火墙包括一个名为sp_migrate_firewall_user_to_group()的存储过程,以帮助您将账户配置转换为组件配置。要使用它,请以拥有FIREWALL_ADMIN特权的用户执行以下步骤:

  1. 运行firewall_profile_migration.sql脚本来安装sp_migrate_firewall_user_to_group()存储过程。该脚本位于您的MySQL安装目录下的share目录。

    在命令行中指定与之前定义的防火墙安装相同的防火walls数据库名称。示例中指定了系统数据库,mysql

    $> mysql -u root -p -D mysql < firewall_profile_migration.sql
    Enter password: (enter root password here)

    如果您在自定义架构中安装了MySQL企业防火墙,请对应地进行替换。

  2. 通过查询信息SchemaMYSQL_FIREWALL_USERS表来确定哪些账户配置存在。例如:

    mysql> SELECT USERHOST FROM INFORMATION_SCHEMA.MYSQL_FIREWALL_USERS;
    +-------------------------------+
    | USERHOST                      |
    +-------------------------------+
    | admin@localhost               |
    | local_client@localhost        |
    | remote_client@abc.example.com |
    +-------------------------------+
  3. 对于之前步骤中识别的每个账户配置,转换为组件配置。将mysql.前缀替换为实际防火walls数据库名称,如果必要:

    CALL mysql.sp_migrate_firewall_user_to_group('admin@localhost', 'admins');
    CALL mysql.sp_migrate_firewall_user_to_group('local_client@localhost', 'local_clients');
    CALL mysql.sp_migrate_firewall_user_to_group('remote_client@localhost', 'remote_clients');

    在每种情况下,帐户配置必须存在且不能处于RECORDING模式,组配置也不能已经存在。生成的组配置只有一个 enlisted 成员,即该组的训练账户,该组配置的操作模式来自帐户配置的操作模式。

  4. (可选) 删除 sp_migrate_firewall_user_to_group() :

    DROP PROCEDURE IF EXISTS mysql.sp_migrate_firewall_user_to_group;

    如果您在自定义架构中安装了 MySQL Enterprise Firewall,需要根据您的系统进行相应的替换。

关于sp_migrate_firewall_user_to_group() 的详细信息,请参见Firewall Miscellaneous Stored Procedures