WebAssembly Transports & Executable Runtime (WATER) is a project that seeks to provide easily iterable and transferrable pluggable censorship circumvention transports. This involves a library supporting the design of transport modules (compiled to WASM) and client runtimes for running those modules in any language supporting current WASM standards (at the moment we have implemented support for Golang and Rust).

Check it out.


WATER-go provides a Go runtime for WebAssembly Transport Modules(WATM) as a pluggable application-layer transport protocol provider. It is designed to be highly portable and lightweight, allowing for rapidly deployable pluggable transports. While other pluggable transport implementations require a fresh client deployment (and app-store review) to update their protocol WATER allows dynamic delivery of new transports in real time over the network or out-of-band.

WATER wasm transport

To build a WATM in Go, please refer to refraction-networking/watm for examples and helper libraries interfacing Pluggable Transports-like interfaces. Official Go compiler is currently not supported until further notice.

The Rust implementation of the runtime library and information about writing, building, and using WebAssembly Transport Modules(WATM) from Rust can be found in refraction-networking/water-rs.

Be Water

Empty your mind, be formless, shapeless, like water. If you put water into a cup, it becomes the cup. You put water into a bottle and it becomes the bottle. You put it in a teapot, it becomes the teapot. Now, water can flow or it can crash. Be water, my friend.

– Bruce Lee


Based on WASI Snapshot Preview 1 (wasip1), currently W.A.T.E.R. provides a set of net-like APIs via Dialer, Listener and Relay.


W.A.T.E.R. is designed to be future-proof with the automated multi-version WebAssembly Transport Module(WATM) support. In order to minimize the size of compiled application binaries importing water, the support for each WATM version is implemented in separate sub-packages and by default none will be enabled. The developer MUST manually enable each version to be supported by importing the corresponding package:

import (
    // ...

    _ "github.com/refraction-networking/water/transport/v0"

    // ...

Otherwise, it is possible that the W.A.T.E.R. runtime cannot determine the version of the WATM and therefore fail to select the corresponding runtime:

panic: failed to listen: water: listener version not found

Components (in Golang)


A Dialer connects to a remote address and returns a net.Conn to the caller if the connection can be successfully established. The net.Conn then provides tunnelled read and write to the remote endpoint with the WebAssembly module wrapping / encrypting / transforming the traffic.

Dialer is used to encapsulate the caller’s connection into an outbound, transport-wrapped connection.

    wasm, _ := os.ReadFile("https://github.com/refraction-networking/water/tree/master/examples/v0/plain/plain.wasm")

    config := &water.Config{
        TransportModuleBin: wasm,

    dialer, _ := water.NewDialerWithContext(context.Background(), config)
    conn, _ := dialer.DialContext(context.Background(),"tcp", remoteAddr)
    // ...


A Listener listens on a local address for incoming connections which it Accept()s, returning a net.Conn for the caller to handle. The WebAssembly Module is responsible for the initial accept allowing it to implement both the server side handshake as well as any unwrap / decrypt /reform operations required to validate and re-assemble the stream. The net.Conn returned provides the normalized stream, and allows the caller to write back to the client with the WebAssembly module encoding / encrypting / transforming traffic to be obfuscated on the wire on the way to the remote client.

Listener is used to decapsulate incoming transport-wrapped connections for the caller to handle, managing the tunnel obfuscation once a connection is established.

    wasm, _ := os.ReadFile("https://github.com/refraction-networking/water/tree/master/examples/v0/plain/plain.wasm")

    config := &water.Config{
        TransportModuleBin: wasm,

    lis, _ := config.ListenContext(context.Background(), "tcp", localAddr)
    defer lis.Close()
    log.Printf("Listening on %s", lis.Addr().String())

    for {
        conn, err := lis.Accept()

    // ...


A Relay combines the role of Dialer and Listener. It listens on a local address Accept()-ing incoming connections and Dial()-ing the remote endpoints on establishment. The connections are tunneled through the WebAssembly Transport Module allowing the module to handshake, encode, transform, pad, etc. without any caller interaction. The internal Relay manages the incoming connections as well as the associated outgoing connections.

Relay is a managed many-to-many handler for incoming connections that uses the WebAssemble module to tunnel traffic.

    wasm, _ := os.ReadFile("https://github.com/refraction-networking/water/tree/master/examples/v0/plain/plain.wasm")

    config := &water.Config{
        TransportModuleBin: wasm,

    relay, _ := water.NewRelayWithContext(context.Background(), config)

    relay.ListenAndRelayTo("tcp", localAddr, "tcp", remoteAddr) // blocking


See refraction-networking/water/examples for example use cases of the W.A.T.E.R. API, including Dialer, Listener and Relay.


watm has its own licensing policy, please refer to refraction-networking/watm for more information.

Cross-platform Support

W.A.T.E.R. is designed to be cross-platform (and cross-architecture). Currently, it supports the following platforms:

TargetCompiles?Tests Pass?

Cite our work

If you quoted or used our work in your own project/paper/research, please cite our paper Just add WATER: WebAssembly-based Circumvention Transports, which is published in the proceedings of Free and Open Communications on the Internet (FOCI) in 2024 issue 1, pages 22-28.

    author = {Erik Chi and Gaukas Wang and J. Alex Halderman and Eric Wustrow and Jack Wampler},
    title = {Just add {WATER}: {WebAssembly}-based Circumvention Transports},
    booktitle = {Free and Open Communications on the Internet},
    publisher = {},
    year = {2024},
    url = {https://www.petsymposium.org/foci/2024/foci-2024-0003.pdf},