네트워크 오버레이

네트워크 오버레이 엔트리는 SOCKS5, Tor, Tailscale 또는 I2P를 통해 아웃바운드 연결을 라우팅하거나 리스너를 바인딩합니다. 선택한 오버레이는 함수, 프로세스, HTTP 경계를 넘어 전파됩니다.

이 페이지는 설정 레퍼런스입니다. YAML 펜스는 엔트리 또는 애플리케이션 설정 조각이며 외부 프록시, tailnet 또는 I2P SAM 서비스가 이미 존재한다고 가정합니다.

엔트리 종류

종류 설명
network.socks5 일반 SOCKS5 프록시 (Tor의 SOCKS5 리스너도 포함)
network.tailscale Tailscale tsnet 오버레이 노드
network.i2p I2P SAM v3 브리지

SOCKS5

- name: proxy
  kind: network.socks5
  host: 127.0.0.1
  port: 1080
  username: "optional"
  password: "optional"
  isolate_streams: false
필드 타입 설명
host string 프록시 호스트
port int 프록시 포트 (1-65535)
username string 선택적 SOCKS5 인증
password string 선택적 SOCKS5 인증
isolate_streams bool 연결별 랜덤 자격 증명 (Tor 스트림 격리)

hostport는 필수입니다. isolate_streams의 기본값은 false입니다. 격리를 활성화하면 런타임은 설정된 자격 증명 대신 다이얼마다 새로운 사용자 이름과 비밀번호를 생성합니다.

Tailscale

- name: tailnet
  kind: network.tailscale
  hostname: "wippy-node"
  auth_key: ${env:TS_AUTHKEY}
  ephemeral: false
  control_url: ""
필드 타입 설명
hostname string tsnet 노드 이름 (노드별 상태 디렉토리에서 사용)
auth_key string Tailnet 인증 키 — 인라인 또는 env 레지스트리를 통해 해석되는 ${env:NAME}
state_dir string tsnet 상태 디렉토리 재정의
control_url string 대체 조정 서버
ephemeral bool 임시 tailnet 노드로 등록

auth_key는 필수입니다(직접 지정하거나 ${env:NAME}으로 제공). 레거시 auth_key_env 디렉티브도 동일한 방식으로 해석되지만 더 이상 사용되지 않습니다. auth_key: ${env:NAME}을 사용하세요.

I2P

- name: i2p_bridge
  kind: network.i2p
  host: 127.0.0.1
  port: 7656
  session_name: "wippy"
필드 타입 설명
host string SAM v3 브리지 호스트
port int SAM v3 브리지 포트
session_name string 선택적 세션 식별자

hostport는 필수입니다. session_name의 기본값은 wippy이며 다이얼 및 리스너별 SAM 세션 ID의 접두사로 사용됩니다.

오버레이 선택

http.service에서

오버레이(Tailscale, I2P)를 통해 서버 리스너를 바인딩합니다:

- name: gateway
  kind: http.service
  addr: ":8080"
  network: app.net:tailnet

SOCKS5는 인바운드 수신을 지원하지 않습니다 — 아웃바운드 다이얼에만 사용하세요.

Lua에서

with_options를 사용하여 호출된 함수나 생성된 프로세스를 오버레이를 통해 라우팅합니다:

local funcs = require("funcs")

local caller, err = funcs.new():with_options({ network = "app.net:proxy" })
if err then return nil, err end
local result, call_err = caller:call("app.api:fetch_data")
if call_err then return nil, call_err end
local process = require("process")

local pid, err = process.with_options({ network = "app.net:tailnet" })
    :spawn_monitored("app.workers:probe", "app:processes")
if err then return nil, err end

사용자 지정 옵션으로 프로세스 spawner를 구성하려면 context에 대한 process.context 권한도 필요합니다. 거부되면 spawner가 반환되기 전에 Lua 오류가 발생하며, 선택한 네트워크 ID에 대해서는 network.select가 별도로 검사됩니다.

http_client 모듈은 호출별 옵션에서 overlay_network 키를 통해 동일한 오버레이 선택을 받습니다.

상속

오버레이 선택은 호출 스택을 통해 전파됩니다. funcs.new():with_options({network=...})로 호출된 함수는 새 경계가 다른 오버레이를 선택하지 않는 한 내부 다이얼, 중첩 호출, 생성된 프로세스에 해당 오버레이를 사용합니다. 빈 network 옵션은 "재정의 없음"을 의미하며 상속된 오버레이나 애플리케이션 기본값을 지우지 않습니다.

함수 호출에서는 네트워크를 선택하기 전에 런타임 옵션이 함수 엔트리의 meta.options를 재정의합니다. 새 함수 또는 프로세스 경계에서는 비어 있지 않은 options.network가 먼저 선택됩니다. 없으면 설정된 network_service.default_network가 선택되고, 둘 다 없으면 상속된 프레임 선택이 유지됩니다. 선택한 ID는 이미 등록되어 있어야 합니다. 알 수 없는 ID는 호스트 네트워크로 폴백하지 않고 호출이나 spawn을 실패시킵니다.

앰비언트 상속은 후손 자체의 network.select 거부 규칙을 우회합니다. Lua 경계에서의 명시적 선택만 게이트됩니다.

앱 구성

오버레이 드라이버는 .wippy.yamlnetwork_service: 블록에서 앱 전역 설정을 읽습니다:

network_service:
  state_dir: .wippy/net          # base dir for driver state (Tailscale keys, etc.)
  default_network: app.net:tailnet  # overlay applied when no call sets one
필드 기본값 설명
state_dir .wippy/net 드라이버 상태 디렉터리. 상대 경로는 부트 config 디렉터리를 기준으로 해석됩니다.
default_network 옵션을 통해 자체 네트워크를 설정하지 않는 모든 작업 또는 프로세스에 적용되는 오버레이의 레지스트리 ID.

Raw 다이얼

오버레이 선택은 Lua 경계에만 국한되지 않습니다. 런타임 네트워크 서비스를 통한 다이얼 — WASM socket 호스트wasi:sockets 디스패처 — 은 프레임에서 오버레이를 읽어 그 경로로 라우팅합니다. 오버레이가 with_options로 설정되었든, 엔트리의 meta.options.network로 설정되었든, network_service.default_network로 설정되었든 동일합니다.

프라이빗 IP 게이트는 이 경로에서 다르게 동작합니다. 직접 다이얼은 대상을 해석하고 그 결과 나온 모든 주소를 socket.private_ip에 대해 검사합니다. 오버레이가 선택된 경우에는 대상에 들어 있는 리터럴 IP 주소만 검사합니다. 호스트 이름은 오버레이가 해석하도록 넘겨지므로 로컬 리졸버는 전혀 사용되지 않고, 그것이 반환했을 값에 대한 검사도 이루어지지 않습니다.

오버레이가 선택되었지만 컨텍스트에 네트워크 레지스트리가 없으면 다이얼은 network "<id>" selected without a network registry로 실패합니다.

오버레이 업데이트

오버레이 엔트리는 레지스트리 업데이트 시 교체됩니다. 드라이버는 전환 전에 교체 서비스를 빌드하며, 생성에 실패하면 기존 오버레이가 계속 실행됩니다. 성공한 교체는 새 조회에 대해 원자적이며 이후 이전 서비스가 닫힙니다. 따라서 이전 서비스를 이미 사용 중인 작업은 해당 종료를 관찰할 수 있습니다.

권한

액션 리소스 설명
network.select 네트워크 Registry ID funcs.call, process.spawn, http_client에서 명시적 오버레이 선택
network.bind 네트워크 Registry ID 오버레이를 통해 http.service 리스너를 바인딩(network: 필드)
socket.connect host:port 네트워크 서비스를 통한 모든 아웃바운드 다이얼
socket.listen host:port 네트워크 서비스를 통한 TCP 리스너 또는 UDP 소켓 바인딩
socket.resolve 호스트 이름 네트워크 서비스를 통한 DNS 해석
socket.private_ip IP 주소 루프백, 프라이빗, 링크 로컬 또는 unspecified 주소에 대한 접근

범위에서 network.select를 거부하여 그 안의 코드가 명시적으로 오버레이를 선택하지 못하도록 합니다. 상속된 오버레이는 영향을 받지 않습니다 — 호출자에서 권한이 부여되었습니다. network.bindnetwork: 오버레이가 설정된 서버가 리스너를 시작할 때 검사됩니다.

socket.* 권한은 네트워크 서비스 자체가 검사합니다. socket.connect, socket.listen, socket.resolve는 오버레이 라우팅 이전에 검사되므로 클리어넷 트래픽과 오버레이 트래픽에 동일하게 적용됩니다. socket.private_ip는 오버레이가 선택되면 Raw 다이얼에서 설명한 대로 리터럴 주소로 범위가 좁혀집니다.

참고