Skip to content

Latest commit

 

History

History
348 lines (264 loc) · 24.5 KB

moreexamples.md

File metadata and controls

348 lines (264 loc) · 24.5 KB

More examples to avoid bloating up README or specifier-specific docs.

SSL (TLS) and wss://

Connecting to wss:// without checking certificate

Websocat has -k option to turn off checking of SSL certificate. As alternative (or when using older versions of Websocat) you can use external programs to provide SSL for websocat. With socat:

$ websocat -t --ws-c-uri=wss://echo.websocket.org/ - ws-c:cmd:'socat - ssl:echo.websocket.org:443,verify=0'
sadf
sadf
dsafdsaf
dsafdsaf

With openssl s_client, also showing the log output:

$ websocat -v -t --ws-c-uri=wss://echo.websocket.org/ - ws-c:cmd:'openssl s_client -connect echo.websocket.org:443 -quiet' 
 INFO 2018-08-30T15:45:31Z: websocat::lints: Auto-inserting the line mode
 INFO 2018-08-30T15:45:31Z: websocat::sessionserve: Serving Line2Message(Stdio) to Message2Line(WsConnect(Cmd("openssl s_client -connect echo.websocket.org:443 -quiet"))) with Options { websocket_text_mode: true, websocket_protocol: None, udp_oneshot_mode: false, unidirectional: false, unidirectional_reverse: false, exit_on_eof: false, oneshot: false, unlink_unix_socket: false, exec_args: [], ws_c_uri: "wss://echo.websocket.org/", linemode_strip_newlines: false, linemode_strict: false, origin: None, custom_headers: [], websocket_version: None, websocket_dont_close: false, one_message: false, no_auto_linemode: false, buffer_size: 65536, broadcast_queue_len: 16, read_debt_handling: Warn, linemode_zero_terminated: false, restrict_uri: None, serve_static_files: [], exec_set_env: false, reuser_send_zero_msg_on_disconnect: false, process_zero_sighup: false, process_exit_sighup: false, socks_destination: None, auto_socks5: None, socks5_bind_script: None, tls_domain: None }
 INFO 2018-08-30T15:45:31Z: websocat::stdio_peer: get_stdio_peer (async)
 INFO 2018-08-30T15:45:31Z: websocat::stdio_peer: Setting stdin to nonblocking mode
 INFO 2018-08-30T15:45:31Z: websocat::stdio_peer: Installing signal handler
 INFO 2018-08-30T15:45:31Z: websocat::ws_client_peer: get_ws_client_peer_wrapped
depth=2 C = US, ST = Arizona, L = Scottsdale, O = "GoDaddy.com, Inc.", CN = Go Daddy Root Certificate Authority - G2
verify return:1
depth=1 C = US, ST = Arizona, L = Scottsdale, O = "GoDaddy.com, Inc.", OU = http://certs.godaddy.com/repository/, CN = Go Daddy Secure Certificate Authority - G2
verify return:1
depth=0 OU = Domain Control Validated, CN = *.websocket.org
verify return:1
 INFO 2018-08-30T15:45:31Z: websocat::ws_client_peer: Connected to ws
123
123
qwer
qwer
 INFO 2018-08-30T15:45:35Z: websocat::sessionserve: Forward finished
 INFO 2018-08-30T15:45:35Z: websocat::sessionserve: Forward shutdown finished
 INFO 2018-08-30T15:45:35Z: websocat::sessionserve: Reverse finished
 INFO 2018-08-30T15:45:35Z: websocat::sessionserve: Reverse shutdown finished
 INFO 2018-08-30T15:45:35Z: websocat::sessionserve: Finished
 INFO 2018-08-30T15:45:35Z: websocat::stdio_peer: Restoring blocking status for stdin
 INFO 2018-08-30T15:45:35Z: websocat::stdio_peer: Restoring blocking status for stdin

This approach can also be used in Websocat builds that do not support SSL.

Listening wss:// for development purposes

$ openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -days 365
Generating a 4096 bit RSA private key
..........++
.........................++
writing new private key to 'key.pem'
Enter PEM pass phrase:1234
Verifying - Enter PEM pass phrase:1234
-----
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [AU]:
State or Province Name (full name) [Some-State]:
Locality Name (eg, city) []:
Organization Name (eg, company) [Internet Widgits Pty Ltd]:
Organizational Unit Name (eg, section) []:
Common Name (e.g. server FQDN or YOUR name) []:
Email Address []:

$ openssl pkcs12 -export -out q.pkcs12 -inkey key.pem -in cert.pem
Enter pass phrase for key.pem:1234
Enter Export Password:<empty>
Verifying - Enter Export Password:<empty>

$ websocat --pkcs12-der=q.pkcs12 -s 1234
Listening on wss://127.0.0.1:1234/

There is a pre-generated certificate test.pkcs12 included in Git.

Workaround method for creating a wss:// server:

socat openssl-listen:1234,cert=cert.pem,key=key.pem,verify=0,fork,reuseaddr system:"websocat -t inetd-ws\\: open-fd\\:2"

Proxy servers

Connect to a WebSocket using a SOCKS5 proxy

There is internal SOCKS5 client now, but sometimes external client is better:

websocat -v -t - --ws-c-uri=ws://echo.websocket.org ws-c:cmd:'SOCKS5_PASSWORD=a connect-proxy -S a@127.0.0.1:9050 echo.websocket.org 80'

Connect to a WebSocket using HTTP proxy

websocat -v -t - --ws-c-uri=ws://echo.websocket.org ws-c:cmd:'connect-proxy -H 127.0.0.1:9051 echo.websocket.org 80'

Listen WebSocket on SOCKS5 server side and connect to it

cat > port_obtained << \EOF
#!/bin/sh
echo Remote port opened: $1
websocat -t -1 literal:"Roundtrip using SOCKS server" ws://132.148.129.183:$1/
EOF

chmod +x port_obtained

websocat -E -t ws-u:socks5-bind:tcp:132.148.129.183:14124 - --socks5-destination 255.255.255.255:65535 --socks5-bind-script ./port_obtained
Remote port opened: 53467
Roundtrip using SOCKS server

websocat -v -E -t ws-u:socks5-bind:tcp:132.148.129.183:14124 - --socks5-destination 255.255.255.255:65535 --socks5-bind-script ./port_obtained 
 INFO 2018-08-29T22:04:42Z: websocat::lints: Auto-inserting the line mode
 INFO 2018-08-29T22:04:42Z: websocat::sessionserve: Serving Message2Line(WsServer(SocksBind(TcpConnect(V4(132.148.129.183:14124))))) to Line2Message(Stdio) with Options { websocket_text_mode: true, websocket_protocol: None, udp_oneshot_mode: false, unidirectional: false, unidirectional_reverse: false, exit_on_eof: true, oneshot: false, unlink_unix_socket: false, exec_args: [], ws_c_uri: "ws://0.0.0.0/", linemode_strip_newlines: false, linemode_strict: false, origin: None, custom_headers: [], websocket_version: None, websocket_dont_close: false, one_message: false, no_auto_linemode: false, buffer_size: 65536, broadcast_queue_len: 16, read_debt_handling: Warn, linemode_zero_terminated: false, restrict_uri: None, serve_static_files: [], exec_set_env: false, reuser_send_zero_msg_on_disconnect: false, process_zero_sighup: false, process_exit_sighup: false, socks_destination: Some(SocksSocketAddr { host: Ip(V4(255.255.255.255)), port: 65535 }), auto_socks5: None, socks5_bind_script: Some("./port_obtained") }
 INFO 2018-08-29T22:04:43Z: websocat::net_peer: Connected to TCP
 INFO 2018-08-29T22:04:46Z: websocat::proxy_peer: SOCKS5 connect/bind: SocksSocketAddr { host: Ip(V4(0.0.0.0)), port: 34020 }
Remote port opened: 34020
 INFO 2018-08-29T22:04:46Z: websocat::proxy_peer: SOCKS5 remote connected: SocksSocketAddr { host: Ip(V4(104.131.203.210)), port: 58836 }
 INFO 2018-08-29T22:04:47Z: websocat::ws_server_peer: Incoming connection to websocket: /
 INFO 2018-08-29T22:04:47Z: websocat::ws_server_peer: Upgraded
 INFO 2018-08-29T22:04:47Z: websocat::stdio_peer: get_stdio_peer (async)
 INFO 2018-08-29T22:04:47Z: websocat::stdio_peer: Setting stdin to nonblocking mode
 INFO 2018-08-29T22:04:47Z: websocat::stdio_peer: Installing signal handler
Roundtrip using SOCKS server
 INFO 2018-08-29T22:04:47Z: websocat::sessionserve: Forward finished
 INFO 2018-08-29T22:04:47Z: websocat::sessionserve: Forward shutdown finished
 INFO 2018-08-29T22:04:47Z: websocat::sessionserve: One of directions finished
 INFO 2018-08-29T22:04:47Z: websocat::stdio_peer: Restoring blocking status for stdin
 INFO 2018-08-29T22:04:47Z: websocat::stdio_peer: Restoring blocking status for stdin

Persistent client connection

Suppose there is WebSocket server which replies exactly one WebSocket text message for each received WebSocket request.

You want to have a persistent WebSocket client connection to that server and issue multiple requests from a script.

You can do something like this:

$ websocat -t -E tcp-l:127.0.0.1:1234  reuse-raw:ws://echo.websocket.org --max-messages-rev 1&
[1] 864

$ WS_PID=$!

$ echo 'Hello 1' | nc 127.0.0.1 1234
Hello 1

$ echo 'World 2' | nc 127.0.0.1 1234
World 2

$ kill $WS_PID

This scheme is unfortunately unreliable: if client is disconnected before it can receive a message, the message can get delivered to next connected client.

Configuring Nginx to forward Websocket connections

Usual proxy_pass is not enough.

You need something like this:

location /mywebsocket {
    proxy_read_timeout 1d;
    proxy_send_timeout 1d;
    proxy_pass http://localhost:8123;
    #proxy_pass http://unix:/tmp/unixsocket_websocat;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
}

Debugging connection issues by dumping traffic.

If you want to log information that is passing though Websocat to console, you can use log: filter (overlay).

This allows inspecting traffic at various levels. For Websocat versions earlier than 1.7, you can use ws-c:cmd: trick instead.

Example sessions:

At message level

$ websocat  -t - --ws-c-uri=wss://echo.websocket.org log:ws-c:ssl:tcp:echo.websocket.org:443
[WARN  websocat::ssl_peer] Connected to TLS without proper verification of certificate. Use --tls-domain option.
asdf
WRITE 5 "asdf\n"
READ 5 "asdf\n"
asdf
12345
WRITE 6 "12345\n"
READ 6 "12345\n"
12345

At HTTP and Websocket protocol level

$ websocat  -t - --ws-c-uri=wss://echo.websocket.org ws-c:log:ssl:tcp:echo.websocket.org:443
[WARN  websocat::ssl_peer] Connected to TLS without proper verification of certificate. Use --tls-domain option.
WRITE 157 "GET / HTTP/1.1\r\nHost: echo.websocket.org\r\nConnection: Upgrade\r\nUpgrade: websocket\r\nSec-WebSocket-Version: 13\r\nSec-WebSocket-Key: lnQ/ReYmkEBvBVajdASTHg==\r\n\r\n"
READ 201 "HTTP/1.1 101 Web Socket Protocol Handshake\r\nConnection: Upgrade\r\nDate: Sun, 21 Feb 2021 20:59:59 GMT\r\nSec-WebSocket-Accept: uZ5OAMgIFtQE5WRsqRRlA+DM0UI=\r\nServer: Kaazing Gateway\r\nUpgrade: websocket\r\n\r\n"
ABCDE
WRITE 12 "\x81\x86\xd6\xa90\x97\x97\xebs\xd3\x93\xa3"
READ 8 "\x81\x06ABCDE\n"
ABCDE
56789
WRITE 12 "\x81\x86\x8aH\xe8b\xbf~\xdfZ\xb3B"
READ 8 "\x81\x0656789\n"
56789
WRITE 6 "\x88\x80u\xbfoz"
READ 2 "\x88\x00"

At TCP stream level

