Skip to content

Instantly share code, notes, and snippets.

@regeda
Last active February 19, 2020 14:15
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save regeda/3417a47d6a36482df71b18e6abd8daca to your computer and use it in GitHub Desktop.
Save regeda/3417a47d6a36482df71b18e6abd8daca to your computer and use it in GitHub Desktop.
Test different TLS options in a server written in Go
package main
import (
"bufio"
"crypto/tls"
"crypto/x509"
"errors"
"flag"
"fmt"
"io"
"io/ioutil"
"log"
"net"
"strings"
)
var (
caFile = flag.String("ca-file", "", "Path to the CA cert file")
certFile = flag.String("cert-file", "", "Path to the certificate file")
keyFile = flag.String("key-file", "", "Path to the private key file")
authType = flag.String("auth-type", "no_client_cert", "Possible values are: "+authTypesHelp)
listen = flag.String("listen", "127.0.0.1:7777", "The address to listen")
)
var (
authTypesHelp = genAuthTypesHelp()
authTypes = map[string]tls.ClientAuthType{
"no_client_cert": tls.NoClientCert,
"request_client_cert": tls.RequestClientCert,
"require_any_client_cert": tls.RequireAnyClientCert,
"verify_client_cert_if_given": tls.VerifyClientCertIfGiven,
"require_and_verify_client_cert": tls.RequireAndVerifyClientCert,
}
)
func genAuthTypesHelp() string {
s := make([]string, 0, len(authTypes))
for k := range authTypes {
s = append(s, k)
}
return strings.Join(s, ",")
}
func main() {
flag.Parse()
cert, err := tls.LoadX509KeyPair(*certFile, *keyFile)
if err != nil {
log.Fatal("cert could not be loaded:", err)
}
clientsCAs := x509.NewCertPool()
caCert, err := ioutil.ReadFile(*caFile)
if err != nil {
log.Fatal("cacert file could not be read:", err)
}
if !clientsCAs.AppendCertsFromPEM(caCert) {
log.Fatal("cacert file could not be installed")
}
clientAuth, err := parseClientAuth(*authType)
if err != nil {
log.Println("parsing auth type failed, use default:", err)
}
cfg := tls.Config{
Certificates: []tls.Certificate{cert},
ClientAuth: clientAuth,
ClientCAs: clientsCAs,
MinVersion: tls.VersionTLS12,
}
log.Println("listen address:", *listen)
l, err := tls.Listen("tcp", *listen, &cfg)
if err != nil {
log.Fatal("tls listen failed:", err)
}
for {
conn, err := l.Accept()
if err != nil {
log.Fatal("listener accept failed:", err)
}
log.Println("client connected:", conn.RemoteAddr())
go talk(conn)
}
}
func parseClientAuth(t string) (tls.ClientAuthType, error) {
if v, ok := authTypes[t]; ok {
return v, nil
}
return tls.NoClientCert, fmt.Errorf("unknown auth type %s", t)
}
func talk(c net.Conn) {
remoteAddr := c.RemoteAddr()
defer func() {
log.Println("good bye:", remoteAddr)
_ = c.Close()
}()
r := bufio.NewReader(c)
for {
line, _, err := r.ReadLine()
if err != nil {
if !errors.Is(err, io.EOF) {
log.Printf("%s: read failed: %s", remoteAddr, err)
}
return
}
log.Printf("%s: %s", remoteAddr, line)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment