MySQL企业防火墙
注意MySQL Enterprise Firewall是商业产品MySQL Enterprise Edition中包含的扩展。要了解有关商业产品的更多信息,请参见 https://www.mysql.com/products/。
MySQL Enterprise Edition包括MySQL Enterprise Firewall,这是一种应用程序级防火墙,使数据库管理员可以根据与已接受语句模式的白名单的匹配来允许或拒绝SQL语句执行。这有助于使MySQL Server免受SQL注入之类的攻击,或通过在合法查询工作负载特征之外使用应用程序来尝试利用应用程序。
在防火墙中注册的每个MySQL帐户都有其自己的语句白名单,从而可以针对每个帐户量身定制保护。对于给定的帐户,防火墙可以在记录,保护或检测模式下运行,以训练接受的语句模式,对不可接受的语句进行主动保护或对不可接受的语句进行被动检测。该图说明了防火墙在每种模式下如何处理传入的语句。
图6.1 MySQL企业防火墙操作

以下各节描述MySQL企业防火墙的组件,讨论如何安装和使用它,并提供有关其组件的参考信息。
MySQL企业防火墙组件
MySQL企业防火墙基于实现以下组件的插件库:
- 一个名为的服务器端插件
MYSQL_FIREWALL
会在执行SQL语句之前先对其进行检查,并根据其内存中的缓存来决定执行还是拒绝每个语句。 - 服务器端插件命名
MYSQL_FIREWALL_USERS
并MYSQL_FIREWALL_WHITELIST
实现INFORMATION_SCHEMA
表,这些表提供了有关防火墙数据缓存的视图。 - 系统表命名
firewall_users
,并firewall_whitelist
在mysql
数据库中提供防火墙的数据持久性存储。 - 存储过程命名
sp_set_firewall_mode()
并sp_reload_firewall_rules()
执行任务,例如在防火墙中注册MySQL帐户,建立其操作模式以及管理缓存和底层系统表之间的防火墙数据传输。 - 一组用户定义的函数为较低级别的任务提供了SQL级别的API,例如将缓存与基础系统表同步。
- 系统变量启用防火墙配置,状态变量提供运行时操作信息。
FIREWALL_ADMIN
和FIREWALL_USER
特权使用户可以分别管理任何用户的防火墙规则和他们自己的防火墙规则。
安装或卸载MySQL企业防火墙
MySQL企业防火墙安装是一项一次性操作,安装“ MySQL企业防火墙组件”中描述的组件。可以使用图形界面或手动执行安装:
- 在Windows上,MySQL Installer包含一个为您启用MySQL企业防火墙的选项。
- MySQL Workbench 6.3.4或更高版本可以安装MySQL企业防火墙,启用或禁用已安装的防火墙或卸载防火墙。
- 手动MySQL企业防火墙安装涉及运行位于
share
MySQL安装目录中的脚本。
重要在遵循其说明之前,请先阅读整个部分。该过程的某些部分取决于您的环境。
注意如果安装了MySQL企业防火墙,则即使禁用它,其开销也很少。为避免这种开销,除非计划使用防火墙,否则不要安装防火墙。
有关用法说明,有关参考信息,请参见“ MySQL企业防火墙参考”。
- 安装MySQL企业防火墙
- 卸载MySQL企业防火墙
安装MySQL企业防火墙
如果已经从旧版本的MySQL安装了MySQL Enterprise Firewall,请按照本节后面给出的说明将其卸载,然后在安装当前版本之前重新启动服务器。在这种情况下,还需要再次注册您的配置。
在Windows上,可以使用MySQL Installer安装MySQL企业防火墙,如图6.2“在Windows上安装MySQL企业防火墙”所示。选中启用MySQL企业防火墙复选框。(用于网络访问的开放防火墙端口有不同的用途。它是指Windows防火墙,它控制Windows是否阻止MySQL服务器侦听客户端连接的TCP / IP端口。)
重要使用MySQL Installer安装的MySQL 8.0.19存在一个问题,如果在服务器配置步骤中选择了MySQL企业防火墙,则会阻止服务器启动。如果服务器启动操作失败,请单击“取消”以结束配置过程并返回到仪表板。您必须卸载服务器。
解决方法是在未选择MySQL企业防火墙的情况下运行MySQL Installer。(也就是说,不要选中“启用MySQL企业防火墙”复选框。)然后,按照本节后面的手动安装说明,安装MySQL企业防火墙。在MySQL 8.0.20中,此问题已得到纠正。
图6.2 Windows上的MySQL企业防火墙安装

