KalyanChakravarthy.net

Thoughts, stories and ideas.

TLS webserver server in Go

Simple HTTP Server

Getting a go webserver is incredibly simple. All it takes is this

mux := http.NewServeMux()  
mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request)  
s := &http.Server{  
    Addr: ":8080",
    Handle: mux,
}
s.ListenAndServe()  

TLS Server

If all you wanted was to run it with single certificate pair, its straight forward

s.ListenAndServeTLS("certFile", "keyFile")  

TLS Server with multiple certificates

Default server.ListenAndServe is not good for running an http server with multiple certificates.

This was a particular use case I needed to solve

Now why would you want to do that?

  • Its needed for running single server for multiple domains having different certificates.
  • Public certificate for user and other private set of certificates for external or third-party services.
  • A secondary certificate as backup when primary one expires.

Achieving this with custom certificates is a bit more tricky. Here are the steps:

First, setup TLS config

tlsConfig := &tls.Config{  
    NextProtos:               []string{"http/1.1"},
    MinVersion:               tls.VersionTLS10,
    SessionTicketsDisabled:   true,
    PreferServerCipherSuites: true,
}

Load certificate pairs

certPair, err := tls.LoadX509KeyPair("cert", "key")  
tlsConfig.Certificates = []tlsConfig.Certificates{ certPair }

Build name to certificate mapping

tlsConfig.BuildNameToCertificate()  

Create the server object and start it

tlsServer := &http.Server{  
Addr:         "0.0.0.0:8080",  
    Handler:      myHandler,
    TLSConfig:    tlsConfig,
    TLSNextProto: make(map[string]func(*http.Server, *tls.Conn, http.Handler), 0),
}

tlsServer.ListenAndServe()  

TLS with letsencrypt

Go's nifty crypto library is built with letsencrypt's ACME (Automated Certificate Management Environment) protocol in mind.

more information about it is here - https://kalyanchakravarthy.net/blog/https-server-with-go-letsencrypt/