Skip to main content
Nullspace does not ship a first-class proxy product surface in private beta. You can still build a template that starts a Shadowsocks client and points your workload at the local SOCKS proxy.

Local SOCKS proxy

from nullspace import Sandbox, Template, wait_for_port

builder = (
    Template.from_ubuntu_image("22.04")
    .apt_install(["shadowsocks-libev", "curl", "ca-certificates"])
    .set_runtime_envs(
        Sandbox.enable_tunnel(
            "proxy.example.com",
            "change-me",
            port=8388,
            method="aes-256-gcm",
            mode="socks5",
        )
    )
    .set_start_cmd(
        "ss-local -s $SS_SERVER -p $SS_SERVER_PORT "
        "-k $SS_PASSWORD -m $SS_METHOD -b 127.0.0.1 -l 1080",
        readiness=wait_for_port(1080),
    )
)
Applications can then use socks5h://127.0.0.1:1080:
sandbox = Sandbox.create(template="my-proxy-template")
try:
    result = sandbox.commands.run(
        "curl --socks5-hostname 127.0.0.1:1080 https://ifconfig.me",
        shell=True,
    )
    print(result.stdout.strip())
finally:
    sandbox.kill()

Transparent proxy variant

Transparent egress requires root networking privileges inside the guest and is best kept to dedicated templates. Use ss-redir and explicit iptables rules:
builder = (
    Template.from_ubuntu_image("22.04")
    .apt_install(["shadowsocks-libev", "iptables", "ca-certificates"])
    .set_runtime_envs(Sandbox.enable_tunnel("proxy.example.com", "change-me"))
    .set_start_cmd(
        "ss-redir -s $SS_SERVER -p $SS_SERVER_PORT -k $SS_PASSWORD "
        "-m $SS_METHOD -b 127.0.0.1 -l 1081 & "
        "iptables -t nat -A OUTPUT -p tcp -m owner ! --uid-owner root "
        "-j REDIRECT --to-ports 1081 && tail -f /dev/null"
    )
)
Prefer the local SOCKS variant unless you control the full template and have a clear reason to intercept all TCP egress. Concept: Create. API reference: buildTemplate, createSandbox, and execCommand.