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: Verifying - Enter Export Password: $ 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;\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\x820P\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