Skip to content

refraction-networking/water

Repository files navigation

W.A.T.E.R.: WebAssembly Transport Executables Runtime

Apache-2.0 FOSSA CI Go Doc

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 watm for examples and helper libraries interfacing Pluggable Transports-like interfaces. Official Go compiler is currently not supported until further notice.

You can contact one of developers personally via gaukas.wang@colorado.edu, or simply opening an issue.

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

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.

BibTeX
@inproceedings{water-foci24,
    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},
}

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

License

This project is licensed under Apache 2.0 license.

Contents

This repo contains a Go package water, which implements the runtime library used to interact with .wasm WebAssembly Transport Modules(WATM).

Usage

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.

Versioning

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

Customizable Version

TODO: add documentations for customizable WATM version.

Components

Dialer

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("./examples/v0/plain/plain.wasm")

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

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

Listener

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 accpt 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("./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()
		handleConn(conn)
	}

	// ...

Relay

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 connecions 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 connectons.

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

	wasm, _ := os.ReadFile("./examples/v0/plain/plain.wasm")

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

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

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

Example

See examples for example usecase of W.A.T.E.R. API, including Dialer, Listener and Relay.

Submodules

watm has its own licensing policy, please refer to 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:

Target Compiles? Tests Pass?
linux/amd64
linux/arm64
linux/riscv64
macos/amd64
macos/arm64
windows/amd64
windows/arm64
others

Acknowledgments

  • We thank GitHub.com for providing GitHub Actions runners for all targets below:

  • We thank FlyCI.net for providing GitHub Actions runners on macos/arm64 (Apple M1) in the past. (We switched to GitHub's macos-14 runner as of Jan 31 2024)

We are currently actively looking for a CI provider for more target platforms. Please reach out and let us know if you would like to help.