$ websocat  -t - --ws-c-uri=wss://echo.websocket.org --tls-domain=echo.websocket.org ws-c:ssl:log:tcp:echo.websocket.org:443
WRITE 517 "\x16\x03\x01\x02\x00\x01\x00\x01\xfc\x03\x03\x0e(r\xec\xbbXr\xacb\xe2\x0b+\x0f\xdc\xfa\x17\xb7R`\x1e\xda\xb42e\xd7\xf2\xdd\xd24O;\xd9 Y\t2\xe9kI\xa5I\xd4\xee)p6\xd6\xbf\x8dE:`\xe8]\x7fVN\x9e\x10\xe4\x7f8\xa2:\x98\x00>\x13\x02\x13\x03\x13\x01\xc0,\xc00\x00\x9f\xcc\xa9\xcc\xa8\xcc\xaa\xc0+\xc0/\x00\x9e\xc0$\xc0(\x00k\xc0#\xc0\'\x00g\xc0\n\xc0\x14\x009\xc0\t\xc0\x13\x003\x00\x9d\x00\x9c\x00=\x00<\x005\x00/\x00\xff\x01\x00\x01u\x00\x00\x00\x17\x00\x15\x00\x00\x12echo.websocket.org\x00\x0b\x00\x04\x03\x00\x01\x02\x00\n\x00\x0c\x00\n\x00\x1d\x00\x17\x00\x1e\x00\x19\x00\x18\x00#\x00\x00\x00\x16\x00\x00\x00\x17\x00\x00\x00\r\x000\x00.\x04\x03\x05\x03\x06\x03\x08\x07\x08\x08\x08\t\x08\n\x08\x0b\x08\x04\x08\x05\x08\x06\x04\x01\x05\x01\x06\x01\x03\x03\x02\x03\x03\x01\x02\x01\x03\x02\x02\x02\x04\x02\x05\x02\x06\x02\x00+\x00\t\x08\x03\x04\x03\x03\x03\x02\x03\x01\x00-\x00\x02\x01\x01\x003\x00&\x00$\x00\x1d\x00 \xa0t\xa8\x9d\xd8t\x06E\x94\xba+\xa7\xcf\x90**W\x8dS\xd1\xf4\xd4\xf7\x06\xda\xa4B\x9e\xeb\xa4\xf3\x10\x00\x15\x00\xc1\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
READ 5 "\x16\x03\x03\n\x00"
READ 2560 "\x02\x00\x00M\x03\x03`2\xca\x95\x17H\xaa\x9f\x7fz[O>\x0e\xc8x\xd9\x8d\xe71\xac\xffJ\xb8\xd8\x8d\xe4LB2\xee\x80 `2\xca\x95\x93;2\xdc\x04@;T\xc23Ei\x8ax\xfa\xb8y\x12\'\x05(\xce8|^Fv\x97\x00/\x00\x00\x05\xff\x01\x00\x01\x00\x0b\x00\t\xa7\x00\t\xa4\x00\x0550\x82\x0510\x82\x04\x19\xa0\x03\x02\x01\x02\x02\x12\x04\x00\xd5\xa4Naq\xe3S\xeb\xc7\xc8\x82\xb3g\xc5\xdeq0\r\x06\t*\x86H\x86\xf7\r\x01\x01\x0b\x05\x00021\x0b0\t\x06\x03U\x04\x06\x13\x02US1\x160\x14\x06\x03U\x04\n\x13\rLet\'s Encrypt1\x0b0\t\x06\x03U\x04\x03\x13\x02R30\x1e\x17\r210104172430Z\x17\r210404172430Z0\x181\x160\x14\x06\x03U\x04\x03\x13\rwebsocket.org0\x82\x01\"0\r\x06\t*\x86H\x86\xf7\r\x01\x01\x01\x05\x00\x03\x82\x01\x0f\x000\x82\x01\n\x02\x82\x01\x01\x00\xa56O\xbfj\xb6\'\x8a<#\xcf\xce=\x1d\xb4\x1d\x0fI\xffW\\\xd9\xdb\xack\xd3\xed;<?\xb9K\xfcf;\xec\x98-\r\xa0KG\xd5\xec\x9c\xdeIY\x89\x97\x83\xfc\xc7A7\x89\xa9\xf41\x0b\xe6g3\n\xb9nH\x87c\xe3K\x88\xae\x88\x97\x93#\x9d\x19f\x8b\xbf\xe6\xb7\x9d\x87\xc9\xee\x94\x94\xaflz\xeb_P\x1eG\xeb\x88Q\n\x9f\x95VnR1\xed\x1a/\xee\xe5\x87\x1a\xec\x9c\xcd\xff!\x04\xb8\x8c\x9b\x9c&]\xb8\xe4=\xb1\xad\xb0R\x83~\xa9,\xb4ct\x17\xb6\x9f\x82\xda\xf6\xae&\xed\xdf\xfe\x91\x851\x91\xafG8\x14R\xf2\xf8e9\xd8\x0bTsc\xa6\x98\x9dBi%\xfd\xaa\xa7\"\x17{=\x90a\x12os\x8c|\x94M\xeeD\xc7v\xb6\x04\xa1\xd6\xda\x9d_\xb1\xd0\xb5\xb1;\x08\xd72\x89+\xa9W\xd7\x9e\xf0\x86D\xe8\xbf\x81\x0b\xf7\xa9nca|\xd4SK}\x02\xdf7\xa7\xa3\xd5MD\x80b\x19\xa5\xb2(\x9c*\x87\xe0\x9b\x9b\xf6\xe3\x02\x03\x01\x00\x01\xa3\x82\x02Y0\x82\x02U0\x0e\x06\x03U\x1d\x0f\x01\x01\xff\x04\x04\x03\x02\x05\xa00\x1d\x06\x03U\x1d%\x04\x160\x14\x06\x08+\x06\x01\x05\x05\x07\x03\x01\x06\x08+\x06\x01\x05\x05\x07\x03\x020\x0c\x06\x03U\x1d\x13\x01\x01\xff\x04\x020\x000\x1d\x06\x03U\x1d\x0e\x04\x16\x04\x14\x04c\xfdH\xa3m\xbf\x01B%\x98\x95\x9cP\xb6\x10\x96\xc6i\x1c0\x1f\x06\x03U\x1d#\x04\x180\x16\x80\x14\x14.\xb3\x17\xb7XV\xcb\xaeP\t@\xe6\x1f\xaf\x9d\x8b\x14\xc2\xc60U\x06\x08+\x06\x01\x05\x05\x07\x01\x01\x04I0G0!\x06\x08+\x06\x01\x05\x05\x070\x01\x86\x15http://r3.o.lencr.org0\"\x06\x08+\x06\x01\x05\x05\x070\x02\x86\x16http://r3.i.lencr.org/0)\x06\x03U\x1d\x11\x04\"0 \x82\x0f*.websocket.org\x82\rwebsocket.org0L\x06\x03U\x1d \x04E0C0\x08\x06\x06g\x81\x0c\x01\x02\x0107\x06\x0b+\x06\x01\x04\x01\x82\xdf\x13\x01\x01\x010(0&\x06\x08+\x06\x01\x05\x05\x07\x02\x01\x16\x1ahttp://cps.letsencrypt.org0\x82\x01\x04\x06\n+\x06\x01\x04\x01\xd6y\x02\x04\x02\x04\x81\xf5\x04\x81\xf2\x00\xf0\x00v\x00\x94 \xbc\x1e\x8e\xd5\x8dl\x88s\x1f\x82\x8b\",\r\xd1\xdaM^lO\x94=a\xdbN/XM\xa2\xc2\x00\x00\x01v\xce\xa4\xb7\xce\x00\x00\x04\x03\x00G0E\x02!\x00\x9df\x0b\xa0\xc2?\x02\x0c;V1\x04B\xf8\xbc\x80\xf3ToUi\x98i\xfb\x08\xb1\x1d2\xed\xd7\n=\x02 b 2b\x8d\x1b\xac2\xf5-:\xad\x8f\r\xaa\xc7\xccR\xc3\xba\xd5kz#g.\x85c\xb2\xf1\x9b\x86\x00v\x00\xf6\\\x94/\xd1w0\"\x14T\x18\x080\x94V\x8e\xe3M\x13\x193\xbf\xdf\x0c/ \x0b\xccN\xf1d\xe3\x00\x00\x01v\xce\xa4\xb7\xc8\x00\x00\x04\x03\x00G0E\x02 o\xb2V\x9fH\xf6\xfe\x88\x08diV\x9d\x91\x06Gj\x02\xad(\xaa\x1f\xfa\xdd\x13\xe6\xe2Z\r\x8fD\xae\x02!\x00\x88\xf3\xfd\xd6\x04\xef\x03\"\x8c=\xb3dI\x19\xdd\xa8\xf2P\xca#*\t\xdb\x95B9\xee\xd6\x8a\xc1\t[0\r\x06\t*\x86H\x86\xf7\r\x01\x01\x0b\x05\x00\x03\x82\x01\x01\x00W\xde]\xac\xc8;=\xc1\xf7\x84#\x08\\!W\xe6\xe6O\x9a\x81\x86\xefRg~\xff\xc1\xf5\x04q\x89\xb1\x96\xc9c\t%l\xc0\xe9\xee\xaba\x84o\xc2u<o\xaf(\xad:\x14\x94:\x97\x89\x12?\x9f\x80n\x11\xa87\x9e\xdbw\xf8\xde\xde\x9c\x1e\xc3\xe3\xdb\xa3.!R\xa2\x8eM\xb2z\xbc\xb8\xc9\x04\x9b\xc8Q\xff\x8e\xea\x8c\x813\x9e\xc8WOP\xdc\x9e\xbe5P\xc8\xdeq\xdf\xc9\x0ek\xa9\x8f\xfc\xff\xee\xd5\xcf\x95U\xd0\x0f\x1a]\xa2\xb0(y\xaa\xb0(&N^~\xd8\x7f`\'\x85\xeff\xc1\xce\x9f1\xaf\xe1U\xe3\x89t\x14VE\xa3\xf1]\xa7\xf9K\xbeV\x99\xbb\x1c\xc4\xe2|\xf5Pg\x14\xde\xf7\xeb\"Z(\xa1D=#1\xcc\x1f\xa9\xad=\xbe\xb2\x01j\x02\xc9\xd0\x96\n3\xb9(b>\xc4?7\x8d)\x1bOf\xf4\xfd\xefw\xdb\xbb\xf6\x9cN\xf4-\x1a.8Th\xa0q\xfe\xf5\xb0\xcf\x9f/\x14\xb4\xbb \xb8\xfd\xd24Yg?}\xd5L\xde\x07\x00\x04i0\x82\x04e0\x82\x03M\xa0\x03\x02\x01\x02\x02\x10@\x01u\x04\x83\x14\xa4\xc8!\x8c\x84\xa9\x0c\x16\xcd\xdf0\r\x06\t*\x86H\x86\xf7\r\x01\x01\x0b\x05\x000?1$0\"\x06\x03U\x04\n\x13\x1bDigital Signature Trust Co.1\x170\x15\x06\x03U\x04\x03\x13\x0eDST Root CA X30\x1e\x17\r201007192140Z\x17\r210929192140Z021\x0b0\t\x06\x03U\x04\x06\x13\x02US1\x160\x14\x06\x03U\x04\n\x13\rLet\'s Encrypt1\x0b0\t\x06\x03U\x04\x03\x13\x02R30\x82\x01\"0\r\x06\t*\x86H\x86\xf7\r\x01\x01\x01\x05\x00\x03\x82\x01\x0f\x000\x82\x01\n\x02\x82\x01\x01\x00\xbb\x02\x15(\xcc\xf6\xa0\x94\xd3\x0f\x12\xec\x8dU\x92\xc3\xf8\x82\xf1\x99\xa6zB\x88\xa7]&\xaa\xb5+\xb9\xc5L\xb1\xaf\x8ek\xf9u\xc8\xa3\xd7\x0fG\x94\x14U5W\x8c\x9e\xa8\xa29\x19\xf5\x82<B\xa9Nn\xf5;\xc3.\xdb\x8d\xc0\xb0\\\xf3Y8\xe7\xed\xcfi\xf0Z\x0b\x1b\xbe\xc0\x94$%\x87\xfa7q\xb3\x13\xe7\x1c\xac\xe1\x9b\xef\xdb\xe4;ERE\x96\xa9\xc1S\xce4\xc8R\xee\xb5\xae\xed\x8f\xde`p\xe2\xa5T\xab\xb6m\x0e\x97\xa5@4k+\xd3\xbcf\xebf4|\xfak\x8b\x8fW)\x99\xf80\x17]\xbaro\xfb\x81\xc5\xad\xd2\x86X=\x17\xc7\xe7\t\xbb\xf1+\xf7\x86\xdc\xc1\xdaq]\xd4F\xe3\xcc\xad%\xc1\x88\xbc`guf\xb3\xf1\x18\xf7\xa2\\\xe6S\xff:\x88\xb6G\xa5\xff\x13\x18\xea\x98\tw?\x9dS\xf9\xcf\x01\xe5\xf5\xa6p\x17\x14\xafc\xa4\xff\x99\xb3\x93\x9d\xdcS\xa7\x06\xfeH\x85\x1d\xa1i\xae%u\xbb\x13\xccR\x03\xf5\xedQ\xa1\x8b\xdb\x15\x02\x03\x01\x00\x01\xa3\x82\x01h0\x82\x01d0\x12\x06\x03U\x1d\x13\x01\x01\xff\x04\x080\x06\x01\x01\xff\x02\x01\x000\x0e\x06\x03U\x1d\x0f\x01\x01\xff\x04\x04\x03\x02\x01\x860K\x06\x08+\x06\x01\x05\x05\x07\x01\x01\x04?0=0;\x06\x08+\x06\x01\x05\x05\x070\x02\x86/http://apps.identrust.com/roots/dstrootcax3.p7c0\x1f\x06\x03U\x1d#\x04\x180\x16\x80\x14\xc4\xa7\xb1\xa4{,q\xfa\xdb\xe1K\x90u\xff\xc4\x15`\x85\x89\x100T\x06\x03U\x1d \x04M0K0\x08\x06\x06g\x81\x0c\x01\x02\x010?\x06\x0b+\x06\x01\x04\x01\x82\xdf\x13\x01\x01\x01000.\x06\x08+\x06\x01\x05\x05\x07\x02\x01\x16\"http://cps.root-x1.letsencrypt.org0<\x06\x03U\x1d\x1f\x0450301\xa0/\xa0-\x86+http://crl.identrust.com/DSTROOTCAX3CRL.crl0\x1d\x06\x03U\x1d\x0e\x04\x16\x04\x14\x14.\xb3\x17\xb7XV\xcb\xaeP\t@\xe6\x1f\xaf\x9d\x8b\x14\xc2\xc60\x1d\x06\x03U\x1d%\x04\x160\x14\x06\x08+\x06\x01\x05\x05\x07\x03\x01\x06\x08+\x06\x01\x05\x05\x07\x03\x020\r\x06\t*\x86H\x86\xf7\r\x01\x01\x0b\x05\x00\x03\x82\x01\x01\x00\xd9L\xe0\xc9\xf5\x84\x8871\xdb\xbb\x13\xe2\xb3\xfc\x8bkb\x12lX\xb7I~<\x02\xb7\xa8\x1f(a\xeb\xce\xe0.s\xefI\x07z5\x84\x1f\x1d\xadh\xf0\xd8\xfeV\x81/m\x7fX\xa6n56\x10\x1cs\xc3\xe5\xbdm^\x01\xd7nr\xfb*\xa0\xb8\xd3Wd\xe5[\xc2i\xd4\xd0\xb2\xf7|K\xc3\x17\x8e\x88rs\xdc\xfd\xfcm\xbd\xe3\xc9\x0b\x8ea:\x16X}t6+U\x80=\xc7c\xbe\x84C\xc69\xa1\x0ekW\x9e?)\xc1\x80\xf6\xb2\xbdG\xcb\xaa0l\xb72\xe1YT\x0b\x18\t\x17^cl\xfb\x96g<\x1cs\x0c\x93\x8b\xc6\x11v$\x86\xde@\x07\x07\xe4}-f\xb5%\xa3\x96X\xc8\xea\x80\xee\xcfi;\x96\xfc\xe6\x8d\xc03\xf3\x89\xf8)-\x14\x14-~\xf0ap\x95]\xf7\x0b\xe5\xc0\xfb$\xfa\xec\x8e\xcba\xc8\xeecq(\xa8,\x05;w\xef\x9b^\x03d\xf0Q\xd1\xe4\x85S\\\xb0\x02\x97\xd4~\xc64\xd2\xce\x10\x00\xe4\xb1\xdf:\xc2\xea\x17\xbe\x0e\x00\x00\x00"
WRITE 342 "\x16\x03\x03\x01\x06\x10\x00\x01\x02\x01\x00s\xaa\x90\xf7\x88\xba\xdcI\xe0\x81\xcb\xf4\x93\x1cbt#+^\x13?N\xc2\x18\xaf\xab\xb7\xc7\xf5\xc6\x8e\xcaD\xf9U\xaak\x96E\xa6\xeeH&F\x0f\x12\x03\xcf)}\xb8\xbc\x9e\xe2j\x98\xaa\x1b\"L&D\xac\xef\x7fe\x0fu\xf1B\xf1\x8b>0P\xd067\xdfBM\xf0\xd7r\x13`\x8e\x88=\xd0\x9a\xf8\xfe\x0c\x01~\xb8\x87I\xa5\xcc\x15s\x95\"\xa1\xdb>3m4\x92j&\xa6_r\x96\xa0v\xfa\x12\x14WH\xfd\xa6\xa5\x8dY\xfa\xd6(\xa3\xafT\x18\xca8\xb8E\xc2a\xb7l\x1e\xd75\x80_\xb3\x14}S\xa2\x1d\x98\xc4y\x80W\xf6\xb3&\xdf9\x84O9~\xbfd\xd2\xd7/\xb7U\xe1~\xcb6\x8a\xf2\x07\x07\xc1\xb3\xf1L\x14\xa3\x0c\xb2\xf0(\x99\xa3;\xff[\x1d\xa3p\xe2\xe9\x9cZ5\xaa\xe3\xf0\xa4\xb28\xac\x82e\xb9\x82\xfcz\xbf0\x1f\xce\x9f\x9d\xcb\x94\x7f\xc7\xb8\x8fH$\xdcj+\xfe\xb7z\x9b\xe0\xf0\xd4\xdct\xa7\xe7W\x92A\xa1e8\xc7\x14\x03\x03\x00\x01\x01\x16\x03\x03\x00@\xbb\x00\xba\x14\xcc\xa1\xa2@w mP=\xd3T\xaf\"\xe6M!\xa8\xe8A\xbb[\xafx\xbeDU}\xe1/\x8b\x0e\x8b\x8a\xe6\x82\x06\xe5bHy\xbcq{ \xdb\xb3o\xae\xb1\x03\x9e\xa6\xcf\x19\xee\xf9\x9b\xb3@0"
READ 5 "\x14\x03\x03\x00\x01"
READ 1 "\x01"
READ 5 "\x16\x03\x03\x00@"
READ 64 "\\0\xa6\xfb\x9fcks\xe2o\xd7L\xc2\xf7@\x0f\xaf\xc8\xb3\xd9F\xb0\x1b\xa3\xe7\xc6\xfb\xb4\x12\xf1\xac8\x9d0\x89\x96\x89H\xde\xda\n\xaaN\x90@\xa9<#\xe9_\xa1\xcex\x11\xe2\x0f\x87\x1c\x87 \xbf\'9\xa4"
WRITE 213 "\x17\x03\x03\x00\xd0\x8b\xf1G\xdcB\x83\xbf\x0f\xb0\xf4\x97YXk\xe7ow\xd3\x81\x89\xa0\xa1\x8bG\x99\xeb\xe3\xfa\xda\xd4QW=\x1d\x06\xadn#)L\x08\xa6\x10\xa4\x03O\xdf\xd5\xe2a\xda\xce\x9b\xe9f\xdf\xf4\x14UzW\xd8\xc8\x1c\xa2\xbf\x00\xc5\x9c}\x7fW;\x9b\xe8\x9f\xb0\xaa\x8c\xd0\xf9\xe0\xf7\xf4\"\xb6\xb0\nY\xff\x05\x0bz\xbc\x9c\x81\xd0\xf5\xee\x0bK\xd4Q\xd5l\x81E\xfb\xdcW\x12\xe4\xaa\xe7\xaf\x1c\x7f.\xb1\xd78\x11\xe6\xfd\xb6\xb9\xc5\xd1\xec\x83\xe5\x16\xb2P\xbd\x97\xb5E\x95\'\xf2\xf8B\xee\x01S\xf61&@-\xa0\x95e,H\x07\xb1\x9c\xba`\xd9\xf3\x9b\xe8\xba\x8c\xaaqt_\xe2t&f\xd3\xba\xc3W\xcc\xb7;\xa7\xc9A\x16\x11$e\xfd\x1e\x8eKF\x0cO+\x84\x1e\xc7\x85\x1b\xf2\"Pou\xda"
READ 5 "\x17\x03\x03\x00\xf0"
READ 240 "3\x14\xe7g\x12\xc2I4\x96\x8f\r$\xb4\xa2(\xf2b\xf5]\x82\xa77\x88wJy\x84\xf4\x8e\xaf\xa6\x04\x8d\xed\x7f\xd6q\x80o\'0\x1e\x85\xa1\xf8\x9buk\xc2\x9bx>\xb4S\xe3\xa4\xa2\x88\x8a\xff\xac\x06\x81\xc4\x98g,\xb2\xa9\'\xe2C=\x90\x9b\xc4\xd4\x7f\xa3\xcffneE\xee\x86\xae\xd3\x17\xf3 (\xb7\xf8W\xcd(\x16\x82s2\xe7\x03y81\xe0r\xa0C\x82\xedK\x93u\x87x,\xf3\xca\xc7\x84\xa1\xf5x \x06Q5\xe7\x00%\xb4\x84\xfaw\x1f^R\xc9o\xb4\x96\xf0\xa7\x01\xc5h\x04.\xc8Q\xcfw\t\x8e\xa8\xf9\x98\x9a~q\xb9/\x9f.u\x023Q8\x95\x8b\x7f~\xccx\xa9_,\xc7*<.\x0e\'jH\x05\x8b\xe8\xc2\xee\xd8\xa4\x12\xe1\xb6\xd7FL\xe7\r\xc1\x07*\xcb+\xf0\xc2Pq\xed7\t\x1e\xa4,\x05\xd0\x0e\xba\xf1ABtL*\xba\xbb\xe7~\x1e\xefO\x85\xbd\xe6\x84S"
qwert
WRITE 69 "\x17\x03\x03\x00@\n\x8c\\\xa8b\xae\x05N\xb9O\x81\xaej\x9eM\xf7$\xf9\x8f\xc8\xefz!\x89.\xfe\x19\x12`\xbf{fJS\xd5\x15\x84\x0e\xa5\xf7\"4\xa1\xda[\x95\xe2#&\xe8\xd3\x96\xb8]\xa4+~\xb2Cc\xfc6\xb2|"
READ 5 "\x17\x03\x03\x000"
READ 48 "\xb8uj&\xda\xed\xf9\xbc\xbfn\x9eS`\xa3\x10q\x10[\x05}\xef\xd6\xbf\t\xea\x14f\xf9c\xe6$\xd1R:\xdc\xcc\x88[\x97\xca\x12\x9f\xc1pk\x0e\xf6o"
qwert
zxcvbn
WRITE 69 "\x17\x03\x03\x00@\xe5\xf4\x99xS\xf6\xad\xf4\x89?\xbd\x99=`a\xab\x8e\xed\xd83\xa9-\xabU{\xfa~\xd9h\xf8\x1a\xfaS\xfdD-\xc4\x84=:\xae;\x0b\xccRHT\xef\x04E\x927\xbf~\x0e:\xb0\x16\x01\xf5\xd1\x0f\x1e\xc9"
READ 5 "\x17\x03\x03\x000"
READ 48 "\xa4\x9b=\x85\xe3\x8c\x0c-*\x08(Qu\xd8\x93\xbde,c\x1a\x9c\"\xc9o\xa7\xb5\xe9eH6\xa1\xed\xb9\xcb+\x13>nu^\x1c\x9d\x1b2\xc0\x98\x1d("
zxcvbn
WRITE 53 "\x17\x03\x03\x000\x17\x19\xf4>\xddSG8\xdd\xcd\x00\xf2\xf58\x15n\xbaY\xbaU\xf0H\x8b\t}\xa5\xaa\xfbXy\xc7f\xc2r\x9e\x94dO\xdc\xaf\xad\xcc\xcd\x16\x87\xdd\x19\xb9"
READ 5 "\x17\x03\x03\x000"
READ 48 "j#\x9d\x17B\x89\xee\x92\x90\xcaH6\xf7PQe|p\xed\xf8,=\x0f+\x8a\x10)\xcf\x06\xb1\x06\xde\x9eA>B\xb7g\xde\xce\xcc\xfd\x88\x1c\xf1-\x96\x00"

