在使用 MySQL Enterprise Firewall 之前,請依照第 8.4.7.2 節〈安裝或解除安裝 MySQL Enterprise Firewall〉中的指示進行安裝。
本節說明如何使用 SQL 陳述式設定 MySQL Enterprise Firewall。或者,MySQL Workbench 6.3.4 或更高版本提供防火牆控制的圖形介面。請參閱MySQL Enterprise Firewall 介面。
若要啟用或停用防火牆,請設定 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 節〈用於變數指派的 SET 語法〉。
每次 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
全域系統變數設定為 60 到主機伺服器平台 INT_MAX 巨集值之間的數字。介於零和 60 (1 到 59) 之間的值會重設為 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
系統資料庫或自訂的綱要(請參閱安裝 MySQL Enterprise Firewall)。
FIREWALL_EXEMPT
、FIREWALL_ADMIN
和 FIREWALL_USER
權限只能在安裝防火牆時授予,因為 MYSQL_FIREWALL
外掛程式定義了這些權限。
MySQL 伺服器允許用戶端連線並接收它們要執行的 SQL 語句。如果啟用防火牆,伺服器會將每個未立即因語法錯誤而失敗的傳入語句傳遞給它。根據防火牆是否接受該語句,伺服器會執行該語句或向用戶端傳回錯誤。本節說明防火牆如何完成接受或拒絕語句的任務。
防火牆設定檔
防火牆使用設定檔的登錄,以決定是否允許語句執行。設定檔具有以下屬性
一個允許清單。允許清單是定義設定檔可接受哪些語句的規則集。
當前操作模式。此模式使設定檔能夠以不同的方式使用。例如:可以將設定檔置於訓練模式以建立允許清單;允許清單可以用於限制語句執行或入侵偵測;可以完全停用設定檔。
適用範圍。範圍指示設定檔適用於哪些用戶端連線
防火牆支援基於帳戶的設定檔,以便每個設定檔都符合特定的用戶端帳戶(用戶端使用者名稱和主機名稱組合)。例如,您可以註冊一個帳戶設定檔,其中允許清單適用於來自
admin@localhost
的連線,以及另一個帳戶設定檔,其中允許清單適用於來自myapp@apphost.example.com
的連線。防火牆支援群組設定檔,這些設定檔可以有多個帳戶作為成員,並且設定檔允許清單同等地適用於所有成員。群組設定檔可以更輕鬆地管理,並為需要將一組給定的允許清單規則套用於多個帳戶的部署提供更大的彈性。
最初,不存在任何設定檔,因此預設情況下,防火牆會接受所有語句,並且不會影響 MySQL 帳戶可以執行哪些語句。若要應用防火牆保護功能,則需要明確的操作
向防火牆註冊一個或多個設定檔。
透過建立每個設定檔的允許清單來訓練防火牆;也就是說,設定檔允許用戶端執行的語句類型。
將經過訓練的設定檔置於保護模式,以加強 MySQL 對未經授權語句執行的防禦能力
MySQL 將每個用戶端連線與特定的使用者名稱和主機名稱組合相關聯。此組合是連線帳戶。
對於每個用戶端連線,防火牆會使用連線帳戶來決定哪些設定檔適用於處理來自用戶端的傳入語句。
防火牆僅接受適用設定檔允許清單所允許的語句。
大多數防火牆原則同樣適用於群組設定檔和帳戶設定檔。這兩種設定檔類型在以下方面有所不同
帳戶設定檔允許清單僅適用於單一帳戶。當連線帳戶符合群組的任何成員帳戶時,群組設定檔允許清單才適用。
若要使用帳戶設定檔將允許清單套用於多個帳戶,則必須為每個帳戶註冊一個設定檔,並在每個設定檔中複製允許清單。這需要單獨訓練每個帳戶設定檔,因為必須使用其適用的單一帳戶來訓練每個帳戶設定檔。
群組設定檔允許清單適用於多個帳戶,無需為每個帳戶複製它。可以使用任何或所有群組成員帳戶來訓練群組設定檔,或將訓練限制為任何單一成員。無論哪種方式,允許清單都適用於所有成員。
帳戶設定檔名稱基於特定的使用者名稱和主機名稱組合,而這些組合取決於哪些用戶端連線到 MySQL 伺服器。群組設定檔名稱由防火牆管理員選擇,除了長度必須為 1 到 288 個字元之外,沒有其他限制。
由於群組設定檔優於帳戶設定檔,而且具有單一成員帳戶的群組設定檔在邏輯上等同於該帳戶的帳戶設定檔,因此建議將所有新的防火牆設定檔建立為群組設定檔。帳戶設定檔已棄用,並將在未來版本的 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` = ?
透過使用標準化,防火牆允許清單可以儲存每個都符合從用戶端接收的多個不同語句的摘要。如需有關標準化和摘要的詳細資訊,請參閱第 29.10 節「Performance Schema 語句摘要和取樣」。
將 max_digest_length
系統變數設定為零會停用摘要產生,這也會停用需要摘要的伺服器功能,例如 MySQL Enterprise Firewall。
設定檔操作模式
在防火牆中註冊的每個設定檔都有其自己的操作模式,可從以下值中選擇
OFF
:此模式會停用設定檔。防火牆會將其視為不活動並忽略它。RECORDING
:這是防火牆訓練模式。從符合設定檔的用戶端接收的傳入語句被認為對設定檔是可接受的,並成為其「指紋」的一部分。防火牆會記錄每個語句的標準化摘要形式,以學習設定檔的可接受語句模式。每個模式都是一個規則,而規則的聯集就是設定檔允許清單。群組設定檔和帳戶設定檔之間的差異在於,群組設定檔的語句記錄可以限制為從單一群組成員(訓練成員)接收的語句。
PROTECTING
:在此模式下,設定檔允許或防止語句執行。防火牆會根據設定檔允許清單比對傳入語句,僅接受符合的語句並拒絕不符合的語句。在RECORDING
模式中訓練設定檔後,將其切換到PROTECTING
模式,以加強 MySQL 對偏離允許清單的語句存取的防禦能力。如果啟用mysql_firewall_trace
系統變數,防火牆也會將拒絕的語句寫入錯誤日誌。DETECTING
:此模式會偵測但不封鎖入侵(由於與設定檔允許清單中的任何內容都不符,因而可疑的語句)。在DETECTING
模式中,防火牆會將可疑語句寫入錯誤日誌,但會接受它們而不拒絕存取。
當將任何上述模式值指派給設定檔時,防火牆會將該模式儲存在設定檔中。防火牆模式設定操作也允許 RESET
的模式值,但此值不會儲存:將設定檔設定為 RESET
模式會導致防火牆刪除設定檔的所有規則,並將其模式設定為 OFF
。
在 DETECTING
模式下或因為啟用 mysql_firewall_trace
而寫入錯誤日誌的訊息會寫成附註,即資訊訊息。若要確保此類訊息會出現在錯誤日誌中且不會被捨棄,請確保錯誤記錄詳細程度足以包含資訊訊息。例如,如果您使用的是基於優先順序的日誌篩選(如第 7.4.2.5 節「基於優先順序的錯誤日誌篩選 (log_filter_internal)」所述),請將 log_error_verbosity
系統變數設定為值 3。
當多個設定檔套用時的防火牆語句處理
為了簡化說明,後續章節將從防火牆僅針對單一設定檔(群組設定檔或帳號設定檔)比對來自用戶端的傳入語句的角度來描述如何設定設定檔。但防火牆的運作可能更複雜。
一個群組設定檔可以包含多個帳號作為成員。
一個帳號可以是多個群組設定檔的成員。
多個設定檔可以比對到同一個用戶端。
以下描述涵蓋防火牆運作的一般情況,當有多個設定檔可能套用於傳入的語句時。
如先前所述,MySQL 將每個客戶端連線與特定的使用者名稱和主機名稱組合相關聯,稱為連線帳號。防火牆會將連線帳號與已註冊的設定檔比對,以確定哪些設定檔適用於處理來自該連線的傳入語句。
防火牆會忽略非作用中的設定檔(模式為
OFF
的設定檔)。連線帳號會比對到每個包含具有相同使用者和主機之成員的作用中群組設定檔。可以有多個這樣的群組設定檔。
連線帳號會比對到具有相同使用者和主機的作用中帳號設定檔(如果有的話)。最多只有一個這樣的帳號設定檔。
換句話說,連線帳號可以比對到 0 個或多個作用中的群組設定檔,以及 0 個或 1 個作用中的帳號設定檔。這表示對於給定的連線,可能適用 0 個、1 個或多個防火牆設定檔,而防火牆會按如下方式處理每個傳入的語句:
如果沒有適用的設定檔,則防火牆不會施加任何限制並接受該語句。
如果有適用的設定檔,則其模式會決定語句的處理方式:
防火牆會將該語句記錄在每個處於
RECORDING
模式的適用設定檔的允許清單中。對於每個處於
DETECTING
模式且語句可疑(與設定檔允許清單不符)的適用設定檔,防火牆會將該語句寫入錯誤日誌。如果至少有一個適用的設定檔處於
RECORDING
或DETECTING
模式(這些模式接受所有語句),或者如果該語句與至少一個處於PROTECTING
模式的適用設定檔的允許清單相符,則防火牆會接受該語句。否則,防火牆會拒絕該語句(如果啟用mysql_firewall_trace
系統變數,則會將其寫入錯誤日誌)。
了解以上描述後,接下來的章節將回到單一群組設定檔或單一帳號設定檔適用的簡單情況,並涵蓋如何設定每種類型的設定檔。
MySQL Enterprise Firewall 支援註冊群組設定檔。群組設定檔可以有多個帳號作為其成員。若要使用防火牆群組設定檔來保護 MySQL 免受來自指定帳號的傳入語句侵害,請按照下列步驟執行:
註冊群組設定檔並將其置於
RECORDING
模式。將成員帳號新增至群組設定檔。
使用成員帳號連線至 MySQL 伺服器並執行要學習的語句。這將訓練群組設定檔並建立構成設定檔允許清單的規則。
將任何其他要成為群組成員的帳號新增至群組設定檔。
將群組設定檔切換至
PROTECTING
模式。當客戶端使用群組設定檔的任何成員帳號連線至伺服器時,設定檔允許清單會限制語句的執行。如果需要其他訓練,請再次將群組設定檔切換至
RECORDING
模式,使用新的語句模式更新其允許清單,然後將其切換回PROTECTING
模式。
請注意以下與防火牆相關的帳號參照指南:
請注意發生帳號參照的內容。若要為防火牆操作命名帳號,請將其指定為單引號字串(
'
)。這與使用者名稱
@主機名稱
'CREATE USER
和GRANT
等語句的常見 MySQL 慣例不同,對於這些語句,您需要分別以引號括住帳號名稱的使用者和主機部分('
)。使用者名稱
'@'主機名稱
'為防火牆操作將帳號命名為單引號字串的要求表示您無法使用使用者名稱中內嵌有
@
字元的帳號。防火牆會根據伺服器驗證的實際使用者和主機名稱來評估針對帳號的語句。在設定檔中註冊帳號時,請勿使用萬用字元或網路遮罩。
假設存在一個名為
me@%.example.org
的帳號,且用戶端使用該帳號從主機abc.example.org
連線至伺服器。帳號名稱包含
%
萬用字元,但伺服器會驗證用戶端具有me
的使用者名稱和abc.example.com
的主機名稱,這也是防火牆所看到的。因此,用於防火牆操作的帳號名稱是
me@abc.example.org
,而不是me@%.example.org
。
以下程序說明如何向防火牆註冊群組設定檔,訓練防火牆了解該設定檔的可接受語句(其允許清單),使用設定檔保護 MySQL 免受不可接受語句的執行,以及新增和移除群組成員。範例使用名為 fwgrp
的群組設定檔名稱。假設此範例設定檔供應用程式的用戶端使用,該應用程式會存取 sakila
資料庫中的表格(可在 https://mysqldev.dev.org.tw/doc/index-other.html 取得)。
使用管理 MySQL 帳號來執行此程序中的步驟,但指定由防火牆群組設定檔的成員帳號執行的步驟除外。對於由成員帳號執行的語句,預設資料庫應為 sakila
。(您可以透過適當調整說明來使用不同的資料庫。)
如有必要,請建立要成為
fwgrp
群組設定檔成員的帳號,並授予他們適當的存取權限。以下顯示一個成員的語句(選擇適當的密碼):CREATE USER 'member1'@'localhost' IDENTIFIED BY 'password'; GRANT ALL ON sakila.* TO 'member1'@'localhost';
使用
sp_set_firewall_group_mode()
預存程序向防火牆註冊群組設定檔,並將設定檔置於RECORDING
(訓練)模式:CALL mysql.sp_set_firewall_group_mode('fwgrp', 'RECORDING');
注意如果您在自訂結構描述中安裝了 MySQL Enterprise Firewall,請為您的系統進行適當的替代。例如,如果防火牆安裝在
fwdb
結構描述中,則執行如下的預存程序:CALL fwdb.sp_set_firewall_group_mode('fwgrp', 'RECORDING');
使用
sp_firewall_group_enlist()
預存程序新增初始成員帳號,以用於訓練群組設定檔允許清單:CALL mysql.sp_firewall_group_enlist('fwgrp', 'member1@localhost');
若要使用初始成員帳號訓練群組設定檔,請從伺服器主機以
member1
的身分連線至伺服器,以便防火牆看到member1@localhost
的連線帳號。然後執行一些要視為設定檔合法的語句。例如: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
帳號接收語句。由於該帳號是處於RECORDING
模式的fwgrp
設定檔的成員,因此防火牆會將語句解釋為適用於fwgrp
,並將語句的標準化摘要形式記錄為fwgrp
允許清單中的規則。然後,這些規則會套用於fwgrp
的所有成員帳號。注意在
fwgrp
群組設定檔在RECORDING
模式下接收語句之前,其允許清單是空的,這相當於「全部拒絕」。沒有語句可以比對到空的允許清單,這具有以下含義:無法將群組設定檔切換至
PROTECTING
模式。它會拒絕每個語句,有效地禁止身為群組成員的帳號執行任何語句。可以將群組設定檔切換至
DETECTING
模式。在這種情況下,設定檔會接受每個語句,但會將其記錄為可疑。
此時,群組設定檔資訊會快取,包括其名稱、成員資格和允許清單。若要查看此資訊,請查詢 Performance Schema 防火牆表格:
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` | +----------------------------------------------------------------------+
注意@@version_comment
規則來自您連線至伺服器時,mysql 用戶端自動傳送的語句。重要事項在符合應用程式使用的情況下訓練防火牆。例如,為了確定伺服器的特性和功能,指定的 MySQL 連接器可能會在每個連線開始時向伺服器傳送語句。如果應用程式通常透過該連接器使用,也請使用連接器訓練防火牆。這樣可以讓這些初始語句成為與應用程式關聯的群組設定檔的允許清單的一部分。
再次叫用
sp_set_firewall_group_mode()
以將群組設定檔切換至PROTECTING
模式:CALL mysql.sp_set_firewall_group_mode('fwgrp', 'PROTECTING');
重要事項將群組設定檔切換出
RECORDING
模式會將其快取的資料同步到提供持續基礎儲存的防火牆資料庫表格。如果您未切換正在記錄的設定檔的模式,則快取的資料不會寫入到持續儲存,並且在重新啟動伺服器時會遺失。防火牆資料庫可以是mysql
系統資料庫或自訂結構描述(請參閱 安裝 MySQL Enterprise Firewall)。將任何其他應為成員的帳號新增至群組設定檔:
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
帳號訓練的設定檔允許清單也適用於其他帳號。若要驗證更新的群組成員資格,請再次查詢
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 | +----------+-------------------+
透過使用群組中的任何帳戶執行一些可接受和不可接受的語句,來針對防火牆測試群組設定檔。防火牆會將帳戶中的每個語句與設定檔的允許清單進行比對,並接受或拒絕它。
此語句與訓練語句不完全相同,但會產生與其中一個相同的正規化語句,因此防火牆會接受它。
mysql> SELECT title, release_year FROM film WHERE film_id = 98; +-------------------+--------------+ | title | release_year | +-------------------+--------------+ | BRIGHT ENCOUNTERS | 2006 | +-------------------+--------------+
這些語句與允許清單中的任何內容都不符,因此防火牆會拒絕每個語句並產生錯誤。
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`'
這些日誌訊息可能有助於識別攻擊來源(如有必要)。
如果需要從群組設定檔中移除成員,請使用
sp_firewall_group_delist()
預存程序,而不是sp_firewall_group_enlist()
。CALL mysql.sp_firewall_group_delist('fwgrp', 'member3@localhost');
防火牆群組設定檔現在已針對成員帳戶進行訓練。當用戶端使用群組中的任何帳戶連線並嘗試執行語句時,設定檔會保護 MySQL 免受與設定檔允許清單不符的語句影響。
剛才顯示的程序在訓練允許清單之前,僅將一個成員新增至群組設定檔。這樣做可以更好地控制訓練期間,限制哪些帳戶可以將新的可接受語句新增至允許清單。如果需要進行額外訓練,您可以將設定檔切換回 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
模式下,其他成員可以執行任何語句。)
若要避免將特定帳戶指定為群組設定檔的訓練帳戶時發生非預期的行為,請務必確保該帳戶是群組的成員。
額外訓練後,將群組設定檔設定回 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);
可以透過將不符合的語句記錄為可疑,而不會拒絕存取來偵測入侵。首先,將群組設定檔設定為 DETECTING
模式。
CALL mysql.sp_set_firewall_group_mode('fwgrp', 'DETECTING');
然後,使用成員帳戶執行與群組設定檔允許清單不符的語句。在 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 ?'
若要停用群組設定檔,請將其模式變更為 OFF
。
CALL mysql.sp_set_firewall_group_mode(group, 'OFF');
若要忘記設定檔的所有訓練並停用它,請重設它。
CALL mysql.sp_set_firewall_group_mode(group, 'RESET');
重設操作會導致防火牆刪除設定檔的所有規則,並將其模式設定為 OFF
。
MySQL Enterprise Firewall 允許註冊對應於個別帳戶的設定檔。若要使用防火牆帳戶設定檔來保護 MySQL 免受來自特定帳戶的傳入語句影響,請依照下列步驟執行:
註冊帳戶設定檔並將其設定為
RECORDING
模式。使用該帳戶連線至 MySQL 伺服器,並執行要學習的語句。這會訓練帳戶設定檔並建立構成設定檔允許清單的規則。
將帳戶設定檔切換為
PROTECTING
模式。當用戶端使用該帳戶連線至伺服器時,帳戶設定檔允許清單會限制語句執行。如果需要進行額外訓練,請再次將帳戶設定檔切換為
RECORDING
模式,使用新的語句模式更新其允許清單,然後將其切換回PROTECTING
模式。
請注意以下與防火牆相關的帳號參照指南:
請注意發生帳號參照的內容。若要為防火牆操作命名帳號,請將其指定為單引號字串(
'
)。這與使用者名稱
@主機名稱
'CREATE USER
和GRANT
等語句的常見 MySQL 慣例不同,對於這些語句,您需要分別以引號括住帳號名稱的使用者和主機部分('
)。使用者名稱
'@'主機名稱
'為防火牆操作將帳號命名為單引號字串的要求表示您無法使用使用者名稱中內嵌有
@
字元的帳號。防火牆會根據伺服器驗證的實際使用者和主機名稱來評估針對帳號的語句。在設定檔中註冊帳號時,請勿使用萬用字元或網路遮罩。
假設存在一個名為
me@%.example.org
的帳號,且用戶端使用該帳號從主機abc.example.org
連線至伺服器。帳號名稱包含
%
萬用字元,但伺服器會驗證用戶端具有me
的使用者名稱和abc.example.com
的主機名稱,這也是防火牆所看到的。因此,用於防火牆操作的帳號名稱是
me@abc.example.org
,而不是me@%.example.org
。
以下程序顯示如何向防火牆註冊帳戶設定檔、訓練防火牆以瞭解該設定檔的可接受語句(其允許清單),並使用該設定檔來保護 MySQL 免受帳戶執行不可接受的語句影響。範例帳戶 fwuser@localhost
假設由應用程式使用,該應用程式會存取 sakila
資料庫中的資料表(可從 https://mysqldev.dev.org.tw/doc/index-other.html 取得)。
請使用管理 MySQL 帳戶執行此程序中的步驟,但指定由 fwuser@localhost
帳戶執行的步驟除外,該帳戶對應於向防火牆註冊的帳戶設定檔。對於使用此帳戶執行的語句,預設資料庫應為 sakila
。(您可以透過調整指示來使用不同的資料庫。)
如有必要,請建立用於執行語句的帳戶(選擇適當的密碼)並授與其
sakila
資料庫的權限。CREATE USER 'fwuser'@'localhost' IDENTIFIED BY 'password'; GRANT ALL ON sakila.* TO 'fwuser'@'localhost';
使用
sp_set_firewall_mode()
預存程序,向防火牆註冊帳戶設定檔,並將設定檔置於RECORDING
(訓練)模式。CALL mysql.sp_set_firewall_mode('fwuser@localhost', 'RECORDING');
注意如果您在自訂結構描述中安裝了 MySQL Enterprise Firewall,請為您的系統進行適當的替代。例如,如果防火牆安裝在
fwdb
結構描述中,則執行如下的預存程序:CALL fwdb.sp_set_firewall_mode('fwuser@localhost', 'RECORDING');
若要訓練已註冊的帳戶設定檔,請從伺服器主機以
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
模式,防火牆會將語句的正規化摘要形式記錄為設定檔允許清單中的規則。注意在
fwuser@localhost
帳戶設定檔在RECORDING
模式中收到語句之前,其允許清單為空,這相當於 「全部拒絕」。沒有任何語句可以符合空的允許清單,這具有以下含義:帳戶設定檔無法切換為
PROTECTING
模式。它會拒絕每個語句,有效地禁止該帳戶執行任何語句。帳戶設定檔可以切換為
DETECTING
模式。在這種情況下,設定檔會接受每個語句,但會將其記錄為可疑。
此時,會快取帳戶設定檔資訊。若要查看此資訊,請查詢
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 ? | +----------------------------------------------------------------------------+
注意@@version_comment
規則來自您連線至伺服器時,mysql 用戶端自動傳送的語句。重要事項在符合應用程式使用情況的條件下訓練防火牆。例如,若要判斷伺服器特性和功能,給定的 MySQL 連接器可能會在每個工作階段開始時將語句傳送至伺服器。如果應用程式通常透過該連接器使用,也請使用該連接器訓練防火牆。這樣可以使這些初始語句成為與應用程式關聯的帳戶設定檔允許清單的一部分。
再次叫用
sp_set_firewall_mode()
,這次將帳戶設定檔切換為PROTECTING
模式。CALL mysql.sp_set_firewall_mode('fwuser@localhost', 'PROTECTING');
重要事項將帳戶設定檔切換出
RECORDING
模式會將其快取的資料同步至提供持續基礎儲存的防火牆資料庫資料表。如果您沒有切換正在記錄之設定檔的模式,則快取的資料不會寫入持續儲存,並且會在重新啟動伺服器時遺失。防火牆資料庫可以是mysql
系統資料庫或自訂結構描述(請參閱安裝 MySQL Enterprise Firewall)。透過使用該帳戶執行一些可接受和不可接受的語句,來測試帳戶設定檔。防火牆會將帳戶中的每個語句與設定檔的允許清單進行比對,並接受或拒絕它。
此語句與訓練語句不完全相同,但會產生與其中一個相同的正規化語句,因此防火牆會接受它。
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 |
+----------------------------+-------+
這些變數分別指示拒絕、接受、記錄為可疑以及新增至快取的語句數。由於您使用已註冊的帳戶連線三次,每次 mysql 用戶端傳送了 @@version_comment
語句,加上 DETECTING
模式下未封鎖的 SHOW TABLES
語句,因此 Firewall_access_granted
計數為 4。
MySQL Enterprise Firewall 支援帳戶設定檔,每個設定檔適用於單一帳戶;同時也支援群組設定檔,每個設定檔可以套用至多個帳戶。當相同的允許清單要套用至多個帳戶時,群組設定檔可簡化管理:不必為每個帳戶建立一個帳戶設定檔,並在所有設定檔中複製允許清單,而是建立單一群組設定檔,並讓這些帳戶成為其成員。接著,群組允許清單便會套用至所有帳戶。
具有單一成員帳戶的群組設定檔,在邏輯上等同於該帳戶的帳戶設定檔,因此可以使用群組設定檔來專門管理防火牆,而不是混合使用帳戶和群組設定檔。對於新的防火牆安裝,可以將新設定檔統一建立為群組設定檔,並避免使用帳戶設定檔來達成。
由於群組設定檔提供更大的彈性,建議將所有新的防火牆設定檔都建立為群組設定檔。帳戶設定檔已被棄用,並可能在未來 MySQL 版本中移除。對於從已包含帳戶設定檔的防火牆安裝進行升級的情況,MySQL Enterprise Firewall 包含一個名為 sp_migrate_firewall_user_to_group()
的預存程序,以協助您將帳戶設定檔轉換為群組設定檔。若要使用它,請以擁有 FIREWALL_ADMIN
權限的使用者執行下列程序
執行
firewall_profile_migration.sql
腳本以安裝sp_migrate_firewall_user_to_group()
預存程序。此腳本位於 MySQL 安裝的share
目錄中。在命令列上指定先前為防火牆安裝定義的相同防火牆資料庫名稱。此範例指定系統資料庫
mysql
。$> mysql -u root -p -D mysql < firewall_profile_migration.sql Enter password: (enter root password here)
如果您將 MySQL Enterprise Firewall 安裝在自訂綱要中,請針對您的系統進行適當的替換。
透過查詢資訊綱要
MYSQL_FIREWALL_USERS
表格,來識別現有的帳戶設定檔。例如:mysql> SELECT USERHOST FROM INFORMATION_SCHEMA.MYSQL_FIREWALL_USERS; +-------------------------------+ | USERHOST | +-------------------------------+ | admin@localhost | | local_client@localhost | | remote_client@abc.example.com | +-------------------------------+
對於前一步驟中識別的每個帳戶設定檔,將其轉換為群組設定檔。如有必要,請將
mysql.
前綴替換為實際的防火牆資料庫名稱。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
模式,且群組設定檔不能已存在。產生的群組設定檔將指定的帳戶作為其唯一的加入成員,該成員也會被設定為群組的訓練帳戶。群組設定檔的運作模式取自帳戶設定檔的運作模式。(選擇性)移除
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()
的其他詳細資訊,請參閱防火牆其他預存程序。