要使用MySQL Workbench 6.3.4或更高版本安装MySQL企业防火墙,请参阅 MySQL企业防火墙接口。
要手动安装MySQL企业防火墙,请参见share
MySQL安装目录,然后选择适合您平台的脚本。可用脚本在用于引用插件库文件的后缀中有所不同:
win_install_firewall.sql
注意:对于.dll
用作文件名后缀的Windows系统,请选择此脚本。linux_install_firewall.sql
注意:对于Linux和类似.so
用作文件名后缀的系统,请选择此脚本。
安装脚本会在默认数据库中创建存储过程,因此请选择要使用的数据库。然后按如下所示运行脚本,在命令行上命名所选的数据库。此处的示例使用mysql
数据库和Linux安装脚本。为您的系统进行适当的替换。
shell>mysql -u root -p mysql < linux_install_firewall.sql Enter password: (enter root password here)
注意要在主/从复制,组复制或InnoDB群集的上下文中使用MySQL企业防火墙,必须在主节点或主节点上运行安装脚本之前准备好从节点或辅助节点。这是必需的,因为
INSTALL PLUGIN
不会复制脚本中的语句。
- 在每个从节点或辅助节点上,
INSTALL PLUGIN
从安装脚本中提取语句并手动执行它们。- 在主节点或主节点上,如前所述运行安装脚本。
使用图形界面或手动安装MySQL Enterprise Firewall应该启用防火墙。要验证这一点,请连接到服务器并执行以下语句:
mysql>SHOW GLOBAL VARIABLES LIKE 'mysql_firewall_mode'; +--------------------- +------- + | Variable_name | Value | +--------------------- +------- + | mysql_firewall_mode | ON | +--------------------- +------- +
如果插件未能初始化,请检查服务器错误日志以获取诊断消息。
卸载MySQL企业防火墙
可以使用MySQL Workbench或手动卸载MySQL Enterprise Firewall。
要使用MySQL Workbench 6.3.4或更高版本卸载MySQL企业防火墙,请参见 MySQL企业防火墙界面。
要手动卸载MySQL企业防火墙,请执行以下语句。假定存储过程是在mysql
数据库中创建的。DROP PROCEDURE
如果过程是在其他数据库中创建的,请适当调整语句。
DROP TABLE mysql.firewall_whitelist;DROP TABLE mysql.firewall_users;UNINSTALL PLUGIN mysql_firewall;UNINSTALL PLUGIN mysql_firewall_whitelist;UNINSTALL PLUGIN mysql_firewall_users;DROP FUNCTION set_firewall_mode;DROP FUNCTION normalize_statement;DROP FUNCTION read_firewall_whitelist;DROP FUNCTION read_firewall_users;DROP FUNCTION mysql_firewall_flush_status;DROP PROCEDURE mysql.sp_set_firewall_mode;DROP PROCEDURE mysql.sp_reload_firewall_rules;
使用MySQL企业防火墙
在使用MySQL企业防火墙之前,请按照“安装或卸载MySQL企业防火墙”中的说明进行安装。
本节介绍如何使用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语句转换为规范化摘要形式。防火墙摘要类似于性能模式使用的语句摘要(请参见“性能模式语句摘要和采样”)。但是,与性能架构不同,与摘要相关的相关系统变量为max_digest_length
。
对于来自注册帐户的连接,防火墙会将每个传入的语句转换为规范化形式,并根据帐户模式进行处理:
- 在记录模式下,防火墙将规范化的语句添加到帐户白名单规则中。
- 在保护模式下,防火墙将规范化的语句与帐户白名单规则进行比较。如果存在匹配项,该语句将通过,服务器将继续对其进行处理。否则,服务器将拒绝该语句,并向客户端返回错误。如果
mysql_firewall_trace
启用了系统变量,则防火墙还将拒绝的语句写入错误日志。 - 在检测模式下,防火墙像在保护模式下一样匹配语句,但是在不拒绝访问的情况下将不匹配的语句写入错误日志。
具有OFF
或不向防火墙注册模式的帐户将被其忽略。
要使用MySQL企业防火墙保护帐户,请按照以下步骤操作:
- 注册该帐户并将其置于记录模式。
- 使用注册的帐户连接到MySQL服务器并执行要学习的语句。这将建立该帐户的已接受对帐单白名单。
- 将注册帐户切换为保护模式。
以下示例显示了如何在防火墙中注册帐户,如何使用防火墙来学习该帐户的可接受语句,以及如何防止执行不可接受的语句。示例帐户,'fwuser'@'localhost'
供访问sakil
数据库中表的应用程序使用。(该数据库位于https://dev.mysql.com/doc/index-other.html。)
注意帐户名称的用户和主机部分分别用引号括起来,例如
CREATE USER
和GRANT
,而要指定用于防火墙组件的帐户,请将其命名为单引号字符串'fwuser@localhost'
。将帐户命名为防火墙组件的单引号字符串的约定意味着您不能使用
@
在用户名中包含嵌入式字符的帐户。
使用管理的MySQL帐户执行以下过程中的步骤,但指定给由防火墙注册的帐户执行的帐户除外。默认数据库应该是sakil
使用注册帐户执行的语句的数据库。
如有必要,请创建要保护的帐户(选择适当的密码)并授予其
sakil
数据库特权:mysql>
CREATE USER 'fwuser'@'localhost'IDENTIFIED BY 'fWp@3sw0rd'; mysql>GRANT ALL ON sakil .*TO 'fwuser'@'localhost';使用
sp_set_firewall_mode()
存储过程在防火墙中注册帐户并将其置于记录模式(如果该过程位于之外的数据库中mysql
,请相应地调整语句):mysql>
CALL mysql.sp_set_firewall_mode('fwuser@localhost', 'RECORDING');在执行过程中,存储过程将调用防火墙用户定义的函数,这些函数可能会产生自己的输出。
使用注册的帐户,连接到服务器,然后执行一些对其合法的语句:
mysql>
SELECT first_name, last_nameFROM customerWHERE customer_id = 1; mysql>UPDATE rentalSET return_date = NOW()WHERE rental_id = 1; mysql>SELECT get_customer_balance(1, NOW());防火墙将这些语句转换为摘要形式,并将其记录在帐户白名单中。
注意
在帐户以记录模式执行报表之前,其白名单为空,这等同于“全部拒绝”。”如果切换到保护模式,该账户将被有效地执行语句禁止。
此时,用户和白名单信息已缓存,可以在防火墙
INFORMATION_SCHEMA
表中看到:mysql>
SELECT MODE FROM INFORMATION_SCHEMA.MYSQL_FIREWALL_USERSWHERE USERHOST = 'fwuser@localhost'; +----------- + | MODE | +----------- + | RECORDING | +----------- + mysql>SELECT RULEFROM INFORMATION_SCHEMA.MYSQL_FIREWALL_WHITELISTWHERE 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 ? | +---------------------------------------------------------------------------- +注意
该
@@version_comment
规则来自当您以注册用户身份连接到服务器时mysql客户端自动发送的一条语句。在与应用程序使用相匹配的条件下训练防火墙非常重要。例如,给定的MySQL连接器可能会在连接开始时向服务器发送语句,以确定服务器的特性和功能。如果通常通过该连接器使用应用程序,则也应采用这种方式来训练防火墙。这使这些初始报表成为与该应用程序关联的帐户的白名单的一部分。
使用存储过程将注册用户切换到保护模式:
mysql>
CALL mysql.sp_set_firewall_mode('fwuser@localhost', 'PROTECTING');重要
退出帐户
RECORDING
模式将其防火墙缓存数据同步到基础mysql
系统数据库表以进行持久存储。如果不为正在记录的用户切换模式,则缓存的白名单数据不会写入系统表,并且在重新启动服务器时会丢失。使用注册的帐户,执行一些可接受和不可接受的语句。防火墙将每个白名单与帐户白名单进行匹配,然后接受或拒绝。
该语句与训练语句不同,但是会生成与其中之一相同的规范化语句,因此防火墙会接受它:
mysql>
SELECT first_name, last_nameFROM customerWHERE customer_id = '48'; +------------ +----------- + | first_name | last_name | +------------ +----------- + | ANN | EVANS | +------------ +----------- +这些语句与白名单中的任何语句都不匹配,并且每个语句都会导致错误:
mysql>
SELECT first_name, last_nameFROM customerWHERE 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 ? '
注意
检测模式将消息写为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 | +---------------------------- +------- +变量分别表示拒绝,接受,记录为可疑以及添加到缓存中的语句数。该
Firewall_access_granted
计数为4,这是因为mysql客户端以注册用户身份进行连接的3次中的每一次@@version_comment
都由mysql客户端发送的语句,加上SHOW TABLES
在DETECTING
模式下未被阻塞的语句。
如果需要对帐户进行其他培训,请再次将其切换到记录模式,然后在执行要添加到白名单的语句后,再回到保护模式。
MySQL企业防火墙参考
以下讨论可作为对MySQL企业防火墙组件的参考:
- MySQL企业防火墙表
- MySQL企业防火墙的过程和功能
- MySQL企业防火墙系统变量
- MySQL企业防火墙状态变量
MySQL企业防火墙表
MySQL企业防火墙维护帐户和白名单信息。它使用mysql
系统数据库中的INFORMATION_SCHEMA
表以持久形式存储此数据,并使用表提供对缓存数据的视图。启用后,防火墙会将其操作决策基于缓存的数据。
mysql
只有具有该数据库特权的用户才能访问这些表。INFORMATION_SCHEMA
任何人都可以访问该表。
该mysql.firewall_users
表列出了已注册的防火墙帐户及其操作模式。该表具有以下列(相应的INFORMATION_SCHEMA.MYSQL_FIREWALL_USERS
表具有相似但不一定相同的列):
USERHOST
在防火墙上注册的帐户。每个帐户具有格式,并代表服务器认证的实际用户名和主机名。注册用户时,不应使用模式和网络掩码。
user_name@host_name
MODE
该帐户当前的防火墙操作模式。允许的模式值
OFF
,DETECTING
,PROTECTING
,RECORDING
,和RESET
。有关其含义的详细信息,请参阅的说明sp_set_firewall_mode()
在 MySQL企业防火墙程序和功能。
该mysql.firewall_whitelist
表列出了已注册的防火墙帐户及其白名单。该表具有以下列(相应的INFORMATION_SCHEMA.MYSQL_FIREWALL_WHITELIST
表具有相似但不一定相同的列):
USERHOST
在防火墙上注册的帐户。格式与用户帐户表的格式相同。
RULE
指示帐户可接受的对帐单格式的规范化对帐单。帐户白名单是其规则的并集。
ID
一个整数列,它是表的主键。该列是在MySQL 8.0.12中添加的。
MySQL企业防火墙的过程和功能
MySQL企业防火墙具有存储过程,这些过程执行诸如在防火墙中注册MySQL帐户,建立其操作模式以及管理缓存与底层系统表之间的防火墙数据传输之类的任务。它还具有一组用户定义函数(UDF),这些函数为较低级别的任务提供了SQL级别的API,例如将缓存与基础系统表同步。
在正常操作下,存储过程将实现用户界面。UDF由存储过程调用,而不是由用户直接调用。
要在默认数据库不是包含该过程的数据库时调用存储过程,请用数据库名称限定过程名称。例如:
CALL mysql.sp_set_firewall_mode(user, mode);
下表描述了每个防火墙存储过程和UDF:
sp_reload_firewall_rules(user)
此存储过程使用防火墙UDF重置注册帐户,并从
mysql.firewall_whitelist
表中存储的规则为其重新加载内存中规则。此过程可控制单个帐户的防火墙操作。该
user
参数以字符串形式将受影响的帐户命名为字符串。user_name@host_name
例:
CALL mysql.sp_reload_firewall_rules('fwuser@localhost');警告
此过程将帐户模式设置为
RESET
,这将清除帐户白名单并将其模式设置为OFF
。如果帐户模式不在呼叫OFF
之前,sp_reload_firewall_rules()
请sp_set_firewall_mode()
在重新加载规则后使用来恢复其先前的模式。例如,如果该帐户处于PROTECTING
模式下,则在调用后不再如此sp_reload_firewall_rules()
,您必须PROTECTING
再次将其设置为显式。sp_set_firewall_mode(user,mode)
该存储过程向防火墙注册了一个MySQL帐户并建立其操作模式。该过程还根据需要调用防火墙UDF,以在缓存和基础系统表之间传输防火墙数据。即使
mysql_firewall_mode
系统变量为OFF
,也可以调用此过程,尽管在禁用防火墙的情况下为帐户设置模式没有任何作用。该
user
参数以字符串形式将受影响的帐户命名为字符串。user_name@host_name
mode
是该用户的动作模式,作为字符串。允许这些模式值:OFF
:禁用该帐户的防火墙。DETECTING
:入侵检测模式:将可疑(不匹配)语句写入错误日志,但不拒绝访问。PROTECTING
:通过将传入对帐单与帐户白名单进行匹配来保护帐户。RECORDING
:培训模式:记录该帐户可接受的对帐单。不会立即因语法错误而失败的传入语句被记录为帐户白名单规则的一部分。RESET
:清除帐户白名单并将帐户模式设置为OFF
。
将帐户的模式切换为任何模式,但
RECORDING
将防火墙高速缓存数据同步到基础mysql
系统数据库表以进行持久存储。将模式从切换OFF
为RECORDING
会将白名单从mysql.firewall_whitelist
表重新加载到缓存中。如果帐户的白名单为空,
PROTECTING
则将其模式设置为产生一条错误消息,该错误消息将在结果集中返回,但不会出现SQL错误:mysql>
CALL mysql.sp_set_firewall_mode('a@b','PROTECTING'); +---------------------------------------------------------------------- + | set_firewall_mode(arg_userhost, arg_mode) | +---------------------------------------------------------------------- + | ERROR: PROTECTING mode requested for a@b but the whitelist is empty. | +---------------------------------------------------------------------- + 1 row in set (0.02 sec) Query OK, 0 rows affected (0.02 sec)mysql_firewall_flush_status()
此UDF将几个防火墙状态变量重置为0:
Firewall_access_denied Firewall_access_granted Firewall_access_suspicious
例:
SELECT mysql_firewall_flush_status();normalize_statement(stmt)
此UDF将SQL语句标准化为用于白名单规则的摘要形式。
例:
SELECT normalize_statement('SELECT * FROM t1 WHERE c1 > 2');read_firewall_users(user,mode)
此聚合UDF通过
SELECT
表上的语句更新防火墙用户缓存mysql.firewall_users
。例:
SELECT read_firewall_users('fwuser@localhost', 'RECORDING')FROM mysql.firewall_users;read_firewall_whitelist(user,rule)
此聚合UDF通过
SELECT
表上的一条语句更新记录的语句高速缓存mysql.firewall_whitelist
。例:
SELECT read_firewall_whitelist('fwuser@localhost', 'RECORDING')FROM mysql.firewall_whitelist;set_firewall_mode(user,mode)
该UDF管理用户缓存并建立用户操作模式。
例:
SELECT set_firewall_mode('fwuser@localhost', 'RECORDING');
MySQL企业防火墙系统变量
MySQL企业防火墙支持以下系统变量。使用它们来配置防火墙操作。除非安装了防火墙,否则这些变量不可用(请)。
mysql_firewall_mode
属性 值 命令行格式 --mysql-firewall-mode[={OFF|ON}]
系统变量 mysql_firewall_mode
范围 Global 动态 是 SET_VAR
提示适用没有 类型 布尔型 默认值 ON
MySQL企业防火墙是启用(默认)还是禁用。
mysql_firewall_trace
属性 值 命令行格式 --mysql-firewall-trace[={OFF|ON}]
系统变量 mysql_firewall_trace
范围 Global 动态 是 SET_VAR
提示适用没有 类型 布尔型 默认值 OFF
MySQL企业防火墙跟踪是启用还是禁用(默认)。当
mysql_firewall_trace
启用时,为PROTECTING
模式,防火墙写入拒绝语句错误日志。
MySQL企业防火墙状态变量
MySQL企业防火墙支持以下状态变量。使用它们来获取有关防火墙运行状态的信息。除非安装了防火墙,否则这些变量不可用(请)。每当MYSQL_FIREWALL
安装插件或启动服务器时,防火墙状态变量都设置为0 。mysql_firewall_flush_status()
UDF 将其中许多重置为零(请参阅 MySQL企业防火墙过程和功能)。
Firewall_access_denied
MySQL企业防火墙拒绝的语句数。
Firewall_access_granted
MySQL企业防火墙接受的语句数。
Firewall_access_suspicious
MySQL Enterprise Firewall记录为处于
DETECTING
模式下的用户可疑的语句数。Firewall_cached_entries
MySQL企业防火墙记录的语句数,包括重复项。