listening websockets from systemd

Systemd units for WebSocket-to-localhost-SSH redirector.

Accept=yes mode

Each client connection gets separate Websocat process.

/etc/systemd/system/qqq.socket

[Unit]
Description="websocat"

[Socket]
ListenStream=/run/qqq.socket
#ListenStream=127.0.0.1:1234 # also works for TCP
Accept=yes

[Install]
WantedBy=sockets.target

/etc/systemd/system/qqq@.service (note the important @ character).

[Unit]
Description="websocat"
Requires=qqq.socket

[Service]
Type=simple
ExecStart=/opt/websocat -E -b ws-inetd: tcp:127.0.0.1:22
StandardInput=socket
NonBlocking=true

[Install]
WantedBy=multi-user.target

Accept=no mode

Websocat is socket-activated by systemd and keeps on listening for more connections

Requires new enough Websocat version with --accept-from-fd option.

/etc/systemd/system/qqq.socket

[Unit]
Description="websocat"

[Socket]
ListenStream=/run/qqq.socket
# does _not_ work with TCP socket currently
Accept=no

[Install]
WantedBy=sockets.target

/etc/systemd/system/qqq.service (note the absence of @).

[Unit]
Description="websocat"
Requires=qqq.socket

[Service]
ExecStart=/opt/websocat -E -b --accept-from-fd l-ws-unix:3 tcp:127.0.0.1:22

[Install]
WantedBy=multi-user.target

with SocketUser=www-data it can be combined with Nginx setup above.

Example SSH client command: ssh root@localhost -o 'ProxyCommand=/opt/websocat -E -b - ws-c:unix:/run/qqq.socket'

Specifying distinct host names for resolving IP address, Host: header and TLS.

Example command line:

websocat -t - --ws-c-uri=wss://domain-for-host-header/ ws-c:tls:tcp:domain-or-ip-address-for-resolving:443 --tls-domain domain-for-checking-certificate

Or without TLS:

websocat -t - --ws-c-uri=wss://domain-for-host-header/ ws-c:tcp:domain-or-ip-address-for-resolving:80