vi / websocat

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

Error websocat: WebSocketError: WebSocket protocol error #106

Open chrisooo3 opened 3 years ago

chrisooo3 commented 3 years ago

While running this command:

websocat ws://localhost:3000/ws/?transport=websocket

I get following error:

websocat: WebSocketError: WebSocket protocol error
websocat: error running

Why?

vi commented 3 years ago

Maybe the server is using the "Deflate" extension even when not requested from the client?

Debugging websocket handshake and reply currently involves running a customized command line and using additional tool "socat":

Example:

$ websocat -t - --ws-c-uri=ws://echo.websocket.org ws-c:cmd:'socat -v - tcp:echo.websocket.org:80'
> 2021/02/21 14:16:03.965471  length=157 from=0 to=156
GET / HTTP/1.1\r
Host: echo.websocket.org\r
Connection: Upgrade\r
Upgrade: websocket\r
Sec-WebSocket-Version: 13\r
Sec-WebSocket-Key: nwTCW8VmQNnNCyk4Me1wRw==\r
\r
< 2021/02/21 14:16:04.171128  length=201 from=0 to=200
HTTP/1.1 101 Web Socket Protocol Handshake\r
Connection: Upgrade\r
Date: Sun, 21 Feb 2021 11:12:52 GMT\r
Sec-WebSocket-Accept: BP6ittw+k5e5oS6cER0MLUZUsew=\r
Server: Kaazing Gateway\r
Upgrade: websocket\r
\r
12345
> 2021/02/21 14:16:07.983052  length=12 from=157 to=168
...M..*....G< 2021/02/21 14:16:08.164349  length=8 from=201 to=208
..12345
12345
> 2021/02/21 14:16:09.676664  length=6 from=169 to=174
....G_< 2021/02/21 14:16:09.782588  length=2 from=209 to=210

Try something like websocat -t - --ws-c-uri=ws://127.0.0.1:3000/ws/?transport=websocket ws-c:cmd:'socat -v - tcp:127.0.0.1:3000' and post the output here.

TomzBench commented 1 year ago

I'm trying to connect to a websocket created by nodejs "socket.io" library. I'm not sure if this is supported.

However, running your diagnostic command i get an output like:

websocat -t - --ws-c-uri=ws://127.0.0.1:8080 ws-c:cmd:'socat -v - tcp:127.0.0.1:8080'
> 2023/07/06 15:35:22.442670  length=153 from=0 to=152
GET / HTTP/1.1\r
Host: 127.0.0.1:8080\r
Connection: Upgrade\r
Upgrade: websocket\r
Sec-WebSocket-Version: 13\r
Sec-WebSocket-Key: IrnBRf/QYCq8xIUkmrNT/Q==\r
\r
websocat: WebSocketError: WebSocket protocol error
websocat: error running

EDIT - looks like socket.io is a layer on top of websocket spec so I guess I shouldn't expect this tool to work with socket.io

nickwales commented 12 months ago

Having a similar issue here, I'm using envoy in front of websocketd. Going direct works but it fails when going through envoy with:

websocat ws://localhost:8443 
websocat: WebSocketError: I/O failure
websocat: error running
websocat -t - --ws-c-uri=ws://localhost:8443 ws-c:cmd:'socat -v - tcp:localhost:8443'
> 2023/11/28 22:35:00.000380333  length=153 from=0 to=152
GET / HTTP/1.1\r
Host: localhost:8443\r
Connection: Upgrade\r
Upgrade: websocket\r
Sec-WebSocket-Version: 13\r
Sec-WebSocket-Key: mP/nZJG8um2oNnO9F9xLtg==\r
\r
< 2023/11/28 22:35:00.000382770  length=181 from=0 to=180
HTTP/1.1 101 Switching Protocols\r
upgrade: websocket\r
connection: Upgrade\r
sec-websocket-accept: XyGPfQtog75rP2zpjzZSRtm5KdI=\r
date: Wed, 29 Nov 2023 04:34:59 GMT\r
server: envoy\r
\r
< 2023/11/28 22:35:00.000399233  length=3 from=181 to=183
..11
< 2023/11/28 22:35:01.000432914  length=3 from=184 to=186
..22
vi commented 11 months ago

@nickwales The reply looks OK at the first glance. And I see 1 and 2 arriving - I assume ..1 is socat's output and the final 1 is websocat's output.

~Does second invocation also produces WebSocketError: I/O failure or it is just the first one?~ Probably "no".

~Maybe you can also include tcpdump of traffic on port 8443 and/or use socat -v -x (instead of just -v).~

Note: as alternative to cmd:'socat -v -x - tcp:localhost:8443' you can use log:tcp:127.0.0.1:8443.


Now I noticed "localhost". Currently this is problematic if your server does not also listen for IPv6 version of localhost properly.

\ ws://localhost may fail if service is not listening both IPv4 and IPv6 properly. There is a workaround based on ws-c:tcp: if needed. Or just use ws://127.0.0.1.

Maybe I'll introduce a warning if user tries ws://localhost, as fixing this is only planned for a redesigned Websocat.

nickwales commented 11 months ago

@vi 127.0.0.1 works! Really appreciate the help!