如何在Golang Web服务器上设置HTTPS?

I'm reading https://www.kaihag.com/https-and-go/ and bought an SSL certificate from Comodo which they emailed me a .zip file. All of the files I have so far look like this

csr.pem
private-key.pem
website.com.crt
website.com.ca-bundle
website.com.zip

The above website wants me to concatenate 3 .pem files which I don't have. Incidentally what is the reason the .pem files need to concatenated? Using the above files which haven't been modified, how can https be set up on a golang webserver?

Use https://golang.org/pkg/net/http/#ListenAndServeTLS

http.HandleFunc("/", handler)
log.Printf("About to listen on 10443. Go to https://127.0.0.1:10443/")
err := http.ListenAndServeTLS(":10443", "cert.pem", "key.pem", nil)
log.Fatal(err)

This isn't really a go question, but the intermediate certs are required because computers only store root certs. By concatenating them you put them all in one file so the browser gets all certs - this is a required step otherwise your server will fail on certain devices. Your cert provider will provide instructions for doing this. For go you need one cert file and one private key file.

https://kb.wisc.edu/page.php?id=18923

Here are some instructions for comodo for combining the certs (doesn't matter which server is used, the process is the same):

https://support.comodo.com/index.php?/Knowledgebase/Article/View/1091/37/certificate-installation--nginx

You need http.ListenAndServeTLS

package main

import (
    // "fmt"
    // "io"
    "net/http"
    "log"
)

func HelloServer(w http.ResponseWriter, req *http.Request) {
    w.Header().Set("Content-Type", "text/plain")
    w.Write([]byte("This is an example server.
"))
    // fmt.Fprintf(w, "This is an example server.
")
    // io.WriteString(w, "This is an example server.
")
}

func main() {
http.HandleFunc("/hello", HelloServer)
    err := http.ListenAndServeTLS(":443", "server.crt", "server.key", nil)
    if err != nil {
        log.Fatal("ListenAndServe: ", err)
    }
}

Here’s a snippet: https://gist.github.com/denji/12b3a568f092ab951456

The library https://github.com/adrianosela/sslmgr abstracts away the whole concept of keys and certificates. All you need is for the server to be reachable by the hostname (i.e. your DNS must point yourdomain.com to your-public-ip). You can even disable SSL for local development as follows:

ss, err := sslmgr.NewServer(sslmgr.ServerConfig{
    Hostnames: []string{os.Getenv("yourdomain.com")},
    Handler:   h,
    ServeSSLFunc: func() bool {
        return strings.ToLower(os.Getenv("PROD")) == "true"
    },
})
if err != nil {
    log.Fatal(err)
}
ss.ListenAndServe()

Here is my finding and I would like to share because it took me a few hours as all available installation guides were for Nginx and Apache HTTP configurations, not for the Golang Web Server.

Environments:

  • SSL certificate from Comodo / Sectigo
  • Gin-gonic as middleware

Issue:

  • It was working fine on Chrome/Firefox on Mac but was giving me a CORS error on Windows Firefox. Later, it was found that it was not really a CORS related matter, and I diagnosed my ubuntu server of the SSL validity by using https://www.digicert.com/help. The result was, "The certificate is not signed by a trusted authority (checking against Mozilla's root store)".

Solution:

The solution is to concatenate the following certificates by using a text editor and name it as you'd like. I saved it as "my_domain.txt".

  • my_domain.ca-bundle (which includes one root and two intermediate certs)
  • my_domain.crt (the main cert for my domain)

Then run it like this,

router.RunTLS(":"+os.Getenv("PORT"), "../my_domain.txt", "../my_private_key.txt")

Hope it helped!