設定自訂規則語言屬性

每條 Google Cloud Armor 安全性政策規則都有優先順序、相符條件和動作。Cloud Armor 會根據與要求相符的最高優先順序規則執行動作。如果規則的優先順序低於優先順序最高的相符規則,即使兩者具有相同的相符條件,系統也不會評估該規則。

每項安全性政策規則都支援兩種類型的比對條件:

  • 基本比對條件包含 IP 位址清單或 IP 位址範圍清單。使用 Google Cloud CLI 建立規則時,請使用 --src-ip-ranges 旗標定義基本比對條件。
  • 進階比對條件包含最多五個子運算式的運算式,可比對連入要求的各種屬性。使用 Google Cloud CLI 建立規則時,請使用 --expression 標記定義進階比對條件。

本頁面將說明進階比對條件,以及用於在安全性政策規則的進階比對條件中編寫運算式的 Cloud Armor 自訂規則語言。Cloud Armor 自訂規則語言是一般運算語言 (CEL) 的子集。以 Cloud Armor 自訂規則語言編寫的運算式需要兩個元件:

  • 屬性:要檢查的資料
  • 運算:如何使用資料

舉例來說,下列運算式會在 inIpRange() 運算中使用 origin.ip9.9.9.0/24 屬性。在本例中,如果 origin.ip 位於 9.9.9.0/24 IP 位址範圍內,運算式就會傳回 true。

inIpRange(origin.ip, '9.9.9.0/24')

即使上一個範例運算式只比對來源 IP 位址,在 Cloud Armor 安全性政策規則中使用該運算式時,從配額角度來看,該規則仍視為具有進階比對條件的規則。詳情請參閱「Cloud Armor 配額與限制」。

作業

以下參考資料說明可搭配屬性 (以 xyk 表示) 使用的運算子,用於定義規則運算式。

作業 運算式 說明
平等 x == y 如果 x 等於 y,則傳回 true。
相等、字串常值 x == "foo" 如果 x 等於指定的常數字串常值,則傳回 true。
Equality,原始字串常值 x == R"fo'o" 如果 x 等於指定的原始字串常值 (不會解讀逸出序列),則傳回 true。原始字串常值很適合用來表示本身必須使用逸出序列字元的字串。
邏輯 NOT !x 如果布林值 x 為 False,則傳回 True;如果布林值 x 為 True,則傳回 False。
不平等 x != y 如果 x 不等於 y,則傳回 true。
串連 x + y 傳回串連字串 xy
邏輯 AND x && y 如果 xy 均為 true,則傳回 true。
邏輯 OR x || y 如果 x 和/或 y 為 True,則傳回 True。
包含子字串 x.contains(y) 如果字串 x 包含子字串 y,則傳回 true。
以子字串開頭 x.startsWith(y) 如果字串 x 的開頭為子字串 y,則傳回 true。
結尾為子字串 x.endsWith(y) 如果字串 x 的結尾為子字串 y,則傳回 true。
規則運算式比對 x.matches(y) 如果字串 x 與指定的 RE2 模式 y 部分相符,則傳回 true。RE2 模式是以 RE2::Latin1 選項編譯,該選項會停用萬國碼 (Unicode) 功能。
範圍內的 IP 位址 inIpRange(x, y) 如果 IP 位址 x 位於 IP 範圍 y 內,則傳回 true。
小寫 x.lower() 傳回字串 x 的小寫值。
Uppercase x.upper() 傳回字串 x 的大寫值。
Base64 解碼值 x.base64Decode() 傳回 x 的 Base64 解碼值;系統會先將字元 _ - 分別替換為 / +。如果 x 不是有效的 Base64 值,則傳回 "" (空字串)。
機碼對應值 m['k'] 如果索引鍵 k 可用,則傳回字串對應 m 中索引鍵 k 的值;否則傳回錯誤。建議先使用 "has(m['k'])==true" 檢查是否有空位。
在地圖上查看鑰匙的可用性 has(m['k']) 如果索引鍵 k 可在對應 m 中使用,則傳回 true。
轉換為整數 int(x) x 的字串結果轉換為 int 型別。然後使用標準算術運算子 (例如 > 和 <=) 進行整數比較。這只適用於應為整數的值。
長度 size(x) 傳回字串 x 的長度。
解碼網址 x.urlDecode() 傳回 x 的網址解碼值;%## 格式的字元序列會替換為非 ASCII 等效字元,而 + 則會替換為空格。系統會原封不動地傳回無效的編碼。
解碼網址 (Unicode) x.urlDecodeUni() 傳回 x 的網址解碼值;除了 urlDecode() 之外,這也會處理 %u### 格式的 Unicode 字元序列。系統會原封不動地傳回無效的編碼。
將 UTF-8 轉換為 Unicode x.utf8ToUnicode() 傳回以 UTF-8 編碼的 x小寫 Unicode 表示法。

