設定自訂規則語言屬性

每個 Google Cloud Armor 安全性政策規則都有優先順序、比對條件和動作。Google Cloud Armor 會執行與要求相符的最高優先順序規則所指定的動作。優先順序低於最高匹配規則的規則不會評估,即使兩者具有相同的匹配條件也一樣。

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

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

本頁面將說明進階比對條件,以及 Google Cloud Armor 自訂規則語言,您可使用這兩者在安全性政策規則的進階比對條件中編寫運算式。Google Cloud Armor 自訂規則語言是一般運算語言 (CEL) 的子集。使用 Google 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 位址,但如果您在 Google Cloud Armor 安全性政策規則中使用上述範例運算式,從配額角度來看,系統會將該規則視為具有進階比對條件的規則。詳情請參閱 Google Cloud Armor 配額與限制

作業

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

作業 運算式 說明
平等 x == y 如果 x 等於 y,則傳回 true。
相等性,字串常值 x == "foo" 如果 x 等於指定的常數字串文字,則傳回 true。
相等性,原始字串常值 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 如果 xy 或兩者皆為 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 中,則傳回「是」。
小寫 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 中,則傳回「是」。
轉換為整數 int(x) x 的字串結果轉換為 int 類型。接著,您可以使用標準算術運算子 (例如 > 和 <=) 進行整數比較。這項功能僅適用於應為整數的值。
長度 size(x) 傳回字串 x 的長度。
解碼網址 x.urlDecode() 傳回 x 的網址解碼值;%## 格式的字元序列會替換為非 ASCII 等價字元,而 + 會替換為空格。系統會原封不動地傳回無效的編碼。
解碼網址 (Unicode) x.urlDecodeUni() 傳回 x 的已解碼網址值;除了 urlDecode(),這也處理 %u### 格式的 Unicode 字元序列。系統會原封不動地傳回無效的編碼。
將 utf8 轉換為 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_ja3_fingerprint 字串 如果用戶端使用 HTTPSHTTP/2HTTP/3 進行連線,則會產生 JA3 TLS/SSL 指紋。如果沒有,則會傳回空白字串。
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 國家/地區代碼,Google Cloud Armor 會個別處理每個代碼。Google Cloud Armor 規則和運算式會明確使用這些區域代碼來允許或拒絕要求。
origin.asn 整數 與來源 IP 位址相關聯的自治系統編號 (ASN)。系統會根據支援含有來源 IP 位址的 IP 位址前置字元的網路業者,決定全球唯一的 ASN。

reCAPTCHA 屬性

本節列出僅適用於 reCAPTCHA 符記或豁免 cookie 的屬性。如果要評估的 reCAPTCHA 權杖或豁免 cookie 因下列任一原因而無法使用或無效,則以這些屬性為基礎的子運算式會傳回 false

  • 權杖格式錯誤,無法解碼。
  • 權杖包含無效的屬性。例如,權杖是使用與規則相關聯的 reCAPTCHA 金鑰以外的 reCAPTCHA 金鑰產生。
  • 權杖已過期。
欄位 類型 欄位說明
token.recaptcha_exemption.valid bool 存在有效的 reCAPTCHA 豁免 Cookie。

動作符記屬性

欄位 類型 欄位說明
token.recaptcha_action.score float reCAPTCHA 動作權杖的分數。有效分數的範圍為 0.01.0,其中 0.0 很可能是不正當使用者,而 1.0 則很可能是合法使用者。
token.recaptcha_action.captcha_status string reCAPTCHA 動作權杖的驗證碼狀態。有效狀態為 NONEPASSFAIL,其中 NONE 是指 reCAPTCHA 評估期間沒有挑戰,因此動作符記中沒有人機驗證欄位。
token.recaptcha_action.action string reCAPTCHA 動作符記中的動作名稱 (最多 100 個半形字元)。 請參閱「動作名稱」。
token.recaptcha_action.valid bool 存在有效的 reCAPTCHA 動作符記。

工作階段符記屬性

欄位 類型 欄位說明
token.recaptcha_session.score float reCAPTCHA 工作階段符記的分數。有效分數的範圍為 0.01.0,其中 0.0 很可能是不正當使用者,而 1.0 則很可能是合法使用者。
token.recaptcha_session.valid bool 存在有效的 reCAPTCHA 工作階段符記。

運算式範例

針對每個運算式,採取的動作取決於運算式是否包含在拒絕規則或允許規則中。

根據 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'
    

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

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

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

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

  • 以下運算式會比對 JA3 指紋等於 e7d705a3286e19ea42f587b344ee6865 的要求:

    origin.tls_ja3_fingerprint == 'e7d705a3286e19ea42f587b344ee6865'
    

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

  • 以下運算式會比對 JA3 指紋等於下列任一 JA3 指紋的要求:

    • e7d705a3286e19ea42f587b344ee6865
    • f8a5929f8949e846267b582072e35f84
    • 8f8b62163873a62234c14f15e7b88340
    origin.tls_ja3_fingerprint == 'e7d705a3286e19ea42f587b344ee6865' || origin.tls_ja3_fingerprint == 'f8a5929f8949e846267b582072e35f84' || origin.tls_ja3_fingerprint == '8f8b62163873a62234c14f15e7b88340'
    

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

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

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

如要進一步瞭解預先設定的 WAF 規則,請參閱用途說明「使用預先設定的 WAF 規則,減輕應用程式層攻擊」。

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

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

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

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

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

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

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

運算式 說明
evaluatePreconfiguredWaf(string, MAP<string, dyn>) 如果指定的 WAF 規則集合中任一 WAF 簽章傳回值為 true,則傳回值為 true。第一個引數是 WAF 規則集的名稱,例如 xss-v33-stable。第二個引數 (選用) 是地圖,其中鍵為字串,而值則會根據鍵動態指定類型。這個引數的目的,是為了微調要評估哪些 WAF 簽章。可接受的鍵包括:
  • 「sensitivity」:這是 OWASP 核心規則集的偏執程度,共有 4 個等級,從 1 到 4。其值為整數,有效範圍為 0 到 4。請注意,當 0 與「opt_in_rule_ids」搭配使用時,系統會將其保留為有效值 (稍後說明)。指定 x (x >= 1) 的敏感度時,系統會評估所有敏感度值介於 1 到 x 之間的相關 WAF 簽章。如果省略,系統會使用 4 做為敏感度值。
  • 「opt_out_rule_ids」:要從評估中排除的 WAF 簽章 (以規則 ID 表示),其中基本組合是由敏感度值決定。其值為字串清單。允許的規則 ID 數量上限為 128
  • 「opt_in_rule_ids」:要納入評估的 WAF 簽章 (以規則 ID 表示),其中基礎集合為空白。其值為字串清單。允許的規則 ID 數量上限為 128。使用此方法時,必須指定 0 的「sensitivity」。

「opt_out_rule_ids」和「opt_in_rule_ids」鍵互斥,如果您想查看並手動啟用日後新增至現有規則集的 WAF 簽章,可以選擇使用「opt_in_rule_ids」。

evaluatePreconfiguredExpr(string, LIST)

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

第一個引數是預先設定的網路應用程式防火牆規則名稱,例如 xss-stable。第二個引數 (選用) 是逗號分隔的字串清單,其中列出應從評估中排除的 ID。當預先設定的網頁應用程式防火牆規則的特定成員觸發偽陽性時,排除清單就會派上用場。

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

  • 以下運算式會使用 xss-v33-stable 預先設定的網路應用程式防火牆規則,減輕 XSS 攻擊:

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

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

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

後續步驟