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):
Question: Why is there a question mark?
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."
If at all still relevent:
http.ListenAndServeTLS(...)
takes certificate and private key not public & private key.
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)
}