コンテンツにスキップ

関数

Cloudflareのルール言語は、式内の値を操作および検証するための関数を提供します。

  • 変換関数は、HTTPリクエストから抽出された値を操作します。
  • HMAC検証関数は、HMACトークンの有効性をテストします。有効なHMACトークンの存在に基づいてリクエストをターゲットにする式を書くために使用します。

変換関数

ルール言語は、HTTPリクエストから抽出された値を変換するいくつかの関数をサポートしています。変換関数の一般的な使用例は、文字列を大文字または小文字に変換することです。デフォルトでは、文字列の評価は大文字と小文字を区別します。

例えば、lower()関数は、文字列内のすべての大文字を小文字に変換します。

以下の式では、lower()関数がhttp.hostの値を小文字に変換し、ターゲット値"www.cloudflare.com"と一致させます:

lower(http.host) == "www.cloudflare.com"

配列を引数として取らない変換関数は、[*]インデックス表記を必要とします。詳細については、配列を参照してください。

ルール言語は、以下の変換関数をサポートしています:

any

any(Array<Boolean>)Boolean

引数の配列内の_任意_の値に対して比較演算子がtrueを返す場合、trueを返します。それ以外の場合はfalseを返します。

例:

any(url_decode(http.request.body.form.values[*])[*] contains "an xss attack")

all

all(Array<Boolean>)Boolean

引数の配列内の_すべて_の値に対して比較演算子がtrueを返す場合、trueを返します。それ以外の場合はfalseを返します。

例:

all(http.request.headers["content-type"][*] == "application/json")

cidr

cidr(address (IP address), ipv4_network_bits (Integer), ipv6_network_bits (Integer))IP address

提供されたIPv4およびIPv6ネットワークビットに基づいて、IPアドレス(IPv4またはIPv6)に対応するネットワークアドレスを返します(これにより、対応するネットマスクが決まります)。

addressパラメータはフィールドでなければならず、リテラル文字列であってはなりません。

ipv4_network_bitsの値は1から32の間で、ipv6_network_bitsの値は1から128の間でなければなりません。

例:

  • ip.src113.10.0.2の場合、cidr(ip.src, 24, 24)113.10.0.0を返します。
  • ip.src2001:0000:130F:0000:0000:09C0:876A:130Bの場合、cidr(ip.src, 24, 24)2001:0000:0000:0000:0000:0000:0000:0000を返します。

cidr6

cidr6(address (IP address), ipv6_network_bits (Integer))IP address

提供されたネットワークビットに基づいて、IPv6アドレスに対応するIPv6ネットワークアドレスを返します。最初のパラメータにIPv4アドレスを提供した場合、それは変更されずに返されます。

addressパラメータはフィールドでなければならず、リテラル文字列であってはなりません。

ipv6_network_bitsの値は1から128の間でなければなりません。

この関数は次のように等価です:cidr(<address>, 32, <ipv6_network_bits>)

例:

  • ip.src2001:0000:130F:0000:0000:09C0:876A:130Bの場合、cidr6(ip.src, 24)2001:0000:0000:0000:0000:0000:0000:0000を返します。
  • ip.src113.10.0.2の場合、cidr6(ip.src, 24)113.10.0.2(変更なし)を返します。

concat

concat(String | Integer | Bytes | Array elements)String

カンマ区切りの値のリストを取ります。引数の値を単一の文字列に連結します。

例えば、concat("String1", " ", "String", 2)"String1 String2"を返します。

decode_base64

decode_base64(source (String))String

sourceで指定されたBase64エンコードされた文字列をデコードします。

sourceはフィールドでなければならず、リテラル文字列であってはなりません。

例えば、次のHTTPリクエストヘッダーがある場合:client_id: MTIzYWJj(any(decode_base64(http.request.headers["client_id"][*])[*] eq "123abc"))trueを返します。

ends_with

ends_with(source (String), substring (String))Boolean

ソースが指定された部分文字列で終わる場合、trueを返します。それ以外の場合はfalseを返します。ソースはリテラル値(例えば"foo")であってはなりません。

例えば、http.request.uri.path"/welcome.html"の場合、ends_with(http.request.uri.path, ".html")trueを返します。

len

len(String | Bytes)Integer

文字列またはバイトフィールドのバイト長を返します。

例えば、http.host"example.com"の場合、len(http.host)11を返します。

lookup_json_integer

lookup_json_integer(field (String), key (String | Integer) [, key (String | Integer), ...])Integer

指定されたkeyに関連付けられた整数値をfieldから返します。

fieldは有効なJSONドキュメントの文字列表現でなければなりません。

keyは属性名、JSON配列内のゼロベースの位置番号、またはこれらの2つのオプションの組み合わせ(追加の関数パラメータとして)であり、特定の整数値を取得するためにJSONドキュメントの階層に従う必要があります。

注意:この関数は、単純な整数にのみ機能します。例えば、42.0のような小数点以下がゼロの浮動小数点数には機能しません。

例:

  • 次のJSONオブジェクトがhttp.request.body.rawフィールドに含まれている場合:
    { "record_id": "aed53a", "version": 2 }
    その場合、lookup_json_integer(http.request.body.raw, "version")2を返します。

  • 次のネストされたオブジェクトがある場合:
    { "product": { "id": 356 } }
    その場合、lookup_json_integer(http.request.body.raw, "product", "id")356を返します。

  • 次のJSON配列がルートレベルにある場合:
    ["first_item", -234]
    その場合、lookup_json_integer(http.request.body.raw, 1)-234を返します。

  • 次のJSONオブジェクト属性内の配列がある場合:
    { "network_ids": [123, 456] }
    その場合、lookup_json_integer(http.request.body.raw, "network_ids", 0)123を返します。

  • 次のJSONオブジェクトのルートレベル配列がある場合:
    [{ "product_id": 123 }, { "product_id": 456 }]
    その場合、lookup_json_integer(http.request.body.raw, 1, "product_id")456を返します。

lookup_json_string

lookup_json_string(field (String), key (String | Integer) [, key (String | Integer), ...])String

指定されたkeyに関連付けられた文字列値をfieldから返します。

fieldは有効なJSONドキュメントの文字列表現でなければなりません。

keyは属性名、JSON配列内のゼロベースの位置番号、またはこれらの2つのオプションの組み合わせ(追加の関数パラメータとして)であり、特定の値を取得するためにJSONドキュメントの階層に従う必要があります。

例:

  • 次のJSONオブジェクトがhttp.request.body.rawフィールドに含まれている場合:
    { "company": "cloudflare", "product": "rulesets" }
    その場合、lookup_json_string(http.request.body.raw, "company") == "cloudflare"trueを返します。

  • 次のネストされたオブジェクトがある場合:
    { "network": { "name": "cloudflare" } }
    その場合、lookup_json_string(http.request.body.raw, "network", "name") == "cloudflare"trueを返します。

  • 次のJSON配列がルートレベルにある場合:
    ["other_company", "cloudflare"]
    その場合、lookup_json_string(http.request.body.raw, 1) == "cloudflare"trueを返します。

  • 次のJSONオブジェクト属性内の配列がある場合:
    { "networks": ["other_company", "cloudflare"] }
    その場合、lookup_json_string(http.request.body.raw, "networks", 1) == "cloudflare"trueを返します。

  • 次のJSONオブジェクトのルートレベル配列がある場合:
    [{ "network": "other_company" }, { "network": "cloudflare" }]
    その場合、lookup_json_string(http.request.body.raw, 1, "network") == "cloudflare"trueを返します。

lower

lower(String)String

文字列フィールドを小文字に変換します。大文字のASCIIバイトのみが変換され、他のバイトは影響を受けません。

例えば、http.host"WWW.cloudflare.com"の場合、lower(http.host) == "www.cloudflare.com"trueを返します。

regex_replace

regex_replace(source (String), regular_expression (String), replacement (String))String

正規表現に一致するソース文字列の一部を置換文字列で置き換え、結果を返します。置換文字列には、正規表現のキャプチャグループへの参照(例えば、${1}${2})を含めることができます。最大8つの置換参照が可能です。

例:

  • リテラルマッチ置換:
    regex_replace("/foo/bar", "/bar$", "/baz") == "/foo/baz"

  • 一致しない場合、入力文字列は変更されません:
    regex_replace("/x", "^/y$", "/mumble") == "/x"

  • 一致はデフォルトで大文字と小文字を区別します:
    regex_replace("/foo", "^/FOO$", "/x") == "/foo"

  • 一致が複数ある場合、最初の1つだけが置換されます:
    regex_replace("/a/a", "/a", "/b") == "/b/a"

  • 置換文字列内の$をエスケープするには、別の$でプレフィックスを付けます:
    regex_replace("/b", "^/b$", "/b$$") == "/b$"

  • キャプチャグループを使用して置換:
    regex_replace("/foo/a/path", "^/foo/([^/]*)/(.*)$", "/bar/${2}/${1}") == "/bar/path/a/"

キャプチャグループを作成するには、正規表現の一部を括弧で囲みます。次に、置換文字列内で${<NUMBER>}を使用してキャプチャグループを参照します。<NUMBER>はキャプチャグループの番号です。

remove_bytes

remove_bytes(Bytes)Bytes

指定されたバイトのすべての出現を削除した新しいバイト配列を返します。

例えば、http.host"www.cloudflare.com"の場合、remove_bytes(http.host, "\x2e\x77")"cloudflarecom"を返します。

starts_with

starts_with(source (String), substring (String))Boolean

ソースが指定された部分文字列で始まる場合、trueを返します。それ以外の場合はfalseを返します。ソースはリテラル値(例えば"foo")であってはなりません。

例えば、http.request.uri.path"/blog/first-post"の場合、starts_with(http.request.uri.path, "/blog")trueを返します。

substring

substring(field (String | Bytes), start (Integer) [, end (Integer)])String

fieldの値(文字列またはバイトのフィールドの値)から、startバイトインデックスから(ただしendバイトインデックスを除く)までの部分を返します。field内の最初のバイトのインデックスは0です。オプションのendインデックスを提供しない場合、関数はstartインデックスから文字列の最後までの部分を返します。

startおよびendインデックスは負の整数値を取ることができ、これにより文字列の先頭ではなく末尾から文字をアクセスできます。

例:

// http.request.body.rawが"asdfghjk"の場合:
substring(http.request.body.raw, 2, 5) は"dfg"を返します。
substring(http.request.body.raw, 2) は"dfghjk"を返します。
substring(http.request.body.raw, -2) は"jk"を返します。
substring(http.request.body.raw, 0, -2) は"asdfgh"を返します。

to_string

to_string(Integer | Boolean | IP address)String

整数、ブール値、またはIPアドレス値の文字列表現を返します。

例:

// cf.bot_management.scoreが5の場合:
to_string(cf.bot_management.score) は"5"を返します。
// sslがtrueの場合:
to_string(ssl) は"true"を返します。

upper

upper(String)String

文字列フィールドを大文字に変換します。小文字のASCIIバイトのみが変換され、他のバイトは影響を受けません。

例えば、http.host"www.cloudflare.com"の場合、upper(http.host)"WWW.CLOUDFLARE.COM"を返します。

url_decode

url_decode(source (String)[, options (String)])String

sourceで定義されたURL形式の文字列をデコードします。以下のように:

  • %20および+はスペース文字( )にデコードされます。

  • %E4%BDä½にデコードされます。

sourceはフィールドでなければならず、リテラル文字列であってはなりません。

options パラメータはオプションです。オプションは、"r""ur" のように、引用符で囲まれた単一の文字列として提供する必要があります。利用可能なオプションは以下の通りです:

  • r: 再帰的デコードを適用します。例えば、%2520 は2回(再帰的に)デコードされてスペース文字( )になります。
  • u: Unicodeパーセントデコードを有効にします。結果はUTF-8でエンコードされます。例えば、"%u2601" はUTF-8でエンコードされた雲の絵文字(☁️)にデコードされます("\xe2\x98\x81"、サイズは3バイト)。

例:

url_decode("John%20Doe") は "John Doe" を返します
url_decode("John+Doe") は "John Doe" を返します
url_decode("%2520") は "%20" を返します
url_decode("%2520", "r") は " " を返します
// any() 関数と共に url_decode() を使用する場合:
any(url_decode(http.request.body.form.values[*])[*] contains "an xss attack")

uuidv4

uuidv4(Bytes)String

