From c9062e7d1a1d917f618b71ac3810b4f3e396ab0d Mon Sep 17 00:00:00 2001 From: cbdev Date: Fri, 7 Jun 2019 19:20:42 +0200 Subject: Main readme and config module --- README.md | 109 +++++++++++++++++++++++++++++++++++++++++++++++++ config.c | 74 +++++++++++++++++++++++++++++++++ config.h | 8 ++++ makefile | 2 +- plugins/backend_file.c | 22 +++++----- websocksy.c | 68 +++--------------------------- 6 files changed, 210 insertions(+), 73 deletions(-) create mode 100644 README.md create mode 100644 config.c create mode 100644 config.h diff --git a/README.md b/README.md new file mode 100644 index 0000000..10a2f73 --- /dev/null +++ b/README.md @@ -0,0 +1,109 @@ +# websocksy + +`websocksy` is a highly configurable [WebSocket (RFC6455)](https://tools.ietf.org/html/rfc6455) to 'normal' networking transport (TCP/UDP) bridge. +It is written in C and supports pluggable modules for bridge peer selection modules (for dynamic bridging) and stream framing. + +Connecting WebSockets to 'real' sockets may seem like an easy task at first, but the WebSocket protocol has some fundamental differences to TCP and UDP. + +### Framing + +Data sent over WebSockets is explicitly framed - you get told how much data to expect for any one package. This is similar to UDP, which operates on Datagrams, +which are always received as one full message and carry an integrated length field. + +In contrast to that, TCP operates on a 'stream' basis, where any message boundaries need to be established by an upper layer protocol, and any messages sent +may be fragmented into multiple receive operations. + +Bridging data _from_ the WebSocket _to_ the network peer is thus not the problem - one can simply write out any complete message frame received. +For TCP, the other direction needs some kind of indication when to send the currently buffered data from the stream as one message to the WebSocket client. + +### Frame typing + +WebSocket frames contain an `opcode`, which indicates the type of data the frame contains, for example `binary`, `text`, or `ping` frames. + +Normal sockets only transfer bytes of data as payload, without any indication or information on what they signify - that is dependent on the upper layer protocols +that use these transport protocols. + +### Contextual information + +WebSockets carry in their connection establishment additional metadata, such as HTTP headers, an endpoint address and a list of supported subprotocols, +from which the server may select one it supports. + +Normal sockets only differentiate connections by a tuple consisting of source and destination addresses and ports, with the destination port number +being the primary discriminator between services. + +## Dynamic proxying + +To allow `websocksy` to connect any protocol to a WebSocket endpoint despite these differences, there are two avenues of extensibility. + +### Peer discovery backend + +Peer discovery backends map the metadata from a WebSocket connection, such as HTTP headers (e.g. Cookies), the connection endpoint and any indicated +subprotocols to a peer address naming a 'normal' socket. + +Backends can be loaded from shared libraries and may use any facilities available to them in order to find a peer - for example they may query a database +or [scan a file](plugins/backend_file.md) based on the supplied metadata. This allows the creation of dynamically configured bridge connections. + +Currently, the following peer address schemes are supported: + +* `tcp://[:]` - TCP client +* `udp://[:]` - UDP client +* `unix://` - Unix socket, stream mode +* `unix-dgram://` - Unix socket, datagram mode + +The default backend integrated into `websocksy` returns the same (configurable) peer for any connection. + +### Peer stream framing + +To solve the problem of framing the data stream from TCP peers and selecting the correct WebSocket frame type, `websocksy` uses "framing functions", +which can be loaded as plugins from shared objects. These are called when data was received from the network peer to decide if and how many bytes are +to be framed and sent to the WebSocket, and with what frame type. + +The framing function to be used for a connection is returned dynamically by the peer discovery backend. The backend may select from a library of different +framing functions (both built in and loaded from plugins). + +`websocksy` comes with the following framing functions built in: + +* `auto`: Send all data immediately, with the `text` type if the content was detected as valid UTF-8 string, otherwise use a `binary` frame +* `binary`: Send all data immediately as a `binary` frame + +# Configuration / Usage + +`websocksy` may either be configured by passing command line arguments or by specifying a configuration file to be read. + +The listen port may either be exposed to incoming WebSocket clients directly or via a proxying webserver such as nginx. + +### Command line arguments + +* `-p `: Set the listen port for incoming WebSocket connections +* `-l `: Set the host for listening for incoming WebSocket connections +* `-b `: Select external backend +* `-c