文件首頁
MySQL 9.0 參考手冊
相關文件 下載本手冊
PDF (US Ltr) - 40.0Mb
PDF (A4) - 40.1Mb
Man Pages (TGZ) - 258.2Kb
Man Pages (Zip) - 365.3Kb
Info (Gzip) - 4.0Mb
Info (Zip) - 4.0Mb


MySQL 9.0 參考手冊  /  ...  /  使用 MySQL Enterprise Firewall

8.4.7.3 使用 MySQL Enterprise Firewall

在使用 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 巨集值之間的數字。值介於 0 和 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_EXEMPTFIREWALL_ADMINFIREWALL_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 節,〈效能結構描述陳述式摘要和採樣〉

警告

max_digest_length 系統變數設定為零會停用摘要產生,這也會停用需要摘要的伺服器功能,例如 MySQL Enterprise Firewall。

設定檔操作模式

在防火牆註冊的每個設定檔都有其自己的操作模式,可從以下值中選擇

  • OFF:此模式會停用設定檔。防火牆會將其視為非活動狀態並忽略它。

  • RECORDING:這是防火牆訓練模式。從符合設定檔的客戶端接收的傳入陳述式被認為是設定檔可接受的,並成為其「「指紋」。」防火牆會記錄每個陳述式的標準化摘要形式,以了解設定檔的可接受陳述式模式。每個模式都是一個規則,而這些規則的並集就是設定檔允許清單。

    群組設定檔和帳戶設定檔之間的一個區別是,群組設定檔的陳述式記錄可以限制為從單個群組成員(訓練成員)接收的陳述式。

  • PROTECTING:在此模式下,設定檔會允許或阻止陳述式執行。防火牆會將傳入陳述式與設定檔允許清單進行匹配,僅接受匹配的陳述式,並拒絕不匹配的陳述式。在 RECORDING 模式下訓練設定檔後,將其切換為 PROTECTING 模式,以強化 MySQL 免受偏離允許清單的陳述式存取。如果啟用 mysql_firewall_trace 系統變數,防火牆還會將拒絕的陳述式寫入錯誤日誌。

  • DETECTING:此模式會偵測但不會阻止入侵(因與設定檔允許清單中的任何內容都不匹配而可疑的陳述式)。在 DETECTING 模式下,防火牆會將可疑陳述式寫入錯誤日誌,但會接受它們而不拒絕存取。

當設定檔被指派任何上述模式值時,防火牆會將該模式儲存在設定檔中。防火牆模式設定操作也允許 RESET 模式值,但不會儲存此值:將設定檔設定為 RESET 模式會導致防火牆刪除該設定檔的所有規則,並將其模式設定為 OFF

注意

DETECTING 模式或因為啟用 mysql_firewall_trace 而寫入錯誤日誌的訊息會作為 Notes(資訊訊息)寫入。若要確保此類訊息出現在錯誤日誌中且未被丟棄,請確保錯誤記錄詳細程度足以包含資訊訊息。例如,如果您正在使用基於優先順序的日誌篩選,如第 7.4.2.5 節,〈基於優先順序的錯誤日誌篩選 (log_filter_internal)〉中所述,請將 log_error_verbosity 系統變數設定為值 3。

當套用多個設定檔時的防火牆陳述式處理

為了簡單起見,稍後描述如何設定設定檔的章節將從防火牆將來自客戶端的傳入陳述式與單個設定檔(群組設定檔或帳戶設定檔)進行匹配的角度來看。但是防火牆操作可能更複雜

  • 群組設定檔可以包含多個帳戶作為成員。

  • 一個帳戶可以成為多個群組設定檔的成員。

  • 多個設定檔可以匹配給定的客戶端。

以下說明涵蓋了當多個設定檔可能適用於傳入的語句時,防火牆如何運作的一般情況。

如前所述,MySQL 將每個客戶端會話與特定的使用者名稱和主機名稱組合(稱為會話帳戶)相關聯。防火牆會將會話帳戶與已註冊的設定檔進行比對,以確定哪些設定檔適用於處理來自該會話的傳入語句。

  • 防火牆會忽略非活動設定檔(模式為 OFF 的設定檔)。

  • 如果群組設定檔包含具有相同使用者和主機的成員,則會話帳戶會與每個活動的群組設定檔匹配。可能有多個這樣的群組設定檔。

  • 如果存在具有相同使用者和主機的活動帳戶設定檔,則會話帳戶會與該設定檔匹配。最多只有一個這樣的帳戶設定檔。

