vi / websocat

Command-line client for WebSockets, like netcat (or curl) for ws:// with advanced socat-like functions
MIT License
6.72k stars 257 forks source link

Binary Frames support #217

Closed lsd-cat closed 4 months ago

lsd-cat commented 4 months ago

I am trying to use websocat to bridge a websocket VNC (used in some vmware products) to a standard TCP socket so that standard VNC clients can be used.

A history of that issue can be seen at https://github.com/hashicorp/packer/issues/8984#issuecomment-691530514

The go client that the user in that issue implemented, available here https://github.com/markpeek/webmks/blob/master/main.go#L77 does indeed work without issues.

However, when I am trying to use websocat in this way:

./websocat.x86_64-unknown-linux-musl -b tcp-listen:127.0.0.1:5900 wss://<host>:443/ticket/<ticket> --no-fixups --no-line -k -H "Protocol: binary" -H "Origin: http://localhost/" -H "Version: hybi-13

my VNC client fails and websocat logs

websocat: WebSocketError: WebSocket protocol error
vi commented 4 months ago

Try a debugging command line like this:

./websocat.x86_64-unknown-linux-musl -b tcp-listen:127.0.0.1:5900 --ws-c-uri=wss://<host>:443/ticket/<ticket> --tls-domain=<host> ws-c:log:tls:tcp:<host>:443 --no-fixups --no-line -k -H "Protocol: binary" -H "Origin: http://localhost/" -H "Version: hybi-13"

(if original command line is not trimmed - there is missing closing quote mark)

This unlikely resolves the issue, but is expected to print unencrypted WebSocket establishment and traffic.

-b --no-fixups --no-line

The latter options will probably change nothing in -b mode are may be redundant.

lsd-cat commented 4 months ago

Thank you for your quick reply.

Here is the output with the extra info, I also removed the redundant options as you suggested.

./websocat.x86_64-unknown-linux-musl -b tcp-listen:127.0.0.1:5900  --ws-c-uri=wss://<host>:443/ticket/<ticket>  --tls-domain=<host> ws-c:log:tls:tcp:<host>:443 -k -H "Protocol: binary" -H "Origin: http://localhost/" -H "Version: hybi-13"
websocat: Unfortunately, serving multiple clients without --exit-on-eof (-E) or with -U option is prone to socket leak in this websocat version
WRITE 236 "GET /ticket/a907a6a64e9ca22b HTTP/1.1\r\nProtocol: binary\r\nOrigin: http://localhost/\r\nVersion: hybi-13\r\nHost: <host>r\nConnection: Upgrade\r\nUpgrade: websocket\r\nSec-WebSocket-Version: 13\r\nSec-WebSocket-Key: LuJJKDYUKdI50x49LR1a1A==\r\n\r\n"
READ 0 ""
websocat: WebSocketError: WebSocket protocol error

Does this mean the server just returns nothing instead of 101 or anything else?

vi commented 4 months ago

It seems that server fails to provide any HTTP response. It does not get to data transfer stage.

Does some other client (e.g. browser) successfully connect to that server?

Maybe there are traffic dumps of connection attempts (both from Websocat and that other client)?

You can also use -v option to increase logging (and see messages like Resolving hostname, Connected to TCP and Connected to TLS.

lsd-cat commented 4 months ago

Yes, browsers succesfully connects to the same websocket using the html5 based VNC client provided by vmware. (This is when forwarding the host locally via SSH). But I do not see the Go version setting up those any headers.

GET /ticket/456758acaa528aeb HTTP/1.1
Host: 127.0.0.1:8443
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:121.0) Gecko/20100101 Firefox/121.0
Accept: */*
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate, br
Sec-WebSocket-Version: 13
Origin: https://127.0.0.1:8443
Sec-WebSocket-Protocol: binary, vmware-vvc
Sec-WebSocket-Extensions: permessage-deflate
Sec-WebSocket-Key: Awjv/dudotsjFW8BE5KVPw==
DNT: 1
Connection: keep-alive, Upgrade
Cookie: vmware_client=VMware; vmware_soap_session="cookie"
Sec-Fetch-Dest: empty
Sec-Fetch-Mode: websocket
Sec-Fetch-Site: same-origin
Pragma: no-cache
Cache-Control: no-cache
Upgrade: websocket

With the following response:

HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Protocol: binary
Sec-WebSocket-Accept: zJDtT9UJrm4vlURrLVBX/2K5ND8=

From there, I have taken that as a curl command and worked to reduce to the minimum the headers needed:

curl -k -H 'Sec-WebSocket-Version: 13' -H 'Sec-WebSocket-Protocol: binary, vmware-vvc' -H 'Sec-WebSocket-Key: Awjv/dudotsjFW8BE5KVPw==' -H 'Sec-Fetch-Dest: empty' -H 'Upgrade: websocket' https://127.0.0.1:8443/ticket/963d2d66188a765f
?
 RFB 003.008

RFB is valid bytes from the VNC protocol.

lsd-cat commented 4 months ago

Replicating the same curl command with websocat works, if anybody ever needs it:

./websocat.x86_64-unknown-linux-musl -b tcp-listen:127.0.0.1:5900  --ws-c-uri=wss://<host>:443/ticket/<ticket>  --tls-domain=<host> ws-c:log:tls:tcp:<host>:443 -k -H 'Sec-WebSocket-Version: 13' -H 'Sec-WebSocket-Protocol: binary, vmware-vvc' -H 'Sec-WebSocket-Key: Awjv/dudotsjFW8BE5KVPw==' -H 'Sec-Fetch-Dest: empty' -H 'Upgrade: websocket'

Thank you very much for the guidance in troubleshooting this and for developing this originally :)

vi commented 4 months ago

I also noticed that headers in the original command line are different. And there is mysterious hybi-13 that is absent in the browser-initiated request.

If just Sec-WebSocket-Protocol: binary is the key then you can use simpler, dedicated option --protocol binary

lsd-cat commented 4 months ago

The most stripped down command that works for me is:

./websocat.x86_64-unknown-linux-musl -b tcp-listen:127.0.0.1:5900 wss://<host>:443/ticket/549e511c564b478a -k --protocol "binary, vmware-vvc"
nbanb commented 2 months ago

Hi all Thanks, that was helpfull !

Here is the command that finaly suites best to my use (based on QEMU noVNC) :


# First launching the websocket pipe provide by websocat : 
SSL_CERT_FILE=/dev/shm/fbx-cacert-ws websocat -H "X-Fbx-App-Auth: $_SESSION_TOKEN" --origin https://fbx.fbx.lan --protocol "chat, superchat" -E --binary tcp-listen:127.0.0.1:5900 wss://fbx.fbx.lan/api/v10/vm/17/vnc

# Second launching TigerVNC-viewer (providing vncviewer command) : 
# optvnc+=(...)
optvnc+=(-shared -geometry 1920x1080 -display $DISPLAY 127.0.0.1::5900 )
vncviewer "${optvnc[@]}"

Kind regards nbanba