屬性

屬性代表來自傳入要求的資訊,例如來源 IP 位址或要求的網址路徑。

欄位 類型 欄位說明
origin.ip 字串 要求的來源 IP 位址。
origin.user_ip 字串 來源用戶端的 IP 位址,包含在上游 Proxy 的 HTTP-HEADER 中。使用這項屬性前,請先在安全性政策的 advancedOptionsConfig 欄位中設定 userIpRequestHeaders[] 選項,以符合 True-Client-IPX-Forwarded-ForX-Real-IP 等來源。

如未設定 userIpRequestHeaders[] 選項,如果設定的標頭含有無效的 IP 位址值,或設定的標頭不存在,origin.user_ip 預設為 origin.ip。詳情請參閱 securityPolicy 資源參考資料。

origin.tls_ja4_fingerprint 字串 JA4 TLS/SSL 指紋 如果用戶端使用 HTTPSHTTP/2HTTP/3 連線,如果無法取得,則會傳回空白字串。
origin.tls_ja3_fingerprint 字串 JA3 TLS/SSL 指紋 如果用戶端使用 HTTPSHTTP/2HTTP/3 連線,如果無法取得,則會傳回空白字串。
request.headers 地圖 HTTP 要求標頭的字串對字串對應。如果標頭含有多個值,這項對應中的值會是以半形逗號分隔的字串,當中包含標頭的所有值。這項對應中的鍵都是小寫。外部應用程式負載平衡器接受的所有標頭都會經過檢查,且適用相同的標頭限制

建議先使用 has() 檢查可用性,例如 has(request.headers['header-key']) && request.headers['header-key'] != 'header-value'

request.method 字串 HTTP 要求方法,例如 GETPOST
request.path 字串 要求的 HTTP 網址路徑。
request.scheme 字串 HTTP 網址通訊協定,例如 httphttps。 這個屬性的值一律為小寫
request.query 字串 HTTP 網址查詢,格式為 name1=value&name2=value2,如 HTTP 要求的第一行所示。未執行任何解碼作業。
origin.region_code 字串 與來源 IP 相關聯的 Unicode 國家/地區代碼,例如 US。如果您要建立使用 ISO 3166-1 alpha 2 國家/地區代碼的規則或運算式,Cloud Armor 會個別處理每個代碼。Cloud Armor 規則和運算式會明確使用這些區域代碼,允許或拒絕要求。
origin.asn 整數 與來源 IP 位址相關聯的自治系統編號 (ASN)。系統會根據支援含有原始 IP 位址的 IP 位址前置字元的網路業者,判斷全球唯一的 ASN。

運算式範例

對於每個運算式,系統採取的動作取決於運算式是否納入拒絕或允許規則。

根據 IPv4 或 IPv6 的 IP 位址範圍允許或拒絕存取

  • 下列運算式會比對來自 198.51.100.0/24 IP 位址範圍的要求:

    inIpRange(origin.ip, '198.51.100.0/24')
    
  • 下列運算式會比對來自 2001:db8::/32 IP 位址範圍的要求:

    inIpRange(origin.ip, '2001:db8::/32')
    

根據上游 Proxy 後方的自訂用戶端 IP 位址範圍,允許或拒絕存取要求

如果您已設定 origin.user_ip 運算子,可以根據 advancedOptionsConfig.userIpRequestHeaders[] 欄位中指定的標頭值進行比對。

  • 下列運算式會比對來自 192.0.2.0/24 IP 位址範圍的要求:

    inIpRange(origin.user_ip, '192.0.2.0/24')
    
  • 下列運算式會比對來自 2001:db8::/32 IP 位址範圍的要求:

    inIpRange(origin.user_ip, '2001:db8::/32')
    
  • 下列運算式會比對含有 80=BLAH 的 Cookie 要求:

    has(request.headers['cookie']) && request.headers['cookie'].contains('80=BLAH')
    

允許或拒絕含有非空白 referer 標頭的流量

  • 下列運算式會比對具有非空白 referer 標頭的要求:

    has(request.headers['referer']) && request.headers['referer'] != ""
    

根據標頭中的主機網址允許或拒絕流量

  • 下列運算式會比對特定網址的要求:

    request.headers['host'].lower().contains('test.example.com')
    

允許或拒絕來自特定區域的流量

如果您的網路應用程式無法在 AU 區域使用,則必須封鎖來自該區域的所有要求。

  • 在拒絕規則中,使用下列運算式比對來自 AU 區域的要求:

    origin.region_code == 'AU'
    