換句話說,會話帳戶可以匹配 0 個或多個活動的群組設定檔,以及 0 個或 1 個活動的帳戶設定檔。這表示 0 個、1 個或多個防火牆設定檔適用於給定的會話,防火牆會對每個傳入的語句執行以下操作:

  • 如果沒有適用的設定檔,防火牆不會施加任何限制,並接受該語句。

  • 如果有適用的設定檔,它們的模式將決定語句的處理方式。

    • 防火牆會將語句記錄在每個處於 RECORDING 模式的適用設定檔的允許清單中。

    • 對於每個處於 DETECTING 模式且語句可疑(與設定檔允許清單不匹配)的適用設定檔,防火牆會將語句寫入錯誤日誌。

    • 如果至少有一個適用的設定檔處於 RECORDINGDETECTING 模式(這些模式接受所有語句),或者如果語句與至少一個處於 PROTECTING 模式的適用設定檔的允許清單匹配,則防火牆接受該語句。否則,防火牆會拒絕該語句(如果啟用了 mysql_firewall_trace 系統變數,則會將其寫入錯誤日誌)。

考慮到上述說明,接下來的章節將回歸到單一群組設定檔或單一帳戶設定檔適用的簡單情況,並介紹如何設定每種設定檔。

註冊防火牆群組設定檔

