Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Golang ListenAndServeTLS returns data when not using https in the browser

Tags:

http

https

ssl

go

The following is my tls backend:

package main

import (
    "fmt"
    "net/http"
)

const (
    PORT       = ":8443"
    PRIV_KEY   = "./private_key"
    PUBLIC_KEY = "./public_key"
)

func rootHander(w http.ResponseWriter, r *http.Request) {
    fmt.Fprint(w, "Nobody should read this.")
}

func main() {
    http.HandleFunc("/", rootHander)
    err := http.ListenAndServeTLS(PORT, PUBLIC_KEY, PRIV_KEY, nil)
    if err != nil {
        fmt.Printf("main(): %s\n", err)
    }
}

The keys are generated using these two lines:

openssl genrsa -out private_key 2048
openssl req -new -x509 -key private_key -out public_key -days 365

When I start the tls server, and visit the site with a browser (https://example.com:8443) I get the expected result, after ignoring the browser warning:

Nobody should read this.

So far everything is cool.

Now, when I point my browser to http://example.com:8443 (notice that http is used, not https) I get the following result for Firfox (Chrome does the same, but downloading the site):

using http

Question: Why is there a question mark?

like image 572
Kiril Avatar asked May 06 '14 11:05

Kiril


3 Answers

Here is some code to redirect requests on port 80 to 443 and to serve up tls certificates using a CA like lets encrypt. I know that with lets encrypt (letsencrypt.org) you want to reference the resulting fullchain.pem file as well as the privkey.pem.

The biggest problem with self signing is that it wont be very viable in production. With golang we really configure our applications quite specifically so something simple like attaching tls certs properly is an important topic when we are ready to launch.

here some simple code I have actually used to launch a static site:

package main
import (
"net/http"
"log"
)
func redirect(w http.ResponseWriter, req *http.Request) {
 // remove/add not default ports from req.Host
 target := "https://" + req.Host + req.URL.Path
 if len(req.URL.RawQuery) > 0 {
     target += "?" + req.URL.RawQuery
 }
 log.Printf("redirect to: %s", target)
 http.Redirect(w, req, target,
         http.StatusTemporaryRedirect)
 }


func main() {
 //define a variable for the FileServer directory in this case ./static/
 var fs = http.FileServer(http.Dir("static"))
 //express the handler function
 http.Handle("/", fs)
 //We should redirect requests on port 80
 go http.ListenAndServe(":80", http.HandlerFunc(redirect))
 //finally we Listen for requests and serve them up on a specific port
 http.ListenAndServeTLS(":443", "fullchain.pem", "privkey.pem", nil)

 }
like image 120
Sm0k3Scr33n Avatar answered Oct 17 '22 16:10

Sm0k3Scr33n


If at all still relevent:

http.ListenAndServeTLS(...) takes certificate and private key not public & private key.

like image 21
Pawel Kraszewski Avatar answered Oct 17 '22 17:10

Pawel Kraszewski


If you pipe the output into od, curl -k -3 http://localhost:8443 | od -A n -t x1, you get the following sequence of bytes 15 03 01 00 02 02 0a which is rendered/handled by the browser.

Which, according to https://code.google.com/p/go/issues/detail?id=2253, is TLS for "I didn't understand what you said."

like image 30
Anthony Sterling Avatar answered Oct 17 '22 17:10

Anthony Sterling