|
4 years ago | |
---|---|---|
wsfwd | 4 years ago | |
.gitignore | 4 years ago | |
Makefile | 4 years ago | |
README.md | 4 years ago | |
requirements.txt | 4 years ago | |
setup.py | 4 years ago |
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.
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’ }
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.
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/