Skip to content

Instantly share code, notes, and snippets.

@LivingInSyn
Created January 24, 2019 15:25
Show Gist options
  • Save LivingInSyn/b2634518f654c0e877224bb03e2ed3bb to your computer and use it in GitHub Desktop.
Save LivingInSyn/b2634518f654c0e877224bb03e2ed3bb to your computer and use it in GitHub Desktop.
package main
import (
"bufio"
"crypto/tls"
"crypto/x509"
"io/ioutil"
"net"
"strings"
"time"
log "github.com/sirupsen/logrus"
)
var rootCAs *x509.CertPool
var serverCert tls.Certificate
func main() {
//load certs
serverCert, _ = tls.LoadX509KeyPair("server.crt", "server.key")
//get root ca
caAddr := "ca.crt"
rootCAs = configureRootCAs(&caAddr)
//build server config
serverConf := &tls.Config{
GetCertificate: func(hi *tls.ClientHelloInfo) (*tls.Certificate, error) {
return &serverCert, nil
},
GetConfigForClient: func(hi *tls.ClientHelloInfo) (*tls.Config, error) {
serverConf := &tls.Config{
GetCertificate: func(hi *tls.ClientHelloInfo) (*tls.Certificate, error) {
return &serverCert, nil
},
MinVersion: tls.VersionTLS12,
ClientAuth: tls.RequireAndVerifyClientCert,
ClientCAs: rootCAs,
VerifyPeerCertificate: getClientValidator(hi),
}
return serverConf, nil
},
}
ln, err := tls.Listen("tcp", ":55554", serverConf)
if err != nil {
log.Error(err)
panic("quitting")
}
for {
conn, err := ln.Accept()
if err != nil {
panic(err)
}
go handleConnection(conn)
}
}
func getClientValidator(helloInfo *tls.ClientHelloInfo) func([][]byte, [][]*x509.Certificate) error {
// return func(rawCerts [][]byte, verifiedChains [][]*x509.Certificate) error {
// return nil
// }
log.Debug("Inside get client validator")
return func(rawCerts [][]byte, verifiedChains [][]*x509.Certificate) error {
//copied from the default options in src/crypto/tls/handshake_server.go, 680 (go 1.11)
//but added DNSName
log.Debug("tls config in validator")
opts := x509.VerifyOptions{
Roots: rootCAs,
CurrentTime: time.Now(),
Intermediates: x509.NewCertPool(),
KeyUsages: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth},
DNSName: strings.Split(helloInfo.Conn.RemoteAddr().String(), ":")[0],
}
_, err := verifiedChains[0][0].Verify(opts)
return err
}
}
func handleConnection(conn net.Conn) {
defer conn.Close()
r := bufio.NewReader(conn)
for {
msg, err := r.ReadString('\n')
if err != nil {
log.Println(err)
return
}
println(msg)
n, err := conn.Write([]byte("world\n"))
if err != nil {
log.Println(n, err)
return
}
}
}
func configureRootCAs(caCertPathFlag *string) *x509.CertPool {
// also load as bytes for x509
// Read in the cert file
x509certs, err := ioutil.ReadFile(*caCertPathFlag)
if err != nil {
log.Fatalf("Failed to append certificate to RootCAs: %v", err)
}
// Get the SystemCertPool, continue with an empty pool on error
rootCAs, _ := x509.SystemCertPool()
if rootCAs == nil {
rootCAs = x509.NewCertPool()
}
// append the local cert to the in-memory system CA pool
if ok := rootCAs.AppendCertsFromPEM(x509certs); !ok {
log.Warning("No certs appended, using system certs only")
}
return rootCAs
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment