Skip to content

非公式本サイトは非公式の日本語ドキュメントであり、Cloudflare 公式サイトではありません。最新情報はdevelopers.cloudflare.comをご確認ください。

エグレス制御

最終更新 Markdown で表示Agent セットアップ

動的 Worker で信頼できないコードや AI 生成コードを実行するときは、ネットワーク上で何にアクセスできるかを制御する必要があります。次のようなことが必要になる場合があります。

  • 外向きアクセスをすべて遮断し、動的 Worker が渡した バインディング だけを使えるようにする
  • 外向きリクエストを、許可した宛先の集合に制限する
  • シークレットを動的 Worker に見せずに、外向きリクエストへ資格情報を注入する
  • 可観測性のため、すべての外向きリクエストを記録または監査する

get() が返す、または load() に渡す WorkerCode オブジェクトの globalOutbound オプションで、これらをすべて制御します。動的 Worker が行うすべての fetch()connect() 呼び出しを傍受します。

外向きアクセスをすべて遮断する

globalOutboundnull に設定すると、動的 Worker をネットワークから完全に分離できます。

return {
	mainModule: "index.js",
	modules: { "index.js": code },
	globalOutbound: null,
};

これにより、動的 Worker からの fetch() または connect() リクエストは例外を投げます。

このモードでも、バインディング を使って、特定のリソースやサービスへの直接アクセスを Dynamic Worker に渡せます。インターネットを遮断したうえで、バインディングで特定の機能だけを与えるのが、サンドボックスを設計するうえで最もシンプルで安全な方法です。

一方、Dynamic Worker サンドボックス内で既存の HTTP クライアントライブラリとの互換性が必要な場合、fetch() の遮断は現実的でないことがあり、リクエストの傍受を選ぶ方がよい場合があります。

外向きリクエストを傍受する

外向きリクエストを傍受するには、ローダー Worker でゲートウェイとして動く WorkerEntrypoint クラスを定義します。動的 Worker が行うすべての fetch()connect() 呼び出しは、ネットワークへ直接行かず、このゲートウェイを通ります。globalOutboundctx.exports でゲートウェイを動的 Worker に渡します。

import { WorkerEntrypoint } from "cloudflare:workers";

export class HttpGateway extends WorkerEntrypoint {
	async fetch(request) {
		// Every outbound fetch() from the dynamic Worker arrives here.
		// Inspect, modify, block, or forward the request.
		return fetch(request);
	}
}

export default {
	async fetch(request, env, ctx) {
		const worker = env.LOADER.get("my-worker", async () => {
			return {
				compatibilityDate: "$today",
				mainModule: "index.js",
				modules: { "index.js": code },

				// Pass the gateway as a service binding.
				// The dynamic Worker's fetch() and connect() calls
				// are routed through HttpGateway instead of going
				// to the network directly.
				globalOutbound: ctx.exports.HttpGateway(),
			};
		});

		return worker.getEntrypoint().fetch(request);
	},
};

ここから、宛先の制限、資格情報の注入、リクエストの記録など、任意のロジックをゲートウェイに追加できます。

資格情報を注入する

よくあるパターンは、シークレットを動的 Worker に見せずに、外向きリクエストへ資格情報を付けることです。カスタムバインディング と同様に、ctx.props でテナントごとまたはリクエストごとのコンテキストをゲートウェイに渡せます。

動的 Worker は通常どおり fetch() を呼びます。HttpGateway がリクエストを傍受し、ローダー Worker の環境からトークンを付けて転送します。動的 Worker は API_TOKEN にアクセスできません。

import { WorkerEntrypoint } from "cloudflare:workers";

export class HttpGateway extends WorkerEntrypoint {
	async fetch(request) {
		let url = new URL(request.url);
		const headers = new Headers(request.headers);

		// For requests to api.example.com, inject credentials.
		if (url.hostname === "api.example.com") {
			headers.set("Authorization", `Bearer ${this.env.API_TOKEN}`);
			headers.set("X-Tenant-Id", this.ctx.props.tenantId);
		}

		return fetch(request, { headers });
	}
}

export default {
	async fetch(request, env, ctx) {
		const tenantId = getTenantFromRequest(request);

		const worker = env.LOADER.get(`tenant:${tenantId}`, async () => {
			return {
				mainModule: "index.js",
				modules: {
					"index.js": `
						export default {
							async fetch() {
								const resp = await fetch("https://api.example.com/data");
								return new Response(await resp.text());
							},
						};
					`,
				},
				globalOutbound: ctx.exports.HttpGateway({
					props: { tenantId },
				}),
			};
		});

		return worker.getEntrypoint().fetch(request);
	},
};

役に立ちましたか?