Skip to content

Instantly share code, notes, and snippets.

@rfdonnelly
Last active March 20, 2024 23:44
Show Gist options
  • Save rfdonnelly/451fa9187f0ebc678a5a3f110c3771cd to your computer and use it in GitHub Desktop.
Save rfdonnelly/451fa9187f0ebc678a5a3f110c3771cd to your computer and use it in GitHub Desktop.
Websocket to UDP

WebSocket to UDP

The following allows a client side web application to communicate with a UDP endpoint.

We create a WebSocket to UDP bridge using websockify and socat.

The connection looks like:

┌────────────────────────┐      ┌──────────────────────────┐      ┌────────────────────┐      ┌────────────────┐
│                        │      │                          │      │                    │      │                │
│                        │      │                          │      │                    │      │                │
│      Web browser       │      │        websockify        │      │       socat        │      │                │
│                        ◄──────►                          ◄──────►                    ◄──────►  UDP endpoint  │
│  (WebSocket endpoint)  │      │  (WebSocket-TCP bridge)  │      │  (TCP-UDP bridge)  │      │                │
│                        │      │                          │      │                    │      │                │
│                        │      │                          │      │                    │      │                │
└────────────────────────┘      └──────────────────────────┘      └────────────────────┘      └────────────────┘

Install

sudo apt install websockify socat netcat

Setup

  1. Start websockify. Listen on port 40000. Forward on port 40001.

    websockify 40000 localhost:40001
  2. Start socat. Listen for TCP traffic on port 40001. Forward UDP traffic on port 40002.

    socat tcp-listen:40001,fork udp:localhost:40002

One-way Example

  1. Start the UDP client. We’ll use netcat as a standin for our UDP client. Listen on port 40002.

    netcat -vvlup 40002
  2. Create a WebSocket and send a message. In the web browser Javascript console:

    let message = new Blob(["hello world\n"], { type: "text/plain" });
    let sock = new WebSocket("ws://localhost:40000", ['binary', 'base64']);
    sock.send(message);
    sock.close();

Two-way example

  1. Start the UDP client. We’ll use socat to echo the message back to the web browser.

    socat udp-listen:40002 exec:'/bin/cat'
  2. Create a WebSocket, a message handler, and send a message. In the web browser Javascript console:

    let message = new Blob(["hello world\n"], { type: "text/plain" });
    let sock = new WebSocket("ws://localhost:40000", ['binary', 'base64']);
    sock.onmessage = async (event) => { const text = await event.data.text(); console.log(text); }
    sock.send(message);
    sock.close();

Basic Terminal Server

  1. Start a UDP client that sends requests to /bin/sh and returns the output

    socat udp-listen:40002 exec:'/bin/sh'
  2. Create a WebSocket, a message handler, and send a message. In the web browser Javascript console:

    let sock = new WebSocket("ws://localhost:40000", ['binary', 'base64']);
    sock.onmessage = async (event) => { const text = await event.data.text(); console.log(text); }
    const send = async (text) => { const message = new Blob([text + "\n"], {type: "text/plain"}); await sock.send(message); }
    await send("uname -a");
    sock.close();
websocket-udp-term-server.mp4

Appendix A: Wireshark on WSL 2

Wireshark on Windows cannot capture traffic in WSL 2. To capture traffic in WSL 2, Wireshark must be run inside of WSL 2.

sudo apt install wireshark
sudo chmod +x /usr/bin/dumpcap
wireshark
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment