Skip to content

Commit

Permalink
Merge pull request #133 from ktock/followup
Browse files Browse the repository at this point in the history
Following up for  #123
  • Loading branch information
ktock authored Sep 14, 2023
2 parents 5f93ee2 + ff03e50 commit b3e540b
Show file tree
Hide file tree
Showing 17 changed files with 122 additions and 119 deletions.
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -115,8 +115,8 @@ $ docker run --rm -p 8080:80 \

You can run the container on browser with several types of configurations:

- `localhost:8080/?net=browser`: Container with networking. [Network stack](./extras/c2w-net-proxy/) based on [`gvisor-tap-vsock`](https://github.com/containers/gvisor-tap-vsock) runs on browser and forwards HTTP/HTTPS packets using the browser's Fetch API. The set of accesible sites is restricted by the browser configuration (e.g. CORS restriction). See also [`./examples/networking/fetch`](./examples/networking/fetch/) for detalis.
- `localhost:8080/?net=delegate=ws://localhost:8888`: Container with networking. You need to run [user-space network stack](./cmd/c2w-net/) based on [`gvisor-tap-vsock`](https://github.com/containers/gvisor-tap-vsock) on the host (outside of browser). It forwards all packets received from the browser over WebSocket. See also [`./examples/networking/websocket`](./examples/networking/websocket/) for detalis and configuration. (tested only on Linux)
- `localhost:8080/?net=browser`: Container with networking. [Network stack `c2w-net`](./extras/c2w-net-proxy/) implemented based on [`gvisor-tap-vsock`](https://github.com/containers/gvisor-tap-vsock) runs on browser and forwards HTTP/HTTPS packets using the browser's Fetch API. The set of accesible sites is restricted by the browser configuration (e.g. CORS restriction). See also [`./examples/networking/fetch`](./examples/networking/fetch/) for detalis.
- `localhost:8080/?net=delegate=ws://localhost:8888`: Container with networking. You need to run [user-space network stack `c2w-net`](./cmd/c2w-net/) implemented based on [`gvisor-tap-vsock`](https://github.com/containers/gvisor-tap-vsock) on the host (outside of browser). It forwards all packets received from the browser over WebSocket. See also [`./examples/networking/websocket`](./examples/networking/websocket/) for detalis and configuration. (tested only on Linux)
- `localhost:8080`: Container without networking.

#### emscripten on browser
Expand Down Expand Up @@ -147,7 +147,7 @@ You can run the container on browser via `localhost:8080`.

> NOTE: It can take some time to load and start the container.
Networking can also be enabled using the [user-space network stack](./cmd/c2w-net/) based on [`gvisor-tap-vsock`](https://github.com/containers/gvisor-tap-vsock) serving over WebSocket on the host (outside of browser).
Networking can also be enabled using the [user-space network stack `c2w-net`](./cmd/c2w-net/) implemented based on [`gvisor-tap-vsock`](https://github.com/containers/gvisor-tap-vsock) serving over WebSocket on the host (outside of browser).
See also [`./examples/networking/websocket`](./examples/networking/websocket/) for detalis.

## Getting Started
Expand Down
6 changes: 3 additions & 3 deletions cmd/c2w-net/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ func main() {
if len(args) < 1 {
panic("specify args")
}
qemuAddr := args[0]
socketAddr := args[0]
forwards := make(map[string]string)
for _, p := range portFlags {
parts := strings.Split(p, ":")
Expand Down Expand Up @@ -109,12 +109,12 @@ func main() {
fmt.Fprintf(os.Stderr, "forwarding finished: %v\n", err)
}
}))
if err := http.ListenAndServe(qemuAddr, nil); err != nil {
if err := http.ListenAndServe(socketAddr, nil); err != nil {
panic(err)
}
return
}
conn, err := net.Dial("tcp", qemuAddr)
conn, err := net.Dial("tcp", socketAddr)
if err != nil {
panic(err)
}
Expand Down
2 changes: 1 addition & 1 deletion examples/emscripten/htdocs/module.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ var Module = {};

var netParam = getNetParam();
if (netParam && (netParam.mode == 'delegate')) {
Module['arguments'] = ['--net', 'qemu', '--mac', genmac()];
Module['arguments'] = ['--net', 'socket', '--mac', genmac()];
Module['websocket'] = {
'url': netParam.param
};
Expand Down
8 changes: 4 additions & 4 deletions examples/networking/fetch/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,11 @@ The entire network stack runs on browser so this doesn't require network stack d
- pros: No need to run network stack daemon on the host. Networking is done based on browser's Fetch API and follows its security configuration including CORS restriction.
- cons: Container can send only HTTP/HTTPS packets to outside of the browser. And the set of accesible HTTP/HTTPS sites is limited by the browser's security rule (e.g. limited CORS).

We use [`gvisor-tap-vsock`](https://github.com/containers/gvisor-tap-vsock) as the network stack written in Go.
We provide the customized version of the network stack [`c2w-net-proxy`](../../../extras/c2w-net-proxy) for container-on-browser use-case.
This is compiled to WASM and runs on browser.
We provide the network stack [`c2w-net-proxy`](../../../extras/c2w-net-proxy) implemented based on [`gvisor-tap-vsock`](https://github.com/containers/gvisor-tap-vsock).
This is written in Go and compiled to WASM and runs on browser.

`c2w-net-proxy` running on browser provides HTTP/HTTPS proxy for the container.
The proxy runs on top of `gvisor-tap-vsock`'s network stack that receives packets from the container.
The proxy runs on top of the network stack (running on browser) that receives packets from the container.
`c2w-net-proxy` forwards HTTP/HTTPS requests using the browser's `fetch` API so it doesn't require network stack daemon outside of the browser.

For HTTPS, the proxy teminates the TLS connection from the contaienr with its own certificate and re-encrypt the connection to the destination using the Fetch API.
Expand All @@ -32,6 +31,7 @@ In [our example JS wrapper for container](../../wasi-browser/), by defualt, the

- Containers can't access to sites not allowing CORS access. For example, we haven't find apt mirrors accessible from browser so the container can't run `apt-get`. We expect more sites will allow CORS access.
- The proxy supports only HTTP/HTTPS and the implementation isn't mature. So it's possible that some HTTP networking fails on some cases. We'll work on support for more features.
- The proxy and containers don't have the control over [Forbidden headers](https://developer.mozilla.org/en-US/docs/Glossary/Forbidden_header_name) that are controlled by the browser.
- Only chrome is our tested browser. The set of accesible sites might be different among browsers and the configurations.
- WASI-on-browser container is only supported. Emscripten support is the future work.

Expand Down
16 changes: 8 additions & 8 deletions examples/networking/wasi/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,19 @@

Networking on WASI runtimes is possible by relying on the network stack running on the host (outside of the WASI runtime).

We use [`gvisor-tap-vsock`](https://github.com/containers/gvisor-tap-vsock) as the user-space network stack running on the host.
We provide a wrapper command [`c2w-net`](../../../cmd/c2w-net/) for container-on-WASI-runtime use-case.
We provide [`c2w-net`](../../../cmd/c2w-net/) as the user-space network stack running on the host.
This is implemented based on [`gvisor-tap-vsock`](https://github.com/containers/gvisor-tap-vsock).

The WASM image converted from the container can be configured to expose packets sent from the container via WASI's socket (`sock_*` API).
WASI runtime binds the socket on a TCP port (e.g. using wasmtime's `--tcplisten` flag and wazero's [`WithTCPListener`](https://github.com/tetratelabs/wazero/blob/405a5c9daca906cc8f52ee13e16511f44ae79557/experimental/sock/sock.go#L31) option).
`c2w-net` running on the host connects to that port and forwards packets sent to/from the container.

The WASM image converted from the container has `--net` flag that enables this networking feature.
`--net=qemu` is the only supported mode which sends packets to `gvisor-tap-vsock` (wrapped by `c2w-net`) using [QEMU's forwarding protocol](https://github.com/containers/gvisor-tap-vsock#run-with-qemu-linux-or-macos).
`--net=socket` is the only supported mode which sends packets to `gvisor-tap-vsock` (wrapped by `c2w-net`) using [QEMU's forwarding protocol](https://github.com/containers/gvisor-tap-vsock#run-with-qemu-linux-or-macos).

> NOTE1: By default, the WASM image tries to establish connection with `c2w-net` via WASI's fd=3.
> However WASI runtimes might use larger fd when directory sharing is enabled.
> In that case, `--net=qemu=listenfd=<num>` flag can be used for configuring the WASM image to use the correct socket fd.
> In that case, `--net=socket=listenfd=<num>` flag can be used for configuring the WASM image to use the correct socket fd.
> NOTE2: This feature is tested only on Linux.
Expand Down Expand Up @@ -45,7 +45,7 @@ $ c2w alpine:3.18 /tmp/out/out.wasm
Then launch it on wasmtime with enabling networking.

```console
$ c2w-net --invoke /tmp/out/out.wasm --net=qemu sh
$ c2w-net --invoke /tmp/out/out.wasm --net=socket sh
connecting to NW...
INFO[0001] new connection from 127.0.0.1:1234 to 127.0.0.1:50470
/ # apk update && apk add --no-progress figlet
Expand Down Expand Up @@ -77,7 +77,7 @@ The following example launches httpd server listening on `localhost:8000`.

```
$ c2w httpd /tmp/out/httpd.wasm
$ c2w-net --invoke -p localhost:8000:80 /tmp/out/httpd.wasm --net=qemu
$ c2w-net --invoke -p localhost:8000:80 /tmp/out/httpd.wasm --net=socket
```

> It might takes several seconds to the server becoming up-and-running.
Expand Down Expand Up @@ -107,7 +107,7 @@ Then, it can run on wazero with networking support:
```
$ ( cd ./tests/wazero && go build -o ../../out/wazero-test . )
$ ./out/wazero-test -net /tmp/out/out.wasm --net=qemu sh
$ ./out/wazero-test -net /tmp/out/out.wasm --net=socket sh
connecting to NW...
INFO[0001] new connection from 127.0.0.1:1234 to 127.0.0.1:53666
/ # apk update && apk add --no-progress figlet
Expand Down Expand Up @@ -137,7 +137,7 @@ The following example launches httpd server listening on `localhost:8000`.

```
$ c2w httpd /tmp/out/httpd.wasm
$ ./out/wazero-test -net -p localhost:8000:80 /tmp/out/httpd.wasm --net=qemu
$ ./out/wazero-test -net -p localhost:8000:80 /tmp/out/httpd.wasm --net=socket
```

> It might takes several seconds to the server becoming up-and-running.
Expand Down
4 changes: 2 additions & 2 deletions examples/networking/websocket/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ This example relies on the network stack running on the host (outside of the bro
- pros: Container can access to anywhere accesible from the network stack daemon running on the host.
- cons: The network stack daemon needs to run on the machine and forward packets received over WebSocket.

We use [`gvisor-tap-vsock`](https://github.com/containers/gvisor-tap-vsock) as the user-space network stack running on the host.
We provide a wrapper command [`c2w-net`](../../../cmd/c2w-net/) for container-on-wasm use-case.
We provide [`c2w-net`](../../../cmd/c2w-net/) as the user-space network stack running on the host.
This is implemented based on [`gvisor-tap-vsock`](https://github.com/containers/gvisor-tap-vsock).

`c2w-net` exposes an WebSocket port and it forwards all packets received from that WebSocket.
The container running on browser can connect to that WebSocket and pass all packets there and let `c2w-net` forward them on the host.
Expand Down
3 changes: 3 additions & 0 deletions examples/wasi-browser/htdocs/stack.js
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,9 @@ function connect(name, shared, conn, certbuf) {
var reqObj = JSON.parse(new TextDecoder().decode(req_.req));
reqObj.mode = "cors";
reqObj.credentials = "omit";
if (reqObj.headers && reqObj.headers["User-Agent"] != "") {
delete reqObj.headers["User-Agent"]; // Browser will add its own value.
}
var reqID = getID();
if (reqID < 0) {
console.log(name + ":" + "failed to get id");
Expand Down
4 changes: 2 additions & 2 deletions examples/wasi-browser/htdocs/worker.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ onmessage = (msg) => {
resp['arrayBuffer']().then((wasm) => {
if (netParam) {
if (netParam.mode == 'delegate') {
args = ['arg0', '--net=qemu', '--mac', genmac()];
args = ['arg0', '--net=socket', '--mac', genmac()];
} else if (netParam.mode == 'browser') {
recvCert().then((cert) => {
var certDir = getCertDir(cert);
Expand All @@ -31,7 +31,7 @@ onmessage = (msg) => {
undefined, // 5: accepted socket fd (multi-connection is unsupported)
// 6...: used by wasi shim
];
args = ['arg0', '--net=qemu=listenfd=4', '--mac', genmac()];
args = ['arg0', '--net=socket=listenfd=4', '--mac', genmac()];
env = [
"SSL_CERT_FILE=/.wasmenv/proxy.crt",
"https_proxy=http://192.168.127.253:80",
Expand Down
2 changes: 1 addition & 1 deletion patches/bochs/Bochs/bochs/iodev/devices.cc
Original file line number Diff line number Diff line change
Expand Up @@ -363,7 +363,7 @@ void bx_devices_c::init(BX_MEM_C *newmem)
PLUG_load_plugin(mapdirVirtio9p, PLUGTYPE_STANDARD);
PLUG_load_plugin(packVirtio9p, PLUGTYPE_STANDARD);
PLUG_load_plugin(stdioVirtioConsole, PLUGTYPE_STANDARD);
PLUG_load_plugin(qemuVirtioNet, PLUGTYPE_STANDARD);
PLUG_load_plugin(socketVirtioNet, PLUGTYPE_STANDARD);
#endif
bx_init_plugins();

Expand Down
8 changes: 4 additions & 4 deletions patches/bochs/Bochs/bochs/main.cc
Original file line number Diff line number Diff line change
Expand Up @@ -468,7 +468,7 @@ void print_usage(void)
"OPTIONS:\n"
" -entrypoint <command>: entrypoint command. (default: entrypoint specified in the image config)\n"
" -no-stdin : disable stdin. (default: false)\n"
" -net <mode> : enable networking with the specified mode (default: disabled. supported mode: \"qemu\")\n"
" -net <mode> : enable networking with the specified mode (default: disabled. supported mode: \"socket\")\n"
" -mac <mac address> : use a custom mac address for the VM\n"
"\n"
"This tool is based on Bochs emulator.\n"
Expand Down Expand Up @@ -568,9 +568,9 @@ int init_vm(int argc, char **argv, FSVirtFile *info)
#endif

if (net != NULL) {
if (!strncmp(net, "qemu", 4)) {
if (start_qemu_net(net) != 0) {
fprintf(stderr, "failed to wait qemu net");
if (!strncmp(net, "socket", 6)) {
if (start_socket_net(net) != 0) {
fprintf(stderr, "failed to wait socket net");
exit(1);
}
}
Expand Down
2 changes: 1 addition & 1 deletion patches/bochs/Bochs/bochs/plugin.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1065,7 +1065,7 @@ plugin_t bx_builtin_plugins[] = {
BUILTIN_OPTPCI_PLUGIN_ENTRY(mapdirVirtio9p),
BUILTIN_OPTPCI_PLUGIN_ENTRY(packVirtio9p),
BUILTIN_OPTPCI_PLUGIN_ENTRY(stdioVirtioConsole),
BUILTIN_OPTPCI_PLUGIN_ENTRY(qemuVirtioNet),
BUILTIN_OPTPCI_PLUGIN_ENTRY(socketVirtioNet),
#if BX_SUPPORT_SOUNDLOW
BUILTIN_SND_PLUGIN_ENTRY(dummy),
BUILTIN_SND_PLUGIN_ENTRY(file),
Expand Down
4 changes: 2 additions & 2 deletions patches/bochs/Bochs/bochs/plugin.h
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ extern "C" {
#define BX_PLUGIN_MAPDIR_VIRTIO_9P "mapdirVirtio9p"
#define BX_PLUGIN_PACK_VIRTIO_9P "packVirtio9p"
#define BX_PLUGIN_STDIO_VIRTIO_CONSOLE "stdioVirtioConsole"
#define BX_PLUGIN_QEMU_VIRTIO_NET "qemuVirtioNet"
#define BX_PLUGIN_SOCKET_VIRTIO_NET "socketVirtioNet"

#define BX_REGISTER_DEVICE_DEVMODEL(a,b,c,d) pluginRegisterDeviceDevmodel(a,b,c,d)
#define BX_UNREGISTER_DEVICE_DEVMODEL(a,b) pluginUnregisterDeviceDevmodel(a,b)
Expand Down Expand Up @@ -496,7 +496,7 @@ PLUGIN_ENTRY_FOR_IMG_MODULE(vvfat);
PLUGIN_ENTRY_FOR_MODULE(mapdirVirtio9p);
PLUGIN_ENTRY_FOR_MODULE(packVirtio9p);
PLUGIN_ENTRY_FOR_MODULE(stdioVirtioConsole);
PLUGIN_ENTRY_FOR_MODULE(qemuVirtioNet);
PLUGIN_ENTRY_FOR_MODULE(socketVirtioNet);
#endif

#ifdef __cplusplus
Expand Down
Loading

0 comments on commit b3e540b

Please sign in to comment.