アウトバウンドハンドラーを使うと、信頼できるコードでサンドボックスからの HTTP トラフィックを傍受し、変更できます。
次の用途に使います。
- 特定の送信先オリジンを許可または拒否する
- 認可ヘッダーやトークンを安全に注入する
- トラフィックを透過的に付け替える
- アウトバウンドトラフィックに独自ポリシーを追加する(特定の HTTP リクエストの拒否など)
- KV、R2、Durable Objects などの Workers バインディングに接続する
enableInternet = false で、デフォルトのパブリックインターネットアクセスをブロックします。
import { Sandbox } from "@cloudflare/sandbox";
export class MySandbox extends Sandbox {
enableInternet = false;
}import { Sandbox } from "@cloudflare/sandbox";
export class MySandbox extends Sandbox {
enableInternet = false;
}enableInternet が false のとき、このページで後述する allowedHosts またはアウトバウンドハンドラーで明示的に許可したトラフィックだけがサンドボックスから出られます。利用できるポートは 80、443、DNS だけです。DNS クエリは Cloudflare の DNS サーバーを使います。
Sandbox クラスの allowedHosts と deniedHosts プロパティで、アウトバウンドトラフィックをフィルタできます。
allowedHosts を設定すると、デフォルト拒否の許可リストになります。リストにないホストまたは IP は拒否され、一致する送信先だけが outbound または outboundByHost ハンドラーに到達できます。
allowedHosts と deniedHosts は、単純な glob パターンも使えます。* は任意の文字シーケンスに一致します。
デフォルトでは、Sandbox はインターネットアクセスを許可します。特定のホストまたは IP を拒否するには deniedHosts を設定します。
import { Sandbox, ContainerProxy } from "@cloudflare/sandbox";
export { ContainerProxy };
export class MySandbox extends Sandbox {
deniedHosts = ["some-nefarious-website.com", "141.101.64.0/18"];
}import { Sandbox, ContainerProxy } from "@cloudflare/sandbox";
export { ContainerProxy };
export class MySandbox extends Sandbox {
deniedHosts = ["some-nefarious-website.com", "141.101.64.0/18"];
}デフォルトでインターネットアクセスを無効にし、特定のホストと IP だけを許可することもできます。
import { Sandbox, ContainerProxy } from "@cloudflare/sandbox";
export { ContainerProxy };
export class MySandbox extends Sandbox {
// default internet access to off unless overridden by 'allowedHosts' or outbound proxy
enableInternet = false;
// overrides enableInternet = false
allowedHosts = ["allowed.com"];
}import { Sandbox, ContainerProxy } from "@cloudflare/sandbox";
export { ContainerProxy };
export class MySandbox extends Sandbox {
// default internet access to off unless overridden by 'allowedHosts' or outbound proxy
enableInternet = false;
// overrides enableInternet = false
allowedHosts = ["allowed.com"];
}アウトバウンドハンドラーは、サンドボックスと同じマシンで動く、プログラム可能な egress プロキシです。すべての Workers バインディングにアクセスできます。
outbound で、すべてのアウトバウンド HTTP および HTTPS トラフィックを傍受します。
import { Sandbox, ContainerProxy } from "@cloudflare/sandbox";
export { ContainerProxy };
export class MySandbox extends Sandbox {}
MySandbox.outbound = async (request, env, ctx) => {
if (request.method !== "GET") {
console.log(`Blocked ${request.method} to ${request.url}`);
return new Response("Method Not Allowed", { status: 405 });
}
return fetch(request);
};import { Sandbox, ContainerProxy } from "@cloudflare/sandbox";
export { ContainerProxy };
export class MySandbox extends Sandbox {}
MySandbox.outbound = async (
request: Request,
env: Env,
ctx: OutboundHandlerContext,
) => {
if (request.method !== "GET") {
console.log(`Blocked ${request.method} to ${request.url}`);
return new Response("Method Not Allowed", { status: 405 });
}
return fetch(request);
};特定のドメイン名または IP アドレスをハンドラー関数に割り当てるには outboundByHost を使います。
import { Sandbox, ContainerProxy } from "@cloudflare/sandbox";
export { ContainerProxy };
export class MySandbox extends Sandbox {}
MySandbox.outboundByHost = {
"my.worker": async (request, env, ctx) => {
// Run arbitrary Workers logic from this hostname
return await someWorkersFunction(request.body);
},
};import { Sandbox, ContainerProxy } from "@cloudflare/sandbox";
export { ContainerProxy };
export class MySandbox extends Sandbox {}
MySandbox.outboundByHost = {
"my.worker": async (
request: Request,
env: Env,
ctx: OutboundHandlerContext,
) => {
// Run arbitrary Workers logic from this hostname
return await someWorkersFunction(request.body);
},
};サンドボックスから http://my.worker への呼び出しはハンドラーを起動します。ハンドラーは Workers ランタイム内、サンドボックスの外で実行されます。
deniedHosts と allowedHosts は、どのアウトバウンドハンドラーよりも先に評価されます。allowedHosts を使う場合は、outbound または outboundByHost を動かすホスト名をそこに含めてください。outboundByHost ハンドラーは、包括的な outbound ハンドラーより優先されます。
アウトバウンドハンドラーは Workers ランタイム(サンドボックスの外)で動くため、サンドボックス自身が見ないシークレットを保持できます。サンドボックスは平文の HTTP リクエストを送り、ハンドラーが認証情報を付けて上流サービスへ転送します。
export class MySandbox extends Sandbox {}
MySandbox.outboundByHost = {
"github.com": (request, env, ctx) => {
const requestWithAuth = new Request(request);
requestWithAuth.headers.set("x-auth-token", env.SECRET);
return fetch(requestWithAuth);
},
};export class MySandbox extends Sandbox {}
MySandbox.outboundByHost = {
"github.com": (request: Request, env: Env, ctx: OutboundHandlerContext) => {
const requestWithAuth = new Request(request);
requestWithAuth.headers.set("x-auth-token", env.SECRET);
return fetch(requestWithAuth);
},
};サンドボックス内のコードを完全には信頼できないエージェントワークロードで特に有用です。このパターンでは次のとおりです。
- トークンはサンドボックスに露出しません。 シークレットは Worker の環境にあり、サンドボックスへは渡りません。
- サンドボックス内でのトークンローテーションは不要です。 Worker の環境でシークレットをローテーションすれば、以降のリクエストはすぐに新しい値を使います。
- ホスト単位およびインスタンス単位のルール。
outboundByHostとctx.containerIdを組み合わせて、認証情報や権限を特定のサンドボックスインスタンスに限定できます。
ここでは、ctx.containerId で KV からインスタンスごとのキーを取得します。
export class MySandbox extends Sandbox {}
MySandbox.outboundByHost = {
"my-internal-vcs.dev": async (request, env, ctx) => {
const authKey = await env.KEYS.get(ctx.containerId);
const requestWithAuth = new Request(request);
requestWithAuth.headers.set("x-auth-token", authKey);
return fetch(requestWithAuth);
},
};export class MySandbox extends Sandbox {}
MySandbox.outboundByHost = {
"my-internal-vcs.dev": async (
request: Request,
env: Env,
ctx: OutboundHandlerContext,
) => {
const authKey = await env.KEYS.get(ctx.containerId);
const requestWithAuth = new Request(request);
requestWithAuth.headers.set("x-auth-token", authKey);
return fetch(requestWithAuth);
},
};サンドボックスはデフォルトで HTTPS トラフィックを傍受します。Sandbox クラスでは interceptHttps が true です。
HTTPS 傍受が有効なとき、サンドボックス起動後に一時的な CA ファイルが /etc/cloudflare/certs/cloudflare-containers-ca.crt に作成されます。
Sandbox ランタイムは、ディストリビューションに関係なく、この CA を自動的に信頼するよう最善を尽くします。起動時に、主要な Linux 系列の一般的なシステム CA バンドル場所を確認し、一般的な CA 環境変数を設定します。Node.js、curl、Python の requests、Git などが証明書を自動的に信頼します。
アウトバウンドハンドラーが傍受するのは HTTP と HTTPS だけです。80 と 443 以外のポートのトラフィックは、outbound や outboundByHost には回りません。
enableInternet = false を設定すると、そのトラフィックは拒否されます。例外は DNS クエリだけですが、送信先は Cloudflare の DNS サーバーに限られます。任意の DNS 送信先を使ったデータ持ち出しを防ぎます。
outboundHandlers で名前付きハンドラーを定義し、setOutboundByHost() で実行時に特定ホストへ割り当てます。setOutboundHandler() でハンドラーをグローバルに適用することもできます。
実行時ポリシーは setOutboundByHosts()、setAllowedHosts()、setDeniedHosts()、allowHost()、denyHost()、removeAllowedHost()、removeDeniedHost() でも管理できます。
信頼できる Worker が認証情報を保持し、信頼できないサンドボックスには渡さない構成にできます。
import { Sandbox, ContainerProxy } from "@cloudflare/sandbox";
export { ContainerProxy };
export class MySandbox extends Sandbox {}
MySandbox.outboundHandlers = {
authenticatedGithub: async (request, env, ctx) => {
const githubToken = env.GITHUB_TOKEN;
return authenticateGitHttpsRequest(request, githubToken, ctx.containerId);
},
};import { Sandbox, ContainerProxy } from "@cloudflare/sandbox";
export { ContainerProxy };
export class MySandbox extends Sandbox {}
MySandbox.outboundHandlers = {
authenticatedGithub: async (
request: Request,
env: Env,
ctx: OutboundHandlerContext,
) => {
const githubToken = env.GITHUB_TOKEN;
return authenticateGitHttpsRequest(request, githubToken, ctx.containerId);
},
};Worker からプログラムでホストにハンドラーを適用します。
import { Sandbox, ContainerProxy, getSandbox } from "@cloudflare/sandbox";
export { ContainerProxy };
export default {
async fetch(request, env) {
const sandbox = getSandbox(env.Sandbox, "agent-session");
// Give the sandbox access to github.com during setup
await sandbox.setOutboundByHost("github.com", "authenticatedGithub");
await sandbox.exec("node setup.js");
// Remove access once setup is complete
await sandbox.removeOutboundByHost("github.com");
},
};import { Sandbox, ContainerProxy, getSandbox } from "@cloudflare/sandbox";
export { ContainerProxy };
export default {
async fetch(request: Request, env: Env) {
const sandbox = getSandbox(env.Sandbox, "agent-session");
// Give the sandbox access to github.com during setup
await sandbox.setOutboundByHost("github.com", "authenticatedGithub");
await sandbox.exec("node setup.js");
// Remove access once setup is complete
await sandbox.removeOutboundByHost("github.com");
},
};リクエストは次の順で評価されます。
- 最初に
deniedHostsを確認します。一致するホストまたは IP は直ちに拒否されます。 - 次に
allowedHostsを確認します。設定されている場合、リストにないホストまたは IP は拒否されます。一致するホストはアウトバウンドハンドラーへ進むか、ハンドラーがなければパブリックインターネットへ出ます。 setOutboundByHost()で設定したインスタンス単位のルールは、クラス単位のoutboundByHostルールより先に確認されます。- ホスト単位のハンドラーは包括的なハンドラーより常に優先されるため、
outboundByHostはoutboundより先に動きます。 setOutboundHandler()で設定したインスタンス単位のハンドラーは、クラス単位のoutboundハンドラーより先に確認されます。- ハンドラーが一致しない場合でも、
allowedHostsに一致した、またはenableInternet = trueのときは、リクエストはパブリックインターネットへ出られます。それ以外は拒否されます。
wrangler dev はアウトバウンド傍受に対応しています。サンドボックスのネットワーク名前空間内でサイドカープロセスが起動します。一致するトラフィックをローカルの Workerd インスタンスへ回す TPROXY ルールを適用し、本番と同じ動きにします。
- Workers バインディングに接続する — サンドボックスから KV、R2、Durable Objects、その他のバインディングにアクセスします
- アウトバウンドトラフィックを処理する(Containers) — アウトバウンドハンドラー向けの Container SDK API
- Sandbox オプション — サンドボックスの動作を設定します
- 環境変数 — シークレットと環境変数を設定します