Skip to content

x/net/websocket: sockets served with http.ListenAndServeTLS have SSL handshake problems with most clients #11602

Closed
@integrii

Description

@integrii

I originally posted this here but was asked to make a new issue.

Websockets served over ListenAndServeTLS in the example program below fail to initiate SSL connections on nearly every client I have tried. Regular non-TLS connections work fine, and websites served also seem to be working fine over TLS. This is occurring on go version 1.4.2 x64.

Safari (version 9.0) works just great, but Firefox (version 39.0) and Chrome do not (version 43 on OSX). It also appears that javax.websocket gets a 403.

I get this error in Chrome:

WebSocket connection to 'wss://my.domain.com:8000/copyTest' failed: Error during WebSocket handshake: Unexpected response code: 403

Nothing is produced at the go terminal, unless i hit it with javax.websocket - which produces this:

http: TLS handshake error from 127.0.0.1:44249: tls: first record does not look like a TLS handshake

In Safari I get the expected result in the javascript console:

[Log] sent data:test (testClient.html, line 31)
[Log] got data:test (testClient.html, line 19)

in Firefox I get a 403 similar to Chrome and the console shows this:

GET 
https://my.domain.com:8000/copyTest [HTTP/1.1 403 Forbidden 3ms]
"got error:" error { target: WebSocket, isTrusted: true, currentTarget: WebSocket, eventPhase: 2, bubbles: false, cancelable: false, defaultPrevented: false, timeStamp: 1435967773819792, originalTarget: WebSocket, explicitOriginalTarget: WebSocket, NONE: 0 } testClient.html:22:5
"got close:" close { target: WebSocket, isTrusted: true, wasClean: false, code: 1006, reason: "", currentTarget: WebSocket, eventPhase: 2, bubbles: false, cancelable: false, defaultPrevented: false, timeStamp: 1435967773821310 } testClient.html:25:5

Here is some go code to serve TLS websockets. sub in your own cert.key and cert.pem files.

package main

import (
    "golang.org/x/net/websocket"
    "io"
    "log"
    "net/http"
)

func copyTest(ws *websocket.Conn) {
    io.Copy(ws, ws)
}

func main() {

    // setup http handler
    http.Handle("/copyTest", websocket.Handler(copyTest))

    // start secure websocket server
    log.Println("Listening for secure websocket connections on localhost port 8000...")
    if err := http.ListenAndServeTLS(":8000", "cert.pem", "cert.key", nil); err != nil {
        panic("ListenAndServeTLS Error: " + err.Error())
    }
}

Here is a javascript client. Sub in the proper domain name for your cert instead of localhost and connect using it. Results will be written to the javascript console.

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8" />
        <title>Websocket connector</title>
        <script src="http://code.jquery.com/jquery-compat-git.js">
        </script>
    </head>
    <body>
            <input id="name" type="text" />
            <button id="sendBtn">send</a>

        <script>
            var ws = new WebSocket("wss://localhost:8000/copyTest");

            ws.onmessage = function(e) {
                console.log("got data:" + e.data);
            };
            ws.onerror = function(e) {
                console.log("got error:", e);
            };
            ws.onclose = function(e) {
                console.log("got close:", e);
            };

            $('#sendBtn').click(function(){
                var data = $('#name').val();
                ws.send(data);
                console.log("sent data:" + data);
            });
        </script>
    </body>
</html>

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions