← Sandbox SDK / sandbox / guides
Обработка исходящего трафика
Исходящие обработчики позволяют перехватывать и изменять HTTP-трафик из песочницы с помощью доверенного кода.
Используйте их, чтобы:
- Разрешайте или запрещайте доступ к определённым адресам назначения
- Безопасно внедряйте заголовки авторизации или токены
- Прозрачно перенаправлять трафик
- Добавьте собственную политику для исходящего трафика (например, запрет определённых HTTP-запросов)
- Подключитесь к привязкам Workers например KV, R2 и Durable Objects
Блокируйте исходящий трафик
Используйте 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 или исходящие обработчики могут покинуть sandbox. Только порты 80, 443, и DNS доступны, а DNS-запросы используют DNS-серверы Cloudflare.
Блокируйте или разрешайте трафик по хосту
Исходящий трафик можно фильтровать с помощью allowedHosts и deniedHosts свойства класса Sandbox.
Когда allowedHosts задан, он становится белым списком с запретом по умолчанию. Любой хост или IP, не входящий в список, блокируется, и только совпадающие адреса назначения могут получить доступ к outbound или outboundByHost обработчики.
allowedHosts и deniedHosts также поддерживают простые glob-шаблоны, где * соответствует любой последовательности символов.
По умолчанию Sandbox разрешает доступ в интернет, и вы можете задать deniedHosts чтобы запретить доступ к определённым хостам или IP-адресам:
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"];
}Определите обработчики исходящих запросов
Исходящие обработчики представляют собой программируемые прокси для исходящего трафика, которые выполняются на той же машине, что и песочница. Они имеют доступ ко всем привязкам 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);
};Используйте outboundByHost для сопоставления конкретных доменных имён или IP-адресов с функциями-обработчиками:
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 вычисляются раньше любого outbound-обработчика. Если вы используете allowedHosts, укажите там имя хоста для outbound или outboundByHost для запуска. outboundByHost обработчики имеют приоритет над catch-all 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 и никогда не передаётся в sandbox.
- Ротация токена внутри песочницы не выполняется. Обновите секрет в окружении своего 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-трафик
По умолчанию песочницы перехватывают HTTPS-трафик: interceptHttps имеет значение true в классе Sandbox.
Когда перехват HTTPS активен, временный файл CA создаётся по пути /etc/cloudflare/certs/cloudflare-containers-ca.crt после запуска песочницы.
Среда выполнения Sandbox старается автоматически довериться этому CA независимо от дистрибутива. При запуске она проверяет стандартные расположения системного набора сертификатов CA для основных семейств Linux и настраивает стандартные переменные окружения CA, чтобы среды выполнения вроде Node.js, curl, Python requests, и Git автоматически доверяют этому сертификату.
Трафик не по HTTP
Исходящие обработчики перехватывают только HTTP- и HTTPS-трафик. Трафик на портах, отличных от 80 и 443 никогда не направляется через outbound или outboundByHost.
Если вы зададите enableInternet = false, такой трафик блокируется. Исключение составляют DNS-запросы, но они направляются только на DNS-серверы Cloudflare. Это исключает использование произвольных 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правил. - Обработчики для конкретного хоста всегда имеют приоритет над catch-all обработчиками, поэтому
outboundByHostвыполняется передoutbound. - Обработчики уровня инстанса, заданные с помощью
setOutboundHandler()проверяются раньше, чем на уровне классаoutboundобработчик. - Если ни один обработчик не подошёл, запрос всё равно может выйти в публичный интернет, если он соответствовал
allowedHostsилиenableInternet = true. В противном случае запрос отклоняется.
Локальная разработка
wrangler dev поддерживает перехват исходящих соединений. Внутри сетевого пространства имен sandbox запускается sidecar-процесс. Он применяет TPROXY правила для маршрутизации подходящего трафика к локальному экземпляру Workerd, повторяя поведение продакшена.
Дополнительные материалы
- Подключитесь к привязкам Workers : доступ к KV, R2, Durable Objects и другим bindings из песочницы
- Обработка исходящего трафика (Containers) : Container SDK API для обработчиков исходящих запросов
- Параметры песочницы : настройка поведения песочницы
- Переменные окружения : настройка секретов и переменных окружения