Оверлейные сети
Оверлейные сети
Заголовок раздела «Оверлейные сети»Маршрутизация исходящих HTTP-запросов и порождаемых процессов через оверлеи SOCKS5, Tailscale или I2P.
Wippy поддерживает оверлейные сети, прозрачно передающие трафик, исходящий от функций, процессов и HTTP-клиентов. Каждый оверлей — это запись в реестре; код подключается к нему при каждом вызове, и выбор наследуется во вложенных вызовах, пока потомок явно не переопределит его.
Поддерживаемые оверлеи:
network.socks5— универсальный SOCKS5-прокси (в том числе SOCKS5-слушатель Tor)network.tailscale— оверлейный узел tsnetnetwork.i2p— мост I2P SAM v3
Структура проекта
Заголовок раздела «Структура проекта»netdemo/├── wippy.lock└── src/ ├── _index.yaml └── probe.luaШаг 1: Определение оверлея
Заголовок раздела «Шаг 1: Определение оверлея»Создайте src/_index.yaml:
version: "1.0"namespace: app
entries: - name: processes kind: process.host lifecycle: auto_start: true
- name: terminal kind: terminal.host lifecycle: auto_start: true
# SOCKS5 proxy entry (Tor exposes one at 127.0.0.1:9050 by default) - name: tor kind: network.socks5 host: 127.0.0.1 port: 9050 isolate_streams: true
- name: probe kind: process.lua meta: command: name: probe short: Check outbound IP through overlays source: file://probe.lua method: main modules: - io - http_client - jsonisolate_streams: true заставляет SOCKS5-драйвер генерировать случайные учётные данные для каждого соединения, чтобы Tor открывал новую цепочку при каждом подключении.
Шаг 2: Маршрутизация исходящих вызовов
Заголовок раздела «Шаг 2: Маршрутизация исходящих вызовов»Создайте src/probe.lua:
local io = require("io")local http_client = require("http_client")local json = require("json")
local function fetch_ip(overlay) local options = { timeout = "15s" } if overlay then options.overlay_network = overlay end
local resp, err = http_client.get("https://api.ipify.org?format=json", options) if err then return nil, tostring(err) end if resp.status_code ~= 200 then return nil, "HTTP " .. resp.status_code end
local body = json.decode(resp.body or "") return body and body.ip, nilend
local function main() local direct, d_err = fetch_ip(nil) if d_err then io.print("direct failed: " .. d_err) else io.print("direct IP: " .. direct) end
local routed, r_err = fetch_ip("app:tor") if r_err then io.print("tor failed: " .. r_err) else io.print("tor IP: " .. routed) end
return 0end
return { main = main }Опция overlay_network в http_client выбирает оверлей только для данного вызова. Без неё соединение идёт через дефолтный оверлей процесса (либо network_service.default_network в .wippy.yaml, либо напрямую).
Шаг 3: Запуск
Заголовок раздела «Шаг 3: Запуск»wippy initwippy run probeПри запущенном локально Tor:
direct IP: 203.0.113.42tor IP: 185.220.101.61Если Tor не запущен, строка tor IP выведет ошибку подключения — SOCKS5-оверлей не падает обратно на прямое соединение молча.
Наследование
Заголовок раздела «Наследование»Выбор оверлея распространяется на вложенные вызовы. Укажите оверлей один раз на границе funcs.call или process.spawn, и все внутренние HTTP-вызовы, вложенные funcs.call и process.spawn будут использовать его до явного переопределения:
local funcs = require("funcs")
local result, err = funcs.new() :with_options({ network = "app:tor" }) :call("app:scrape_site", url)local pid, err = process.with_options({ network = "app:tor" }) :spawn_monitored("app.workers:probe", "app:processes")Вложенная функция или порождённый процесс видит оверлей на каждом исходящем вызове без явной передачи.
Привязка слушателя
Заголовок раздела «Привязка слушателя»Оверлеи с поддержкой входящего трафика (Tailscale, I2P) могут также принимать HTTP-слушателей. Привяжите оверлей к http.service вместо клиента:
- name: tailnet kind: network.tailscale hostname: wippy-node auth_key_env: TS_AUTHKEY ephemeral: true
- name: gateway kind: http.service addr: ":8080" network: app:tailnet lifecycle: auto_start: trueСервер привязывается на интерфейсе tailnet; клиенты обращаются к нему через Tailscale-адрес. SOCKS5 работает только на исходящий трафик — назначение его http.service отклоняется.
Глобальный дефолт
Заголовок раздела «Глобальный дефолт»Задайте дефолтный оверлей в .wippy.yaml, чтобы все вызовы использовали его, если не переопределено:
network_service: state_dir: .wippy/net default_network: app:torЯвное указание network = nil сбрасывает дефолт для данного вызова.
Разрешения
Заголовок раздела «Разрешения»Действие network.select контролирует явный выбор оверлея. Запретите его для scope, чтобы код не мог выбирать оверлей:
- name: deny_network kind: security.policy policy: actions: "network.select" resources: "*" effect: deny groups: - untrustedУнаследованные оверлеи обходят эту проверку — они были авторизованы на границе вызывающего кода. Под контролем находится только явный повторный выбор на границе Lua.
Следующие шаги
Заголовок раздела «Следующие шаги»- Сетевая система - Справочник по entry kind
- HTTP Client - Опции оверлея для отдельного вызова
- Модель безопасности - Политики и scope
- Аутентификация - Безопасность на основе токенов