Sunday, April 3, 2016

Simple golang HTTPS web server example

Simple golang HTTPS web server example

Generate a Private Key and a CSR:

Use this method if you want to use HTTPS (HTTP over TLS) to secure your Apache HTTP or Nginx web server, and you want to use a Certificate Authority (CA) to issue the SSL certificate. The CSR that is generated can be sent to a CA to request the issuance of a CA-signed SSL certificate. If your CA supports SHA-2, add the -sha256 option to sign the CSR with SHA-2.

# openssl req -newkey rsa:2048 -nodes -subj "/C=US/ST=New York/L=Brooklyn/O=Example Brooklyn Company/CN=examplebrooklyn.com" -keyout mydomain.key -out mydomain.csr

Note: The -newkey rsa:2048 option specifies that the key should be 2048-bit, generated using the RSA algorithm.
Note: The -nodes option specifies that the private key should not be encrypted with a pass phrase.
Note: The -new option, which is not included here but implied, indicates that a CSR is being generated.

Generate a Self-Signed Certificate:

Use this method if you want to use HTTPS (HTTP over TLS) to secure your Apache HTTP or Nginx web server, and you do not require that your certificate is signed by a CA.

This command creates a 2048-bit private key (domain.key) and a self-signed certificate (domain.crt) from scratch:

# openssl req -newkey rsa:2048 -nodes -subj "/C=US/ST=New York/L=Brooklyn/O=Example Brooklyn Company/CN=examplebrooklyn.com" -keyout mydomain.key -x509 -days 365 -out mydomain.crt

Version 1 - srv.go:

package main

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

func HelloServer(w http.ResponseWriter, req *http.Request) {
    io.WriteString(w, "hello, world!\n")
}

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

Run the code:

# go run srv.go

Then, go to:

https://192.168.5.1/hello

Use curl command to access:

# curl -k https://192.168.5.1/hello

hello, world!

Forces curl to use SSL version 3 when negotiating with a remote SSL server:

# curl -k -3 https://192.168.5.1/hello

Here, we try to access port 443 by HTTP protocol:

# curl -k http://192.168.5.1:443/hello | od -A n -t x1

15 03 01 00 02 02 0a

the above 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."

Version 2:

package main

import (
    "fmt"
    "net/http"
)

const (
    PORT       = ":8443"
    PRIV_KEY   = "./mydomain.key"
    CERT_KEY = "./mydomain.crt"
)

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

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

Then, go to:

https://192.168.5.1/hello

Reference:

https://gist.github.com/denji/12b3a568f092ab951456

http://stackoverflow.com/questions/23494082/golang-listenandservetls-returns-data-when-not-using-https-in-the-browser

https://github.com/nareix/tls-example

https://en.wikipedia.org/wiki/X.509

https://www.digitalocean.com/community/tutorials/openssl-essentials-working-with-ssl-certificates-private-keys-and-csrs

No comments: