Epoxy WISP proxy for Wasmer
This directory is a ready-to-run Wasmer package for the WASIX Epoxy server.
Its package manifest mounts config/config.toml at /etc/epoxy/config.toml
and passes that path to the wisp-proxy entrypoint as a WASI argument.
Run the published proxy locally:
wasmer run wasmer/wisp-server --net
To build and run the package from source instead, use:
cargo install cargo-wasix wasm-tools
./wasmer/build.sh
wasmer run ./wasmer --net
Ensure Cargo's binary directory (normally ~/.cargo/bin) is on PATH.
Alternatively, set WASM_TOOLS to the path of an installed wasm-tools binary.
The build disables the wide-arithmetic compiler target feature and validates
the final optimized module with wide arithmetic disabled before replacing the
packaged Wasm. This keeps the server compatible with Wasmer's V8 runtime and
avoids the compilation failure reported in
wasmerio/wasmer#7059.
No --wide-arithmetic runtime flag is required.
To verify the package locally with V8 (including HTTP, WISP v1/v2, simultaneous streams, and certificate-verified TLS carrying 256 KiB responses), run:
uv run wasmer/test-wasix.py --engine v8
uv run wasmer/test-wasix.py --engine cranelift
These checks start temporary servers bound to loopback, verify the packaged
loopback/multicast/UDP restrictions, and use separate test-only environment
overrides to proxy local HTTP/TLS fixtures. Logs are saved under
.wasmer-build/smoke-<engine>/. Add --external to also test public DNS and
HTTP/HTTPS proxying to example.com; that check needs internet access.
The configured server listens at 0.0.0.0:4000. Ordinary requests to /
show the connection page; WebSocket upgrades on the same URL enter WISP.
Individual settings can still be overridden with the supported WISP_*
environment variables. For example:
wasmer run wasmer/wisp-server --net \
--env WISP_AUTOCONFIGURE=https://app.example.com/wisp-autoconfigure
Available variables are:
WISP_SERVER_BIND,WISP_SERVER_RUNTIME,WISP_SERVER_TRANSPORT,WISP_SERVER_LOG_LEVEL,WISP_AUTOCONFIGUREWISP_PROTOCOL_ALLOW_WSPROXY,WISP_PROTOCOL_BUFFER_SIZE,WISP_PROTOCOL_PREFIX,WISP_PROTOCOL_V2,WISP_PROTOCOL_EXTENSIONSWISP_STREAM_TCP_NODELAY,WISP_STREAM_BUFFER_SIZE,WISP_STREAM_ALLOW_UDP,WISP_STREAM_ALLOW_WSPROXY_UDP,WISP_STREAM_ALLOW_DIRECT_IP,WISP_STREAM_ALLOW_LOOPBACK,WISP_STREAM_ALLOW_MULTICAST,WISP_STREAM_ALLOW_GLOBAL,WISP_STREAM_ALLOW_NON_GLOBAL,WISP_STREAM_ALLOW_PORTS
Boolean values accept true or false; extension and port lists are
comma-separated. Ports accept either one port (443) or an inclusive range
(8000-9000). Environment values overlay the packaged configuration.
Cross-origin browser autoconfiguration
Browsers do not allow one unrelated tab to directly address another tab on a
different origin. WISP_AUTOCONFIGURE therefore identifies a bridge
page you control, such as https://app.example.com/wisp-autoconfigure. The
WISP landing page shows an Automatically connect to … link. Clicking it
navigates the tab to that URL with the WISP endpoint in the endpoint query
parameter. Requiring a click keeps the landing page stable for screenshots and
previews. Making the bridge top-level is important because modern browsers
partition cross-tab channels used by third-party iframes.
The bridge can relay the query parameter to already-open tabs on its own origin:
const channel = new BroadcastChannel("wisp-autoconfigure");
const endpoint = new URL(location.href).searchParams.get("endpoint");
channel.postMessage({ type: "wisp-autoconfigure", version: 1, endpoint });
The existing application tab listens on the same channel:
const channel = new BroadcastChannel("wisp-autoconfigure");
channel.addEventListener("message", ({ data }) => {
if (data?.type === "wisp-autoconfigure" && data.version === 1) {
configureWisp(data.endpoint);
}
});
The packaged policy blocks UDP, loopback, multicast, and non-global targets.
Its allow_ports list permits TCP ports 80 and 443 even when a port is in
block_ports; it does not by itself block other ports. Configure block_ports
if you need a strict port restriction. It permits direct global IP addresses because
browser WASIX clients connect to the address selected by their DNS resolver.
Add WISP authentication or enforce access at the deployment edge before exposing
it publicly; an unauthenticated WISP endpoint is still an outbound proxy.