Python module for forwarding commands over WebSockets. Fully asyncio compatible.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
John-Mark Gurney 77f71985d4 add a bunch of doc strings.. still more to come, but discovered a 4 years ago
wsfwd add a bunch of doc strings.. still more to come, but discovered a 4 years ago
.gitignore add first cut of wsfwd, only implements auth.. rest to follow.. 4 years ago
Makefile add first cut of wsfwd, only implements auth.. rest to follow.. 4 years ago
README.md move the protocol spec to the README, and flesh it out more... 4 years ago
requirements.txt add first cut of wsfwd, only implements auth.. rest to follow.. 4 years ago
setup.py add first cut of wsfwd, only implements auth.. rest to follow.. 4 years ago

README.md

WSFWD

WSFWD is a protocol for authentication (optional) and forwarding command data over a WebSocket. This originally is for simple stdin and stdout forwarding, for running a program like sshd -i to bypass port blocking, or allow more custom routing and execution.

It is designed so that in the future, it could support forwarding stderr separately, but also out of band messages, such as window change information, so that a full tty could be forwarded over the connection.

Protocol

All WebSocket messages much be treated as binary. This is for simplicity and speed when doing large binary transfers. The format of the messages are:

The chan byte value determines the meaning of payload.

If chan byte is zero (aka 00), then the payload is a UTF-8 encoded JSON message that contains a command, for example, an authentication request or command to execute.

Other values for chan byte are dynamically allocated based upon the commands sent.

For commands, the JSON object MUST have a key of cmd, and the value is the command to execute. Each cmd that is sent MUST be acknowledged with an object that has a key of resp, and a value that is the same as the command. If the command fails, the response object MUST have a key of error, and the value MUST be a string containing an error message.

If the response to a command could be confused, it is expected that parts of command request be included in the response. In other cases, such as auth, it is expected that the auth message NOT be included, and that the response to a successful auth message is simply: { ‘resp’: ‘auth’ }

Typical command flow

The following is a typical command flow. Failure messages are included in-line for additional context.

Auth message (optional):

{ 'cmd': 'auth', 'auth': { 'bearer': <token> } }

Error message in case of invalid auth:

{ 'resp': 'auth', 'error': 'Invalid auth' }

Command to execute a program:

{ 'cmd': 'exec', 'args': [ ... ], 'stdin': <chan>, 'stdout': <chan> }

Error if unable to exec the requested program:

{ 'resp': 'exec', 'error': 'Unable to exec', ... }, 'args': [...], [...] }

Success:

{ 'resp': 'exec', 'args': [...], [...] }

Here, messages on the stdin/stdout channels are exchanged.

Close stdin or stdout or other channel:

{ 'cmd': 'chanclose', 'chan': <chan> }

Success:

{ 'resp': 'chanclose', 'chan': <chan> }

Once stdin is closed, the server side will wait for stdout to be closed by the program, send the proper chanclose command for it, and then wait for the program to exit, and return the exit code.

{ 'cmd': 'exit', 'code': <code> }

Currently not implemented, but if stdin is closed by the program, the server may send a chanclose preemptively. The server will discard any additional data, and it is an error to send additional data on the channel after the client responds w/ a resp: chanclose acknowledgment.

Additional Notes

These are the target client and server implementations that WSFWD is designed to work with. It should easily be able to be made to work with other implementations.

FastAPI uses starlette: https://www.starlette.io/websockets/

Client: https://github.com/aaugustin/websockets