指定された引数(ランダムのソース)に基づいてランダムなUUIDv4(ユニバーサルユニーク識別子、バージョン4)を生成します。ランダムなバイトの配列を取得するには、cf.random_seed フィールドを使用します。

例えば、uuidv4(cf.random_seed)49887398-6bcf-485f-8899-f15dbef4d1d5 に似たUUIDv4を返します。

wildcard_replace

wildcard_replace(source (Bytes), wildcard_pattern (Bytes), replacement (Bytes) [, flags (Bytes)])String

リテラルでゼロまたはそれ以上の * ワイルドカードメタキャラクタに一致する source 文字列を置き換え文字列で置き換え、結果を返します。置き換え文字列には、ワイルドカードキャプチャグループへの参照(例えば、${1}${2})を含めることができ、最大8つの置き換え参照が可能です。

一致がない場合、関数は source を変更せずに返します。

source パラメータはフィールドでなければなりません(リテラル文字列ではいけません)。さらに、source の全体の値は wildcard_pattern パラメータと一致しなければなりません(フィールド値の一部だけと一致してはいけません)。

wildcard_pattern パラメータにリテラル * 文字を入力するには、\* を使用してエスケープする必要があります。さらに、\\\ を使用してエスケープする必要があります。このパラメータ内で連続する2つのエスケープされていない * 文字(**)は無効と見なされ、使用できません。文字のエスケープを行う必要がある場合は、wildcard_pattern パラメータに対して 生文字列構文 を使用することをお勧めします。

replacement パラメータにリテラル $ 文字を入力するには、$$ を使用してエスケープする必要があります。

大文字と小文字を区別したワイルドカード一致を行うには、flags パラメータを "s" に設定します。

この関数は遅延一致を使用しており、各 * メタキャラクタを最短の文字列で一致させようとします。

例:

  • フルURIが https://apps.example.com/calendar/admin?expand=true の場合、
    wildcard_replace(http.request.full_uri, "https://*.example.com/*/*", "https://example.com/${1}/${2}/${3}")https://example.com/apps/calendar/admin?expand=true を返します。

  • フルURIが https://example.com/applications/app1 の場合、
    wildcard_replace(http.request.full_uri, "/applications/*", "/apps/${1}")https://example.com/applications/app1 を返します(一致がないため変更されていない値;URIパスの一致には http.request.uri.path フィールドを使用する必要があります)。

  • URIパスが /calendar の場合、
    wildcard_replace(http.request.uri.path, "/*", "/apps/${1}")/apps/calendar を返します。

  • URIパスが /Apps/calendar の場合、
    wildcard_replace(http.request.uri.path, "/apps/*", "/${1}")/calendar を返します(デフォルトでは大文字と小文字を区別しない一致)。

  • URIパスが /Apps/calendar の場合、
    wildcard_replace(http.request.uri.path, "/apps/*", "/${1}", "s")/Apps/calendar を返します(変更されていない値); 一致が大文字と小文字を区別するため、一致がありません。

  • URIパスが /apps/calendar/login の場合、
    wildcard_replace(http.request.uri.path, "/apps/*/login", "/${1}/login")/calendar/login を返します。

ワイルドカード一致のさらなる例については、ワイルドカード一致を参照してください。

マジックファイアウォール関数

bit_slice

bit_slice(protocol (String), offset_start (Number), offset_end (Number))Number

この関数は、指定されたビットスライスで一致を探します。

オフセットは指定されたプロトコルヘッダーから始まります。例えば、UDPパケットのペイロードの最初のビットに一致させるには、offset_start64 に設定する必要があります。

これは主に ipudp、および tcp での使用を意図しています。

スライス(offset_endoffset_start)は32ビットを超えてはならず、論理式を使用して複数の呼び出しを結合できます。

bit_slice オフセットは2,040ビットを超えてはなりません。

HMAC検証

概要

is_timed_hmac_valid_v0() 関数を使用して、ルール式でハッシュベースのメッセージ認証コード(HMAC)トークンを検証できます。この関数のシグネチャは次のとおりです:

is_timed_hmac_valid_v0(
<String literal as Key>,
<String field as MessageMAC>,
<Integer literal as ttl>,
<Integer as currentTimeStamp>,
<Optional Integer literal as lengthOfSeparator, default: 0>,
<Optional String literal as flags>
) -> <Bool as result>