MySQL Enterprise Firewall 支援註冊群組設定檔。一個群組設定檔可以有多個帳戶作為其成員。若要使用防火牆群組設定檔來保護 MySQL 免受來自給定帳戶的傳入語句的影響,請依照下列步驟執行:

  1. 註冊群組設定檔,並將其置於 RECORDING 模式。

  2. 將成員帳戶新增至群組設定檔。

  3. 使用成員帳戶連線到 MySQL 伺服器,並執行要學習的語句。這會訓練群組設定檔,並建立構成設定檔允許清單的規則。

  4. 將要成為群組成員的任何其他帳戶新增至群組設定檔。

  5. 將群組設定檔切換為 PROTECTING 模式。當客戶端使用群組設定檔的任何成員帳戶連線到伺服器時,設定檔允許清單會限制語句的執行。

  6. 如果需要額外的訓練,請再次將群組設定檔切換為 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 免受不可接受語句的執行,以及新增和移除群組成員。此範例使用名為 fwgrp 的群組設定檔名稱。此範例設定檔假設供應用程式的客戶端使用,該應用程式會存取 sakila 資料庫中的表格(可從 https://mysqldev.dev.org.tw/doc/index-other.html 取得)。

使用管理員 MySQL 帳戶來執行此程序中的步驟,但指定由防火牆群組設定檔的成員帳戶執行的步驟除外。對於由成員帳戶執行的語句,預設資料庫應為 sakila。(您可以調整說明來使用不同的資料庫。)

  1. 如有必要,請建立要成為 fwgrp 群組設定檔成員的帳戶,並授予它們適當的存取權限。此處顯示一個成員的語句(選擇適當的密碼)

    CREATE USER 'member1'@'localhost' IDENTIFIED BY 'password';
    GRANT ALL ON sakila.* TO 'member1'@'localhost';
  2. 使用 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');

  3. 使用 sp_firewall_group_enlist() 預存程序新增初始成員帳戶,以用於訓練群組設定檔允許清單

    CALL mysql.sp_firewall_group_enlist('fwgrp', 'member1@localhost');
  4. 若要使用初始成員帳戶訓練群組設定檔,請從伺服器主機以 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 模式。在這種情況下,設定檔會接受每個語句,但會將其記錄為可疑。

  5. 此時,群組設定檔資訊會被快取,包括其名稱、成員資格和允許清單。若要查看此資訊,請查詢效能結構描述防火牆表格:

    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 連接器可能會在每個會話開始時將語句傳送到伺服器。如果應用程式通常是透過該連接器使用,也請使用該連接器來訓練防火牆。這會使那些初始語句成為與應用程式關聯的群組設定檔的允許清單的一部分。

  6. 再次叫用 sp_set_firewall_group_mode() 以將群組設定檔切換為 PROTECTING 模式

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

    將群組設定檔切換出 RECORDING 模式會將其快取資料與提供持續基礎儲存的防火牆資料庫表格同步。如果您未切換正在記錄的設定檔的模式,則快取資料不會寫入持續儲存空間,並且會在伺服器重新啟動時遺失。防火牆資料庫可以是 mysql 系統資料庫或自訂結構描述(請參閱安裝 MySQL Enterprise Firewall)。

  7. 將其他應為成員的任何帳戶新增至群組設定檔

    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 帳戶訓練的設定檔允許清單現在也適用於其他帳戶。

  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. 透過使用群組中的任何帳戶執行一些可接受和不可接受的語句來測試防火牆的群組設定檔。防火牆會將帳戶的每個語句與設定檔允許清單進行比對,並接受或拒絕該語句:

    • 此語句與訓練語句不完全相同,但會產生與其中一個相同的標準化語句,因此防火牆會接受它:

      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`'

      這些日誌訊息在必要時可能對識別攻擊來源有所幫助。

  10. 如果需要將成員從群組設定檔中移除,請使用 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 免於來自指定帳戶的輸入語句,請遵循以下步驟:

  1. 註冊帳戶設定檔並將其置於 RECORDING 模式。

  2. 使用該帳戶連線到 MySQL 伺服器,並執行要學習的語句。這會訓練帳戶設定檔,並建立構成設定檔允許清單的規則。

  3. 將帳戶設定檔切換為 PROTECTING 模式。當用戶端使用該帳戶連線到伺服器時,帳戶設定檔允許清單會限制語句的執行。

  4. 如果需要額外訓練,請再次將帳戶設定檔切換為 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://mysqldev.dev.org.tw/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');
    注意

    如果您已將 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 模式,因此防火牆會以規則形式將語句的正規化摘要形式記錄在設定檔允許清單中。

    注意

    fwuser@localhost 帳戶設定檔在 RECORDING 模式下收到語句之前,其允許清單為空白,這相當於「全部拒絕」。 沒有語句可以比對空白允許清單,這會產生以下含義:

    • 無法將帳戶設定檔切換為 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 ?                                         |
    +----------------------------------------------------------------------------+
    注意

    @@version_comment 規則來自當您連線到伺服器時,mysql 客戶端自動傳送的語句。

    重要

    在符合應用程式使用情況的條件下訓練防火牆。例如,若要判斷伺服器特性和功能,指定的 MySQL 連接器可能會在每個工作階段開始時將語句傳送至伺服器。如果應用程式通常是透過該連接器使用,也請使用連接器訓練防火牆。這可讓這些初始語句成為與應用程式相關聯的帳戶設定檔允許清單的一部分。

  5. 再次叫用 sp_set_firewall_mode(),這次將帳戶設定檔切換為 PROTECTING 模式。

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

    將帳戶設定檔切換出 RECORDING 模式,會將其快取的資料同步到提供永久底層儲存的防火牆資料庫表格。如果您沒有切換正在記錄的設定檔的模式,快取的資料將不會寫入永久儲存,並且會在伺服器重新啟動時遺失。防火牆資料庫可以是 mysql 系統資料庫或自訂結構描述(請參閱安裝 MySQL Enterprise Firewall)。

  6. 透過使用該帳戶執行一些可接受和無法接受的語句,來測試帳戶設定檔。防火牆會將來自帳戶的每個語句與設定檔允許清單比對,並接受或拒絕它。

    • 此語句與訓練語句不完全相同,但會產生與其中一個相同的標準化語句,因此防火牆會接受它:

      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 權限的使用者執行以下程序

  1. 執行 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,請對您的系統進行適當的替換。

  2. 透過查詢資訊綱要 MYSQL_FIREWALL_USERS 表格,找出哪些帳戶設定檔存在。例如:

    mysql> SELECT USERHOST FROM INFORMATION_SCHEMA.MYSQL_FIREWALL_USERS;
    +-------------------------------+
    | USERHOST                      |
    +-------------------------------+
    | admin@localhost               |
    | local_client@localhost        |
    | remote_client@abc.example.com |
    +-------------------------------+
  3. 對於先前步驟識別的每個帳戶設定檔,將其轉換為群組設定檔。如有必要,請將 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 模式,且群組設定檔不得已存在。產生的群組設定檔會將指定的帳戶作為其單一登錄成員,該成員也會設定為群組訓練帳戶。群組設定檔的運作模式取自帳戶設定檔的運作模式。

  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() 的更多詳細資訊,請參閱防火牆雜項預存程序