Cloudflare Radar BGP Anomaly Detection の結果にアクセスするには、まず Account:Radar 権限を含む API トークンを作成する必要があります。次の例はすべて、無料プランの Cloudflare アカウントで動くはずです。
次の例では、AS64512(例の ASN)が起点である、または影響を受ける、最新の BGP origin ハイジャックについて BGP hijack events API をクエリします。
curl "https://api.cloudflare.com/client/v4/radar/bgp/hijacks/events?invlovedAsn=64512&format=json&per_page=10" \
--header "Authorization: Bearer <API_TOKEN>"結果は、AS64512 に影響する最新 10 件の BGP ハイジャックイベントを示します。
{
"success": true,
"errors": [],
"result": {
"asn_info": [
{
"asn": 64512,
"org_name": "XXXXX",
"country_code": "XX"
},
...
],
"events": [
{
"duration": 0,
"event_type": 0,
"hijack_msgs_count": 1,
"hijacker_asn": 64512,
"id": 1234,
"is_stale": false,
"max_hijack_ts": "2023-04-27T14:01:55.952",
"max_msg_ts": "2023-04-27T14:01:55.952",
"min_hijack_ts": "2023-04-27T14:01:55.952",
"on_going_count": 1,
"peer_asns": [
8455
],
"peer_ip_count": 1,
"prefixes": [
"192.0.2.0/24"
],
"tags": [
{
"name": "irr_new_origin_invalid",
"score": 4
},
{
"name": "irr_old_origin_valid",
"score": 0
},
...
],
"victim_asns": [
64513
],
"confidence_score": 4
},
],
"total_monitors": 163
},
...
}レスポンスから、各イベントについて次の情報を知れます。
hijack_msg_count: すべてのピアから観測された、潜在的な BGP ハイジャックメッセージの数。peer_asns: ハイジャックメッセージを観測したルートコレクターピアの AS 番号。prefixes: 影響を受けたプレフィックス。hijacker_asnとvictim_asns: 潜在的なハイジャック ASN と被害 ASN。confidence_score: このイベントがハイジャックであることにシステムがどれだけ自信があるかを表す定量スコア。- 1-3: 低信頼度。
- 4-7: 中信頼度。
- 8 以上: 高信頼度。
tags: イベント向けに収集された証拠。各tagは、全体の信頼度スコアに影響するスコアにも紐付いています。- 正のスコアは、イベントがハイジャックである 可能性が高い ことを示します。
- 負のスコアは、イベントがハイジャックである 可能性が低い ことを示します。
minConfidence=8 パラメーターを付けて低信頼度イベントをさらに除外できます。confidence_score が 8 以上のイベントだけが返されます。
curl "https://api.cloudflare.com/client/v4/radar/bgp/hijacks/events?invlovedAsn=64512&format=json&per_page=10&minConfidence=8" \
--header "Authorization: Bearer <API_TOKEN>"BGP ルートリークは、Cloudflare Radar が検出するもう 1 つの BGP 異常です。現在は特に、
provider-customer-provider 型のルートリークの検出に焦点を当てています。設計と手法の詳細は ブログ記事 ↗ で学べます。
次の例では、AS64512 に影響する最新の BGP ルートリークイベントについて BGP route leak events API をクエリします。
curl "https://api.cloudflare.com/client/v4/radar/bgp/leaks/events?invlovedAsn=64512&format=json&per_page=10" \
--header "Authorization: Bearer <API_TOKEN>"結果は、AS64512 に影響する最新 10 件の BGP ルートリークイベントを示します。
{
"success": true,
"errors": [],
"result": {
"asn_info": [
{
"asn": 64512,
"org_name": "XXXXXXX",
"country_code": "XX"
},
...
],
"events": [
{
"detected_ts": "2023-04-21T23:10:06",
"finished": false,
"id": 1234,
"leak_asn": 64512,
"leak_count": 14,
"leak_seg": [
64514,
64512,
64513
],
"leak_type": 1,
"max_ts": "2023-04-21T23:10:56",
"min_ts": "2023-04-21T23:09:46",
"origin_count": 1,
"peer_count": 13,
"prefix_count": 1
},
...
]
},
...
}レスポンスから、各イベントについて次の情報を知れます。
leak_asn: リークの原因となった可能性のある AS。leak_seg: 観測され、リークと見なされる AS パスセグメント。min_tsとmax_ts: リーク告知の最も早いタイムスタンプと最も遅いタイムスタンプ。leak_count: 観測された BGP ルートリーク告知の総数。peer_count: リークを観測したルートコレクターピアの数。prefix_countとorigin_count: リークの影響を受けたプレフィックスと origin AS の数。
この例では、Webhooks(Google Hangouts、Discord、Telegram など)またはメールを使い、指定 ASN に関連する BGP ハイジャックのアラートを送る Cloudflare Workers アプリの構築方法を示します。
プラットフォームとして Cloudflare Workers を使い、Cron Triggers で新しいアラートを定期的に確認します。
アプリには次のことをさせます。
- 指定した API トークンで Cloudflare API から取得する。
- Cloudflare KV と照合し、どのイベントが新しいかを知る。
- 新しいハイジャックのメッセージを組み立て、webhook トリガー経由でアラートを送る。
Cloudflare Worker アプリのセットアップから始めます。
まず、ローカルディレクトリに新しい Workers アプリを作成します。
npm create cloudflare@latest -- hijack-alertsyarn create cloudflare hijack-alertspnpm create cloudflare@latest hijack-alertsセットアップでは、次のオプションを選びます。
- What would you like to start with? では、
Hello World exampleを選びます。 - Which template would you like to use? では、
Worker onlyを選びます。 - Which language do you want to use? では、
JavaScriptを選びます。 - Do you want to use git for version control? では、
Yesを選びます。 - Do you want to deploy your application? では、
Noを選びます(デプロイ前にいくつか変更します)。
Worker の開発を始めるには、新しいプロジェクトディレクトリへ cd します。
cd hijack-alertsWrangler ファイルで、デフォルトの確認頻度(1 時間に 1 回)を好みの値に変更します。次は、スクリプトを 5 分ごとに実行するように Workers を構成する例です。
{
"$schema": "./node_modules/wrangler/config-schema.json",
"name": "hijack-alerts",
"main": "src/index.js",
// Set this to today's date
"compatibility_date": "2026-09-20",
"triggers": {
"crons": [
"*/5 * * * *"
]
}
}"$schema" = "./node_modules/wrangler/config-schema.json"
name = "hijack-alerts"
main = "src/index.js"
# Set this to today's date
compatibility_date = "2026-09-20"
[triggers]
crons = [ "*/5 * * * *" ]この例では、最新の確認済みイベント ID を保存するために Cloudflare KV も使い、どのイベントが新しいかを判断します。KV を作成したら、wrangler.jsonc ファイルに戻り、次のセクションを追加します。
{
"kv_namespaces": [
{
"binding": "HIJACKS_KV",
"id": "KV_ID_FOR_PRODUCTION",
"preview_id": "TEMPORARY_KV_FOR_DEV_ENVIRONMENT"
}
]
}[[kv_namespaces]]
binding = "HIJACKS_KV"
id = "KV_ID_FOR_PRODUCTION"
preview_id = "TEMPORARY_KV_FOR_DEV_ENVIRONMENT"API 取得関数から始めます。
次の apiFetch(env, paramsStr) は、リクエストパラメーター文字列を受け取り、適切なヘッダーを組み立て、Cloudflare API の BGP hijacks エンドポイントから取得します。
async function apiFetch(env, paramsStr) {
const config = {
headers: {
Authorization: `Bearer ${env.CF_API_TOKEN}`,
},
};
const res = await fetch(
`https://api.cloudflare.com/client/v4/radar/bgp/hijacks/events?${paramsStr}`,
config,
);
if (!res.ok) {
console.log(JSON.stringify(res));
return null;
}
return await res.json();
}env パラメーターは呼び出し元から渡されます。組み立てる必要はありません。paramsStr は、クエリ URL のクエリパラメーターを保持する文字列変数です。
メインの cron トリガー関数では、クエリパラメーターを組み立て、API 取得関数を呼び出します。 デフォルトの cron トリガー Worker スクリプトは次のように定義されます。
export default {
async scheduled(controller, env, ctx) {
...
}
}この例では、env 変数を使って TOKEN や対象 ASN などの実行時変数と、Cloudflare
KV バインディングを取得します。この例では controller と ctx 変数は使いません。
まず、新しいイベントが何かを知る必要があります。新しいイベントとは、アプリがまだ処理していないイベントです。
先に作成して定義した Cloudflare KV バケット(HIJACKS_KV)を使い、最も最近処理した
イベント ID を保存および取得します。
let kv_latest_id = parseInt(await env.HIJACKS_KV.get("latest_id"));
const first_batch = isNaN(kv_latest_id);最新イベントを確認するメインループは次のようになります(一部の検証コードは省略しています)。
let new_events = [];
let page = 1;
while (true) {
// query for events
const query_params = `per_page=10&page=${page}&involvedAsn=${env.TARGET_ASN}&sortBy=ID&sortOrder=DESC`;
const data = await apiFetch(env, query_params);
// first batch, save KV value only
if (first_batch) {
await env.HIJACKS_KV.put("latest_id", events[0].id.toString());
return;
}
// some validation skipped
// ...
let reached_last = false;
for (const event of data.result.events) {
if (event.id <= kv_latest_id) {
// reached the latest events
reached_last = true;
break;
}
new_events.push(event);
}
if (reached_last) {
break;
}
page += 1;
}これで新しく検出されたイベントがすべて new_events 変数に保存されたので、アラートを送れます。
// sort events by increasing ID order
new_events.sort((a, b) => a.id - b.id);
const kv_latest_id = new_events[new_events.length - 1].id;
// push new events
for (const event of new_events) {
await send_alert(env, event);
}
// update latest_id KV value
await env.HIJACKS_KV.put("latest_id", kv_latest_id.toString());関数 send_alert は、アラートメッセージを組み立て、webhook でアラートを送ります。ここでは
Google Hangouts webhook を使ったプレーンテキストメッセージテンプレートの例を示します。ユーザーは、使う
プラットフォームとニーズに応じてメッセージと webhook の使い方をカスタマイズできます。
async function send_hangout_alert(env, event) {
const webhook_url = `${env.WEBHOOK_URL}&threadKey=bgp-hijacks-event-${event.id}`;
const data = JSON.stringify({
text: `Detected BGP hijack event (${event.id}):
Detected time: *${event.min_hijack_ts} UTC*
Detected ASN: *${event.hijacker_asn}*
Expected ASN(s): *${event.victim_asns.join(" ")}*
Prefixes: *${event.prefixes.join(" ")}*
Tags: *${event.tags.map((tag) => tag.name).join(" ")}*
Peer Count: *${event.peer_ip_count}*
`,
});
await fetch(webhook_url, {
method: "POST",
headers: {
"Content-Type": "application/json; charset=UTF-8",
},
body: data,
});
}webhook はシークレットと見なされ、wrangler secret put WEBHOOK_URL コマンドで環境に設定してください。
最後のステップは npx wrangler deploy でアプリケーションをデプロイすることです。アプリは Cloudflare アカウント上で動き、5 分ごとに実行されるようにトリガーされます。
ドメインで Email Routing が有効な場合は、Workers から直接メールアラートを送ることもできます。詳細は Workers からメールを送る を参照してください。
このアラートを動かすには、Wrangler 構成ファイル で適切なメールバインディングを構成する必要があります。
{
"send_email": [
{
"name": "SEND_EMAIL_BINDING",
"destination_address": "<YOUR_EMAIL>@example.com"
}
]
}[[send_email]]
name = "SEND_EMAIL_BINDING"
destination_address = "<YOUR_EMAIL>@example.com"次に、構成した宛先アドレスへアラートメールを送るメール送信関数を作成できます。
async function send_email_alert(hijacker, prefixes, victims) {
const msg = createMimeMessage();
msg.setSender({
name: "BGP Hijack Alerter",
addr: "<YOUR_APP>@<YOUR_APP_DOMAIN>",
});
msg.setRecipient("<YOUR_EMAIL>@example.com");
msg.setSubject("BGP hijack alert");
msg.addMessage({
contentType: "text/plain",
data: `BGP hijack detected:
Detected origin: ${hijacker}
Expected origins: ${victims.join(" ")}
Prefixes: ${prefixes.join(" ")}
`,
});
var message = new EmailMessage(
"<YOUR_APP>@<YOUR_APP_DOMAIN>",
"<YOUR_EMAIL>@example.com",
msg.asRaw(),
);
try {
await env.SEND_EMAIL_BINDING.send(message);
} catch (e) {
return new Response(e.message);
}
}これらのトピックの詳細は、BGP ルートリーク と BGP ハイジャック の API ドキュメントを参照してください。