コンテンツにスキップ

HTTPリクエストがCloudflareのグローバルネットワークに到達すると、Cloudflareは式と照合するためのフィールド–値ペアのテーブルを作成します。このテーブルは、現在のリクエストが処理されている間存在します。

ルール言語のルックアップテーブルを構成する値は、さまざまなソースから取得されます:

  • プリミティブプロパティはリクエストから直接取得されます(例えば、http.request.uri.path)。
  • 派生値は変換、合成、または基本的な操作の結果です。例えば、変換lower(http.request.uri.path)は、http.request.uri.pathの値を小文字に変換します。
  • 計算値はルックアップ、計算、またはその他のインテリジェンスの結果です。例えば、Cloudflareは機械学習プロセスを使用して脅威スコアを動的に計算し、cf.threat_scoreフィールドで表現します。

これらの値に加えて、式にはリテラル値も含まれる場合があります。これらは静的で既知の値であり、変換の有無にかかわらず、リクエスト/レスポンスフィールドの値と比較するために式に組み込まれます。

ルール式で値を扱う際は、以下のセクションの情報を考慮してください。

文字列値と正規表現

文字列は特定の区切り文字で囲まれたバイトのシーケンスです。

Cloudflareのルールは、リテラル文字列を指定するための2つの形式をサポートしています:引用リテラル文字列生文字列。これらの形式は異なる区切り文字とエスケープメカニズムを持っています。

式で正規表現を指定するために2つの文字列形式のいずれかを使用できますが、Cloudflareは生文字列構文の使用を推奨します。引用文字列構文は複雑なエスケープルールがあり、十分にテストされていない場合に予期しない動作を引き起こす可能性があります。

正規表現の照合は、Rustの正規表現エンジンを使用して行われます。

引用文字列構文

引用文字列構文を使用する場合、文字列リテラルは"(ダブルクォート)文字で区切られます。この形式では、特殊文字"\をそれぞれ\"\\を使用してエスケープする必要があります。

引用文字列構文には以下の追加のエスケープ要件があります:

  • regex operatormatchesまたは~)の右側で正規表現を指定するために使用される場合、文字列は正規表現エスケープルールを使用して解析されます。
  • 他の演算子の右側で使用される場合、または関数パラメータで使用される場合、文字列は基本的なエスケープルールを使用して解析されます。
# URIパスに'a"b'が含まれているかテスト
http.request.uri.path matches "a\"b"
# URIパスに'a"#b'が含まれているかテスト
http.request.uri.path matches "a\"#b"
# 'a'を'\'(バックスラッシュ)に置き換え
regex_replace(http.host, "a", "\\")

生文字列構文

生文字列構文を使用して文字列(または正規表現)を指定するには、特別な区切り文字を使用します:

  • 初期区切り文字は、r文字で構成され、オプションで1つ以上の#文字(最大255)に続き、"(ダブルクォート)文字が続きます。
  • 終了区切り文字は、"(ダブルクォート)文字に続き、初期区切り文字と同じ数の#文字が続きます(0から255の範囲)。

生文字列には特殊文字はなく、終了区切り文字までのすべての文字はそのまま解釈されます(エスケープシーケンスはありません)。

引用文字列構文とは異なり、生文字列構文は使用されるコンテキストに関係なく常に同じです(例えば、regex operatorを持つ正規表現として、または関数呼び出しのパラメータとして)。

# URIパスに'a"b'が含まれているかテスト
http.request.uri.path matches r#"a"b"#
# URIパスに'a"#b'が含まれているかテスト
http.request.uri.path matches r##"a"#b"##
# '\'(バックスラッシュ)を'a'に置き換え
# 次の生文字列では、正規表現で特別な意味を持つため、'\'文字をエスケープする必要があります
regex_replace(http.host, r"\\", "a")
# URIパスが'/api/login.aspx'で終わるかテスト
# 次の生文字列では、正規表現で特別な意味を持つため、'.'文字をエスケープする必要があります("任意の文字")
http.request.uri.path matches r"/api/login\.aspx$"

大文字小文字の区別と値の正規表現

式内の文字列リテラル値の評価は大文字小文字を区別するため、バリエーションをキャプチャするために複数の単純な式を書くことを検討してください。

Cloudflareのビジネスおよびエンタープライズ顧客プランでは、正規表現をサポートするmatches 比較演算子にアクセスできるため、単一の式で値の複数のバリエーションをキャプチャできます。

ブール値

ブールフィールドを使用した単純な式には、演算子の表記や値は必要ありません。以下のsslの例のように、フィールドを単独で挿入するだけで済みます。

ssl

この単純な式は、sslフィールドの値がtrueであるリクエストに一致します。

sslfalseであるリクエストに一致させるには、ブールnot演算子を使用します:

not ssl

配列

Cloudflareのルール言語には、Array型のフィールドArray引数および戻り値を持つ関数が含まれています。

個々の配列要素には、角括弧([])の間にインデックス(非負の値)を使用してアクセスできます。配列のインデックスは0(ゼロ)から始まります。

式を指定する際に、各配列要素に対して評価されることになる場合は、特別な表記[*]を使用します(例えば、map高階関数)のように)。この特別なインデックス表記は、配列を展開し、すべての要素に対して囲む関数を個別に呼び出し、すべての個別の戻り値を含む新しい配列を返します。

以下の例では、Array<String>型のhttp.request.headers.namesフィールドを考慮します:

  • 配列の最初の要素を取得する:
    http.request.headers.names[0]

  • 最初の配列要素がContent-Typeと等しいか確認する(大文字小文字を区別):
    http.request.headers.names[0] == "Content-Type"

  • いずれかの配列要素がContent-Typeと等しいか確認する(大文字小文字を区別):
    any(http.request.headers.names[*] == "Content-Type")

  • いずれかの配列要素がContent-Typeと等しいか確認する(大文字小文字を無視):
    any(lower(http.request.headers.names[*])[*] == "content-type")

最後の例では、lower()関数に[*]表記が含まれているため、関数は各配列要素に対して評価されます。この関数は、[*]と共に使用されると、入力配列の各要素を小文字に変換した新しい配列を返します。次に、文字列比較は、lower()を各ヘッダー名に適用した結果の配列をブール値の配列に変換するために[*]を使用します。最後に、any()は、これらの配列要素のうち少なくとも1つが真であれば真と評価されます。

注意事項

自分自身の配列を定義することはできません。フィールドから返された配列のみを使用できます。

Accessing 範囲外の配列インデックス produces a “missing value”. A missing value has the following behavior:

  • Any comparison <expr> <op> <literal> where <expr> evaluates to a missing value will evaluate to false.
  • Function calls like function(<expr>), where <expr> evaluates to a missing value, will return a missing value in most cases, but the exact behavior can vary per function.

同じ式内で[*]を複数回使用できるのは、同じ配列に適用される場合のみです。また、関数呼び出しの最初の引数でのみ[*]を使用できます。

ルール言語の演算子は、配列や[*]演算子を直接サポートしていませんが、インデックス付き配列要素(例えば、array_value[0])はサポートしています。例えば、囲む関数呼び出しのコンテキスト外で==演算子と[*]を使用することはできません:

  • http.request.headers.names[*] == "Content-Type"無効な式
  • any(http.request.headers.names[*] == "Content-Type")有効な式

マップ

マップ(連想配列とも呼ばれる)は、キーと値のペアのコレクションを格納するデータ構造であり、キーはStringでなければならず、値は任意の型(例えば、Stringや値の配列)であることができます。マップ内のすべての値は同じ型でなければなりません。

Cloudflareのルール言語には、Mapデータ型のいくつかのフィールドが含まれています。マップフィールドの型表記(例えば、Map<Array<String>>)は、キーに関連付けられた値のデータ型を示します(String要素のArray)。これは、キー"foo"の値にアクセスすると、String要素の配列または欠損値のいずれかが得られることを意味します。

マップ内の値にアクセスするには、キーを角括弧([])の間に入力します:

<MAP_FIELD>[<KEY>]

値がArray型のマップの場合、取得した(配列)値に対して演算子を直接使用することはできません。配列の項目に演算子を使用するには、式を指定する際に特別な表記[*]を使用します。この特別なインデックス表記は、配列を展開し、すべての要素に対して囲む関数を個別に呼び出し、すべての個別の戻り値を含む新しい配列を返します。

