websocat
Websocket proxy, socat-style
websocat 1.0.0-alpha
Vitaly "_Vi" Shukela <vi0oss@gmail.com>
Connection forwarder from/to web sockets to/from usual sockets, in style of socat
USAGE:
websocat [FLAGS] [OPTIONS] <s1> <s2>
FLAGS:
--dump-spec Instead of running, dump the specifiers representation to stdout
--exit-on-eof Close a data transfer direction if the other one reached EOF
-h, --help Prints help information
--long-help Show full help aboput specifiers and examples
--oneshot Serve only once
--udp-oneshot udp-listen: replies only one packet per client
-u, --unidirectional Inhibit copying data from right specifier to left
-U, --unidirectional-reverse Inhibit copying data from left specifier to right
--unlink Unlink listening UNIX socket before binding to it
-V, --version Prints version information
-t, --text Send text WebSocket messages instead of binary
OPTIONS:
--exec-args <exec_args>... Arguments for the `exec:` specifier. Must be the last option, everything
after it gets into the exec args list.
--protocol <websocket_protocol> Specify Sec-WebSocket-Protocol: header
--ws-c-uri <ws_c_uri> URI to use for ws-c: specifier [default: ws://0.0.0.0/]
ARGS:
<s1> First, listening/connecting specifier. See --long-help for info about specifiers.
<s2> Second, connecting specifier
Basic examples:
Connect stdin/stdout to a websocket:
websocat - ws://echo.websocket.org/
Listen websocket and redirect it to a TCP port:
websocat ws-l:127.0.0.1:8080 tcp:127.0.0.1:5678
See more examples with the --long-help option
Short list of specifiers (see --long-help):
ws:// wss:// - inetd: ws-listen: inetd-ws: tcp: tcp-l: ws-c:
autoreconnect: reuse: mirror: threadedstdio: clogged:
literal: literalreply: assert: udp-connect: open-async:
readfile: writefile: open-fd: unix-connect: unix-listen:
unix-dgram: abstract-connect: abstract-listen:
exec: sh-c:
It runs singlethreaded. There is old non-async threaded version in legacy
branch of releases prior to 0.5.
Specify listening part first, unless you want websocat to serve once (like in --oneshot
mode).
IPv6 supported, just use specifiers like ws-l:[::1]:4567
Web socket usage is not obligatory, you can use any specs on both sides.
If you want wss://
server, use socat or nginx in addition to websocat until this function is implemented properly.
Pre-built binaries for Linux (usual and musl), Windows, OS X and Android (ARM) are available on the releases page. Most are built without SSL support, so can't connect to secure wss://
websockets, only ws://
.
Limitations
- Replies to WebSocket pings are not tested at all
- Windows not tested at all
- Only partial SSL support.
Full list of specifiers with examples
(available as --long-help
)
WsClient
ws://
,wss://
WebSocket client. Argument is host and URL.
Example: manually interact with a web socket
websocat - ws://echo.websocket.org/
Example: forward TCP port 4554 to a websocket
websocat tcp-l:127.0.0.1:4554 wss://127.0.0.1/some_websocket
WsServer
ws-l:
,l-ws:
,ws-listen:
,listen-ws:
WebSocket server. Argument is either IPv4 host and port to listen or a subspecifier.
Example: Dump all incoming websocket data to console
websocat ws-l:127.0.0.1:8808 -
Example: the same, but more verbose:
websocat ws-l:tcp-l:127.0.0.1:8808 reuse:-TODO
Stdio
-
,stdio:
,inetd:
Read input from console, print to console.
This specifier can be specified only one time.
When inetd:
form is used, it also disables logging to stderr (TODO)
Example: simulate cat(1)
.
websocat - -
Example: SSH transport
ssh -c ProxyCommand='websocat - ws://myserver/mywebsocket' user@myserver
inetd-ws:
- is of ws-l:inetd:
Example of inetd.conf line that makes it listen for websocket connections on port 1234 and redirect the data to local SSH server.
1234 stream tcp nowait myuser /opt/websocat websocat inetd-ws: tcp:127.0.0.1:22
TcpConnect
tcp:
,tcp-connect:
,connect-tcp:
,tcp-c:
,c-tcp:
Connect to specified TCP host and port. Argument is a socket address.
Example: simulate netcat netcat
websocat - tcp:127.0.0.1:22
Example: redirect websocket connections to local SSH server over IPv6
websocat ws-l:0.0.0.0:8084 tcp:[::1]:22
TcpListen
tcp-listen:
,listen-tcp:
,tcp-l:
,l-tcp:
Listen TCP port on specified address.
Example: echo server
websocat tcp-l:0.0.0.0:1441 mirror:
Example: redirect TCP to a websocket
websocat tcp-l:0.0.0.0:8088 ws://echo.websocket.org
ShC
sh-c:
,cmd:
Start specified command line using sh -c
or cmd /C
Example: serve a counter
websocat -U ws-l:127.0.0.1:8008 cmd:'for i in 0 1 2 3 4 5 6 7 8 9 10; do echo $i; sleep 1; done'
Example: unauthenticated shell
websocat --exit-on-eof ws-l:127.0.0.1:5667 sh-c:'bash -i 2>&1'
Exec
exec:
Execute a program directly (without a subshell), providing array of arguments on Unix
Example: Serve current date
websocat -U ws-l:127.0.0.1:5667 exec:date
Example: pinger
websocat -U ws-l:127.0.0.1:5667 exec:ping --exec-args 127.0.0.1 -c 1
ReadFile
readfile:
Synchronously read a file. Argumen is a file path.
Blocking on operations with the file pauses the whole process
Example: Serve the file once per connection, ignore all replies.
websocat ws-l:127.0.0.1:8000 readfile:hello.json
WriteFile
writefile:
Synchronously truncate and write a file.
Blocking on operations with the file pauses the whole process
Example:
websocat ws-l:127.0.0.1:8000 writefile:data.txt
AppendFile
appendfile:
Synchronously append a file.
Blocking on operations with the file pauses the whole process
Example: Logging all incoming data from WebSocket clients to one file
websocat -u ws-l:127.0.0.1:8000 reuse:appendfile:log.txt
Reuser
reuse:
Reuse subspecifier for serving multiple clients.
Better used with --unidirectional, otherwise replies get directed to random connected client.
Example: Forward multiple parallel WebSocket connections to a single persistent TCP connection
websocat -u ws-l:0.0.0.0:8800 reuse:tcp:127.0.0.1:4567
Example (unreliable): don't disconnect SSH when websocket reconnects
websocat ws-l:[::]:8088 reuse:tcp:127.0.0.1:22
AutoReconnect
autoreconnect:
Re-establish underlying specifier on any error or EOF
Example: keep connecting to the port or spin 100% CPU trying if it is closed.
websocat - autoreconnect:tcp:127.0.0.1:5445
Example: keep remote logging connection open (or flood the host if port is closed):
websocat -u ws-l:0.0.0.0:8080 reuse:autoreconnect:tcp:192.168.0.3:1025
TODO: implement delays between reconnect attempts
WsConnect
ws-c:
,c-ws:
,ws-connect:
,connect-ws:
Low-level WebSocket connector. Argument is a subspecifier.
URL and Host: header being sent are independent from the underlying specifier.
Example: connect to echo server in more explicit way
websocat --ws-c-uri=ws://echo.websocket.org/ - ws-c:tcp:174.129.224.73:80
Example: connect to echo server, observing WebSocket TCP packet exchange
websocat --ws-c-uri=ws://echo.websocket.org/ - ws-c:cmd:"socat -v -x - tcp:174.129.224.73:80"
UdpConnect
udp:
,udp-connect:
,connect-udp:
,udp-c:
,c-udp:
Send and receive packets to specified UDP socket, from random UDP port
UdpListen
udp-listen:
,listen-udp:
,udp-l:
,l-udp:
Bind an UDP socket to specifier host:port, receive packet from any remote UDP socket, send replies to recently observed remote UDP socket.
Note that it is not a multiconnect specifier like e.g. tcp-listen
:
entire lifecycle of the UDP socket is the same connection.
File a feature request on Github if you want proper DNS-like request-reply UDP mode here.
OpenAsync
open-async:
Open file for read and write and use it like a socket. Not for regular files, see readfile/writefile instead.
Example: Serve big blobs of random data to clients
websocat -U ws-l:127.0.0.1:8088 open-async:/dev/urandom
OpenFdAsync
open-fd:
Use specified file descriptor like a socket
Example: Serve random data to clients v2
websocat -U ws-l:127.0.0.1:8088 reuse:open-fd:55 55< /dev/urandom
ThreadedStdio
threadedstdio:
Stdin/stdout, spawning a thread.
Like -
, but forces threaded mode instead of async mode
Use when standard input is not epoll(7)
-able or you want to avoid setting it to nonblocking mode.
UnixConnect
unix:
,unix-connect:
,connect-unix:
,unix-c:
,c-unix:
Connect to UNIX socket. Argument is filesystem path.
Example: forward connections from websockets to a UNIX stream socket
websocat ws-l:127.0.0.1:8088 unix:the_socket
UnixListen
unix-listen:
,listen-unix:
,unix-l:
,l-unix:
Listen for connections on a specified UNIX socket
Example: forward connections from a UNIX socket to a WebSocket
websocat --unlink unix-l:the_socket ws://127.0.0.1:8089
Example: Accept forwarded WebSocket connections from Nginx
umask 0000
websocat --unlink ws-l:unix-l:/tmp/wstest tcp:[::]:22
Nginx config:
location /ws {
proxy_read_timeout 7d;
proxy_send_timeout 7d;
#proxy_pass http://localhost:3012;
proxy_pass http://unix:/tmp/wstest;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection \"upgrade\";
}
This configuration allows to make Nginx responsible for SSL and also it can choose which connections to forward to websocat based on URLs.
Obviously, Nginx can also redirect to TCP-listening websocat just as well - UNIX sockets are not a requirement for this feature.
TODO: --chmod option?
UnixDgram
unix-dgram:
Send packets to one path, receive from the other. A socket for sending must be already openend.
I don't know if this mode has any use, it is here just for completeness.
Example:
socat unix-recv:./sender -&
websocat - unix-dgram:./receiver:./sender
AbstractConnect
abstract:
,abstract-connect:
,connect-abstract:
,abstract-c:
,c-abstract:
Connect to UNIX abstract-namespaced socket. Argument is some string used as address.
Too long addresses may be silently chopped off.
Example: forward connections from websockets to an abstract stream socket
websocat ws-l:127.0.0.1:8088 abstract:the_socket
Note that abstract-namespaced Linux sockets may not be normally supported by Rust, so non-prebuilt versions may have problems with them.
AbstractListen
abstract-listen:
,listen-abstract:
,abstract-l:
,l-abstract:
Listen for connections on a specified abstract UNIX socket
Example: forward connections from an abstract UNIX socket to a WebSocket
websocat abstract-l:the_socket ws://127.0.0.1:8089
Note that abstract-namespaced Linux sockets may not be normally supported by Rust, so non-prebuilt versions may have problems with them.
AbstractDgram
abstract-dgram:
Send packets to one address, receive from the other. A socket for sending must be already openend.
I don't know if this mode has any use, it is here just for completeness.
Example (untested):
websocat - abstract-dgram:receiver_addr:sender_addr
Note that abstract-namespaced Linux sockets may not be normally supported by Rust,
so non-prebuilt versions may have problems with them. In particular, this mode
may fail to work without workaround1
Cargo feature.
Mirror
mirror:
Simply copy output to input. No arguments needed.
Similar to exec:cat
.
LiteralReply
literalreply:
Reply with a specified string for each input packet.
Example:
websocat ws-l:0.0.0.0:1234 literalreply:'{"status":"OK"}'
Clogged
clogged:
Do nothing. Don't read or write any bytes. Keep connections in "hung" state.
Literal
literal:
Output a string, discard input.
Example:
websocat ws-l:127.0.0.1:8080 literal:'{ "hello":"world"} '
Assert
assert:
Check the input. Read entire input and panic the program if the input is not equal to the specified string. Used in tests.
SeqpacketConnect
seqpacket:
,seqpacket-connect:
,connect-seqpacket:
,seqpacket-c:
,c-seqpacket:
Connect to AF_UNIX SOCK_SEQPACKET socket. Argument is a filesystem path.
Start the path with @
character to make it connect to abstract-namespaced socket instead.
Too long paths are silently truncated.
Example: forward connections from websockets to a UNIX seqpacket abstract socket
websocat ws-l:127.0.0.1:1234 seqpacket:@test
SeqpacketListen
seqpacket-listen:
,listen-seqpacket:
,seqpacket-l:
,l-seqpacket:
Listen for connections on a specified AF_UNIX SOCK_SEQPACKET socket
Start the path with @
character to make it connect to abstract-namespaced socket instead.
Too long (>=108 bytes) paths are silently truncated.
Example: forward connections from a UNIX seqpacket socket to a WebSocket
websocat --unlink seqpacket-l:the_socket ws://127.0.0.1:8089
Planned features
- Driving SSL server websockets (specifying cert and key)
- Pure Rust version with SSL support?
- SOCK_SEQPACKET mode for
exec:
? - SOCK_SEQPACKET SCTP mode?
- Option for auto
\n
insertion - Add WebRTC's DataChannel to the mix (separate project)?
There are also checkboxes on Issues.