net/http and TLS; aborts connection from browser

blov · 2017-02-16 08:00:10 · 636 次点击    
这是一个分享于 2017-02-16 08:00:10 的资源,其中的信息可能已经有所发展或是发生改变。

tl;dr: Has anyone run into a problem with Go net/http and TLS where browser connections abort but other clients are fine?

I haven't dug into the root cause for this, but I was curious if anyone else has seen this behavior. I have a standard net/http server with organization-signed key and cert PEM files (and intermediate keys), set up to communicate over TLS only. It works reasonably well with browsers and a Citrix NetScaler -- except when it doesn't. I'll get as fewer than two (2) in 10,000 requests abort under normal conditions, with the occasional spike to 400 or more in 10,000 requests.

The Go server is behind the NetScaler which provides a real certificate (signed by DigiCert, wildcard name) and proxies requests. TLS is used between the Go server and the NetScaler because of security requirements around the information transferred.

When running with TLS in my development environment, I can get an "Abort" on an HTTPS connection within the first 250 (or so) requests from Firefox. When running with TLS in either my development environment or against the production server, and when I'm using Python as my client, I get no errors with about 250,000 requests (parallel clients). When running without TLS in standard HTTP/1.1 mode, there are no errors with any client (Firefox or Python).

The Go version is 1.7.5 Darwin and also 1.7.5 Linux. I've experienced the error both with the default Go muxer and httprouter.

For the curious, here's the function used to initialize the HTTP server with TLS:

func ListenAndServe(addr string, handler http.Handler) error {
    // get the read timeout:  this keeps the HTTP server from hanging
    readTimeout := Config.GetDuration("server.timeout.read")

    // get the write timeout:  this lets HTTP clients timeout if we don't reply in a timely manner
    writeTimeout := Config.GetDuration("server.timeout.write")

    // TLS configuration
    var tlsConfig *tls.Config
    var certFile, keyFile string
    isTls := Config.GetBool("server.tls")
    if isTls {
        certFile = Config.GetProperty("server.tls.cert")
        keyFile = Config.GetProperty("server.tls.key")
        insecureSkipVerify := Config.GetBool("server.tls.insecure.cert")
        cert, err := tls.LoadX509KeyPair(certFile, keyFile)
        if err != nil {
            os.Stderr.WriteString("FATAL: error building TLS configuration: " + string(err.Error()) + "\n")
            exit(2)
        }
        tlsConfig = &tls.Config{
            Certificates:       []tls.Certificate{cert},
            InsecureSkipVerify: insecureSkipVerify,
        }
    }

    // configure the server
    server := &http.Server{
        ReadTimeout:  readTimeout * time.Second,
        WriteTimeout: writeTimeout * time.Second,
        Addr:         addr,
        TLSConfig:    tlsConfig,
        Handler:      handler,
    }

    // serve with or without TLS, based on configuration
    if isTls {
        return server.ListenAndServeTLS(certFile, keyFile)
    } else {
        return server.ListenAndServe()
    }
}

Edit: code formatting


入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

636 次点击  
加入收藏 微博
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传