以下の例は、データ型がMap<Array<String>>http.request.headersフィールドに基づいています。配列要素はStringデータ型です。

受信したHTTPリクエストにAccept: application/jsonというHTTPヘッダーが含まれている場合、次の式は示された値に評価されます:

http.request.headers["accept"] # ==> ["application/json"]
http.request.headers["accept"][0] # ==> "application/json"
any(http.request.headers["accept"][*] == "application/json") # ==> true
any(http.request.headers["accept"][*] == "text/plain") # ==> false

次の例は、データ型がMap<Array<String>>http.request.uri.argsフィールドに基づいています。配列要素はStringデータ型です。

HTTPリクエストにfilterというURI引数が3つ(wafbotmcdn)含まれている場合、次の式は示された値に評価されます:

# 例のリクエストURL:
# https://example.com/?filter=waf&filter=botm&filter=cdn
http.request.uri.args["filter"] # ==> ["waf", "botm", "cdn"]
len(http.request.uri.args["filter"][1]) # ==> 4
# すべての'filter'値の長さが常に3または4であるか確認
all(len(http.request.uri.args["filter"][*])[*] in {3 4}) # ==> true
# 'filter'値の長さ(もしあれば)が決して3または4でないか確認
all(not len(http.request.uri.args["filter"][*])[*] in {3 4}) # ==> false
# http.request.uri.argsマップに"filter"キーが含まれているか確認
len(http.request.uri.args["filter"]) >= 0 # ==> true
# http.request.uri.argsマップに"order"キーが含まれていないか確認
not len(http.request.uri.args["order"]) >= 0 # ==> true

any()all()len()、およびその他の利用可能な関数に関する詳細は、関数を参照してください。

注意事項

自分自身のマップを定義することはできません。フィールドから返されたマップのみを使用できます。

Accessing マップ内の存在しないキー produces a “missing value”. A missing value has the following behavior:

  • Any comparison <expr> <op> <literal> where <expr> evaluates to a missing value will evaluate to false.
  • Function calls like function(<expr>), where <expr> evaluates to a missing value, will return a missing value in most cases, but the exact behavior can vary per function.

リスト

リストを使用すると、アイテムのグループを作成し、それらを名前でまとめて参照できます。各リスト型は特定のデータ型のアイテムをサポートします。リスト内のすべてのアイテムは同じデータ型でなければなりません。利用可能なリスト型の詳細については、リストを参照してください。

ルール式でリストを参照するには、$<list_name>を使用し、in 演算子を指定します。リスト内の値のうち、1つだけが式の左側(in演算子の前)と一致すれば、単純な式はtrueと評価されます。一致するものがない場合、式はfalseと評価されます。

以下の例式は、office_networkという名前のIPリストに含まれるIPアドレスからのリクエストをフィルタリングします:

(ip.src in $office_network)

リスト名には小文字のアルファベット、数字、アンダースコア(_)文字のみを含めることができます。リストの作成と管理に関するガイダンスについては、リストを参照してください。

インラインリスト

インラインリストを使用すると、in演算子を使用する単純な式に値のリストを直接含めることができます。

インラインリストの要素は、文字列、整数、またはIPアドレス/範囲であることができます。インラインリストのすべての要素は同じデータ型でなければならず、リテラル値である必要があります。インラインリストの要素を指定するには、個別に入力し、要素をスペースで区切ります。インラインリストには重複する値を含めることができます。

さらに、一部のデータ型では範囲を要素として使用できます:

  • 整数値の場合、範囲は<start_value>..<end_value>の形式で入力します。インラインリストには整数範囲と整数値の両方を含めることができます。

  • IPアドレスの場合、次のように入力できます:

    • <start_address>..<end_address>の形式で明示的なIP範囲(例:198.51.100.3..198.51.100.7)。
    • CIDR範囲(例:192.0.2.0/24または2001:0db8::/32)。

    インラインリストには明示的なIP範囲、CIDR範囲、および個々のIPアドレスを含めることができます。

Examples
http.host in {"example.com" "example.net"}
ip.src in {198.51.100.1 198.51.100.3..198.51.100.7 192.0.2.0/24 2001:0db8::/32}
tcp.dstport in {8000..8009 8080..8089}