Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

websocket and tls: cannot send messages to wss connection (SNI problem?)

253 views
Skip to first unread message

EL

unread,
Jun 8, 2021, 3:02:04 AM6/8/21
to
Hello,

I have a problem with a websocket client that I try to develop. The
connection to the server can be established and I get a confirming
message, but afterwards I can send whatever I want and never get a
response. According to the documentation of the websocket API I send
correct messages and sometimes I even get a response, but most of the
time not.

Its the kraken websocket API, which is behind cloudflare and requires
SNI: https://docs.kraken.com/websockets/

I have made up a script to isolate the issue. For simplicity I left out
any json parsing/generation. It is best [source]d into a live tclsh:

===== test-ws.tcl script below ===================================
package require tls
package require websocket

::http::register https 443 [list ::tls::socket -autoservername yes]

proc handle {sock type msg} {
puts "received \[$type\] with message \[$msg\]"
switch -- $type {
text {
if {[string match {*"status":"online"*} $msg]} {
global connected
set connected yes
}
}
}
}

set s [websocket::open wss://ws.kraken.com handle]

vwait connected

websocket::send $s text {{"event":"ping"}}

====== test-ws.tcl script above ==================================

The last line

% websocket::send $s text {{"event":"ping"}}

should lead to a "pong" response on the socket, according to the
documentation https://docs.kraken.com/websockets/#message-ping
And sometimes I even *do* receive the pong in my now endlessly thousands
of attempts... but most of the time not. Needless to say that it doesn't
make sense to go further and send other messages, when not even a simple
"ping" works.
The [websocket::send] itself does not generate an error. It appears as
if the message could have been sent (number of bytes is the result).

According to the docs, TLS with SNI support is a requirement, and the
servers are behind cloudflare. To my knowledge, the -autoservername flag
in [tls::socket] takes care of SNI, and since it is [http::register]ed,
it should be fine on http level (connection can be established, after
all). But I am not sure whether this extends to the websocket after
upgrade from http... could that be the problem?
Or what else could be the problem? Apart from the server not working,
but I think this is not likely.

BTW, the websocket package works on other wss:// websocket servers, so
websocket and TLS is in general not a problem. Just on this particular
kraken API behind its cloudflare stuff it is.


Thanks in advance,

--
EL

stefan

unread,
Jun 11, 2021, 8:32:03 AM6/11/21
to
On Tuesday, June 8, 2021 at 9:02:04 AM UTC+2, EL wrote:
Hi!

> I have made up a script to isolate the issue. For simplicity I left out
> any json parsing/generation. It is best [source]d into a live tclsh:

Using the script, and tclkit equipped with:

% package req tls
1.7.17
% package req websocket
1.4
% package req Tcl
8.6.9

I cannot reproduce this issue and I receive the expected pong messages on every attempt:

received [connect] with message []
received [text] with message [{"connectionID":2857532312017364341,"event":"systemStatus","status":"online","version":"1.8.6"}]

etc.

> Or what else could be the problem?

What is on your version menu?

Stefan

EL

unread,
Jun 11, 2021, 9:22:04 AM6/11/21
to
On 11.06.2021 14:32, stefan wrote:

> Using the script, and tclkit equipped with:
>
> % package req tls
> 1.7.17
> % package req websocket
> 1.4
> % package req Tcl
> 8.6.9
>
> I cannot reproduce this issue and I receive the expected pong messages on every attempt:
>
> received [connect] with message []
> received [text] with message [{"connectionID":2857532312017364341,"event":"systemStatus","status":"online","version":"1.8.6"}]

That is not the "pong". That is the connect message, I receive it as well.
The pong should come after the following line was issued:

% websocket::send $s text {{"event":"ping","reqid":42}}

And it looks like

received [text] with message {"event":"pong","reqid":42}

> What is on your version menu?

Initially I had
tls 1.7.16
websocket 1.4
Tcl 8.6.9

But now I tried with tls 1.7.22, websocket 1.4 and Tcl 8.6.9 and 8.6.11.
Same result, no "pong".


--
EL

stefan

unread,
Jun 11, 2021, 10:53:25 AM6/11/21
to
Oh, yes, my bad. So, I can confirm. There is no pong. Weird enough, capturing using Wireshark does not show me any activity from the Kraken peer (there should be heartbeats being sent). The connection is reported CONNECTED, but then no activity server -> client activity.

Mmmmh. Stefan

stefan

unread,
Jun 11, 2021, 11:43:38 AM6/11/21
to
The endpoint works using websocat, for example:

$ websocat -k wss://ws.kraken.com
{"connectionID":13785474401592893310,"event":"systemStatus","status":"online","version":"1.8.6"}
{"event":"ping","reqid": 42}
{"event":"pong","reqid":42}

(no heartbeats, though, either)

At least, this gives a starting point to dissect the PDU flows websocat/ TclTLS.

Stefan

EL

unread,
Jun 11, 2021, 4:02:05 PM6/11/21
to
On 11.06.2021 17:43, stefan wrote:
> The endpoint works using websocat, for example:
>
> $ websocat -k wss://ws.kraken.com
> {"connectionID":13785474401592893310,"event":"systemStatus","status":"online","version":"1.8.6"}
> {"event":"ping","reqid": 42}
> {"event":"pong","reqid":42}

Ah interesting. This might be the chance for a workaround, by using
websocat as a proxy:

$ websocat -v -t tcp-listen:127.0.0.1:1234 wss://ws.kraken.com &
$ rlwrap tclsh
% proc handle {sock} {
gets $sock line
puts $line
}
% set s [socket -async localhost 1234]
% fileevent $s readable [list handle $s]
% fconfigure $s -translation auto -buffering line
% puts $s {{"event":"ping","reqid":42}}
{"event":"pong","reqid":42}

It works, at least to some extend. The connection is rather unstable, it
gets lost after a few minutes. Maybe its necessary to send pings every n
seconds, to keep it alive...

> (no heartbeats, though, either)

According to their documentation, the heartbeat is not sent until you
subscribe to a channel. And then it is sent every 1s, if no subscription
payload arrives within 1s.

Funny API, indeed. But well...

> At least, this gives a starting point to dissect the PDU flows websocat/ TclTLS.

Maybe for a wizzard in the tls/http/websocket packages. I have hoped to
find one here ;). Presumably it has something to do with SNI and the
socket-takeover, but well, it can be anything else, too.

For me it would take too much time to get into these packages and debug
the issue. I resorted to pull the REST API now... not as elegant as I
would have liked it, but so far it works for me. If I experience trouble
with this approach, I'll maybe look closer into the workaround above, or
maybe I'll look into creating an extension that wraps libwebsockets
(https://libwebsockets.org/). /If/ this library works with this
particular server.

Thank you for the websocat tip, I didn't know that it exists :). I am
sure that it will be as helpful as socat in some circumstances.


--
EL
0 new messages