或者,如果您的網路應用程式適用於 AU 區域,則必須封鎖來自所有其他區域的要求。

  • 在拒絕規則中,請使用下列運算式,比對來自 AU 區域以外所有區域的要求:

    origin.region_code != 'AU'
    

區域代碼採用 ISO 3166-1 alpha 2 代碼。在某些情況下,區域會對應至國家/地區,但並非一律如此。舉例來說,US 代碼包含美國所有州、一個區和六個邊遠地區。

允許或拒絕來自特定 ASN 的流量

如果需要封鎖特定網路業者為客戶提供的網路應用程式,可以使用網路業者的 ASN 編號進行封鎖。

  • 在拒絕規則中,請使用下列運算式,比對來自特定 ASN 的要求:

    origin.asn == 123
    

或者,如果您的網路應用程式開放特定網路業者後方的客戶使用,則必須封鎖所有其他網路業者的要求。

  • 在拒絕規則中,請使用下列運算式,比對您想允許的網路業者以外的所有其他網路業者:

    origin.asn != 123
    

多個運算式

如要在單一規則中加入多項條件,請合併多個子運算式。

  • 在下列範例中,AU 區域中來自 1.2.3.0/24 的要求 (例如 Alpha 測試人員) 符合下列運算式:

    origin.region_code == "AU" && inIpRange(origin.ip, '1.2.3.0/24')
    
  • 下列運算式會比對來自 1.2.3.4 的要求,其中使用者代理程式包含字串 WordPress

    inIpRange(origin.ip, '1.2.3.4/32') &&
    has(request.headers['user-agent']) && request.headers['user-agent'].contains('WordPress')
    

允許或拒絕要求 URI 符合規則運算式的流量

  • 下列運算式會比對 URI 中含有 /example_path/ 字串的要求:

    request.path.matches('/example_path/')
    
  • 下列運算式會比對 User-Agent 標頭欄位中含有 Chrome 的要求:

    request.headers['user-agent'].matches('Chrome')
    
  • 下列運算式會對包含 wordpressUser-Agent 標頭進行不區分大小寫的比對;這會與 User-Agent:WordPress/605.1.15User-Agent:wordPress 和其他 wordpress 變體比對:

    request.headers['user-agent'].matches('(?i:wordpress)')
    

允許或拒絕含有特定 Base64 解碼值的流量

  • 下列運算式會比對 user-id 標頭的 base64 解碼值為 myValue 的要求:

    has(request.headers['user-id']) && request.headers['user-id'].base64Decode().contains('myValue')
    

允許或拒絕含有特定長度字串值的流量

  • 下列運算式會比對網址長度超過 10 個字元的要求:

    size(request.path) > 10
    
  • 下列運算式會比對標頭 x-data 長度大於或等於 1024 個字元的要求:

    size(request.headers['x-data']) >= 1024
    

允許或拒絕 HTTP 內文中含有零個 content-length 的流量

  • 下列運算式會比對 HTTP 內容中含有零 content-length 的要求:

    int(request.headers["content-length"]) == 0
    

允許或拒絕含有特定網址編碼值的流量

  • 下列運算式會比對含有 %3c 的 Cookie 值要求:

    has(request.headers['cookie']) && request.headers['cookie'].urlDecode().contains('<')
    

允許或拒絕含有特定網址編碼 Unicode 字串值的流量

  • 下列運算式會比對 Cookie 值等於 Match%2BValueMatch%u002BValue 的要求:

    has(request.headers['cookie']) && request.headers['cookie'].urlDecodeUni() == 'Match+Value'
    

允許或拒絕包含特定 Unicode 字串的 UTF-8 文字流量

  • 下列運算式會比對 Cookie 值等於 ¬ 的要求:

    has(request.headers['cookie']) && request.headers['cookie'].utf8ToUnicode() == '%u00ac'
    

根據已知的 JA4 指紋允許或拒絕流量

  • 下列運算式會比對 JA4 指紋等於 t13d1516h2_8daaf6152771_b186095e22b6 的要求:

    origin.tls_ja4_fingerprint == 't13d1516h2_8daaf6152771_b186095e22b6'
    

根據 JA4 指紋清單允許或拒絕流量

  • 下列運算式會比對 JA4 指紋,要求必須符合下列任一 JA4 指紋:

    • t00d0000h0_000000000000_000000000000
    • t13d1516h2_8daaf6152771_b186095e22b6
    origin.tls_ja4_fingerprint == 't00d0000h0_000000000000_000000000000' || origin.tls_ja4_fingerprint == 't13d1516h2_8daaf6152771_b186095e22b6'
    

預先設定的網路應用程式防火牆規則