is_timed_hmac_valid_v0() 関数のパラメータ定義は次のとおりです:

  • Key (String literal)

    • HMACを検証するための秘密の暗号鍵を指定します。
  • MessageMAC (String)

    • これらのHMAC要素の連結を含みます:messageseparatortimestampmac。定義と例については、MessageMACを参照してください。
  • ttl (Integer literal)

    • HMACトークンの有効期限を秒単位で定義します。トークンが発行された時点からどれだけの間有効であるかを決定します。
  • currentTimeStamp (Integer)

    • Cloudflareがリクエストを受信したときのUNIXタイムスタンプを秒単位で表します。この引数には、http.request.timestamp.sec フィールドを近似値として渡します。
  • lengthOfSeparator (Integer literal, optional)

    • MessageMAC内の timestampmessage の間の separator の長さを指定します。バイト単位で表し、デフォルト値は 0 です。
  • flags (String literal, optional)

    • このオプション引数を 's' に設定すると、MessageMAC 引数内のBase64エンコードされた mac の値がパディングなしのURLセーフ文字セットを使用することを期待します。

    • flags の値を 's' に設定しない場合、MessageMAC 引数内の mac のBase64値をURLエンコードする必要があります。

使用法

is_timed_hmac_valid_v0() 関数は、提供された Key を使用して、MessageMACmessagetimestamp の領域からメッセージ認証コード(MAC)を生成します。生成されたMACが MessageMACmac 領域と一致し、トークンが期限切れでない場合、HMACは有効であり、関数は true を返します。

例えば、次の式は、正しいHMACトークンを含まない downloads.example.com へのリクエストに一致します:

http.host == "downloads.example.com"
and not is_timed_hmac_valid_v0("mysecretkey", http.request.uri, 100000, http.request.timestamp.sec, 8)

HMAC検証を使用するルールの例については、WAFドキュメントの トークン認証の設定 を参照してください。

MessageMAC

有効なMessageMACは次の正規表現を満たします:

(.+)(.*)(\d{10})-(.{43,})

およびこれらの括弧で区切られた式で構成されています:

説明
(.+)検証する message/download/cat.jpg
(.*)メッセージとタイムスタンプの間の separator、一般的にはパラメータ名。&verify=
(\d{10})MACが発行されたときの10桁のUNIX timestamp、秒単位で表現。1484063137
(.{43,})mac のBase64エンコードバージョン。HMAC検証関数の urlSafe 引数の値を 's' に設定しない場合、mac のBase64値をURLエンコードする必要があります。Base64 MACエンコーディングがURLセーフな場合、mac 値は43バイトを含みます。そうでない場合、値はURLエンコーディングのため44バイト以上になります。IaLGSmELTvlhfd0ItdN6PhhHTFhzx73EX8uy%2FcSDiIU%3D

MessageMACの生成に関する詳細は、HMACトークン生成を参照してください。

HMAC検証の例

単一フィールド内のMessageMAC

MessageMACが単一フィールド内に完全に含まれている場合を考えます。この例のURIパス:

/download/cat.jpg?verify=1484063787-IaLGSmELTvlhfd0ItdN6PhhHTFhzx73EX8uy%2FcSDiIU%3D

URIがMessageMACの要素にどのようにマッピングされるかに注意してください:

要素
message/download/cat.jpg
separator?verify=(長さ 8
timestamp1484063787
macIaLGSmELTvlhfd0ItdN6PhhHTFhzx73EX8uy%2FcSDiIU%3D

MessageMACが http.request.uri のような単一フィールド内に完全に含まれている場合、HMAC検証関数の MessageMAC 引数にフィールド名を渡します:

is_timed_hmac_valid_v0(
"mysecretkey",
http.request.uri,
100000,
http.request.timestamp.sec,
8
)

連結されたMessageMAC引数

複数のフィールドからMessageMACを構成するには、concat() 関数を使用します。

この例では、リクエストURIと2つのヘッダーフィールドを連結して MessageMAC 引数の値を構築します:

is_timed_hmac_valid_v0(
"mysecretkey",
concat(
http.request.uri,
http.request.headers["timestamp"][0],
"-",
http.request.headers["mac"][0]),
100000,
http.request.timestamp.sec,
0
)