預先設定的網路應用程式防火牆規則會使用預先設定的靜態簽章和/或規則運算式,比對 HTTP POST 主體、HTTP 要求標頭和查詢參數。可用的預先設定 WAF 規則是以 OWASP 核心規則集 3.3 版為準。Cloud Armor 提供多項預先定義的預先設定 WAF 規則。 如需預先設定的網路應用程式防火牆規則完整清單,請參閱「Cloud Armor 預先設定的網路應用程式防火牆規則總覽」。

如要列出所有可用的預先設定網路應用程式防火牆規則,請參閱「列出可用的預先設定網路應用程式防火牆規則」。

如要進一步瞭解預先設定的 WAF 規則,請參閱「使用預先設定的 WAF 規則防範應用程式層攻擊」一文。

預先設定的 WAF 規則名稱

預先設定的網路應用程式防火牆規則名稱格式為 <attack category>-<OWASP CRS version>-<version field>。攻擊類別會指定您要防範的攻擊類型,例如 xss (跨網站指令碼) 或 sqli (SQL 植入)。

支援的版本欄位為 stablecanary。規則的增修內容會先在 canary 版中發布,當新增內容和修改項目被視為安全且穩定時,就會升級至 stable 版本。

預先設定的 WAF 規則成員 ID

預先設定的網路應用程式防火牆規則包含多個運算式,每個運算式都有自己的簽章。 舉例來說,預先設定的網路應用程式防火牆規則 xss-v33-stable 包含名為 owasp-crs-v030301-id941100-xss 的運算式,對應於 3.3 版的規則 ID id941100。您可以使用簽章排除特定運算式,這在特定運算式持續觸發誤判時非常實用。詳情請參閱誤判疑難排解資訊。

如要瞭解核心規則集,以及如何調整不同敏感度層級,請參閱「調整 Google Cloud Armor 網路應用程式防火牆規則」。

預先設定的 WAF 規則的運算子

運算式 說明
evaluatePreconfiguredWaf(string, MAP<string, dyn>) 如果指定 WAF 規則集內的任一 WAF 簽章傳回 true,則傳回 true。第一個引數是 WAF 規則集的名稱,例如 xss-v33-stable。第二個引數 (選用) 是對應,其中鍵為字串,值則視鍵而定,屬於動態型別。這個引數的用途是微調要評估的 WAF 簽章。可接受的金鑰包括:
  • 「sensitivity」:對應至 OWASP 核心規則集偏執狂等級,共有 4 個等級,範圍從 1 到 4。值為整數,有效範圍為 0 到 4。請注意,與「opt_in_rule_ids」(稍後說明) 搭配使用時,0 會保留做為有效值。指定敏感度為 x (x >= 1) 時,系統會評估所有相關聯的 WAF 簽章,敏感度值介於 1 到 x。如果省略,系統會使用 4 做為靈敏度值。
  • 「opt_out_rule_ids」:要從評估作業中排除的 WAF 簽章 (以規則 ID 表示),其中基本集是由敏感度值決定。其值為字串清單。規則 ID 數量上限為 128 個。
  • 「opt_in_rule_ids」:要納入評估的 WAF 簽章 (以規則 ID 表示),其中基本集為空白。其值為字串清單。規則 ID 數量上限為 128 個。使用這項功能時,必須指定 0 的「敏感度」。

「opt_out_rule_ids」和「opt_in_rule_ids」鍵互斥,如要審查並手動選擇加入稍後新增至現有規則集的 WAF 簽章,可以選擇使用「opt_in_rule_ids」。

evaluatePreconfiguredExpr(string, LIST)

如果指定預先設定的網路應用程式防火牆規則中,有任何一個運算式傳回 true,則傳回 true。

第一個引數是預先設定的網路應用程式防火牆規則名稱,例如 xss-stable。第二個引數 (選用) 是以半形逗號分隔的 ID 字串清單,這些 ID 應從評估中排除。如果預先設定的網頁應用程式防火牆規則成員觸發偽陽性,排除清單就很有用。

預先設定的網路應用程式防火牆規則範例

  • 下列運算式使用 xss-v33-stable 預先設定的網路應用程式防火牆規則,防範跨網站指令碼攻擊:

    evaluatePreconfiguredWaf('xss-v33-stable')
    
  • 下列運算式會使用預先設定的網路應用程式防火牆規則中的所有運算式,但成員 ID 941100941110 除外:xss-v33-stable

    evaluatePreconfiguredWaf('xss-v33-stable', {'opt_out_rule_ids': ['owasp-crs-v030301-id941100-xss',
    'owasp-crs-v030301-id941110-xss']})
    
  • 下列運算式使用預先設定的網路應用程式防火牆規則,防範來自 198.51.100.0/24 IP 位址範圍的 SQL 注入攻擊:

    inIpRange(origin.ip, '198.51.100.0/24') && evaluatePreconfiguredWaf('sqli-v33-stable')
    

後續步驟