-
-
Save jehiah/a5b508b8f4efad08e67a to your computer and use it in GitHub Desktop.
A Go TLS server that auto-generates Self-Signed certificates matching the presented clientHelloInfo.ServerName.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
// This TLS server generates self signed certificates on-the-fly with a DNSName matching | |
// the ServerName in the clientHello on connection | |
import ( | |
"crypto/rand" | |
"crypto/rsa" | |
"crypto/tls" | |
"crypto/x509" | |
"crypto/x509/pkix" | |
"encoding/pem" | |
"flag" | |
"log" | |
"math/big" | |
"net/http" | |
"time" | |
) | |
func generateDerCert(privKey *rsa.PrivateKey, expiration time.Time, domain string) ([]byte, error) { | |
serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128) | |
serialNumber, err := rand.Int(rand.Reader, serialNumberLimit) | |
if err != nil { | |
return nil, err | |
} | |
if expiration.IsZero() { | |
expiration = time.Now().Add(time.Minute) | |
} | |
template := x509.Certificate{ | |
SerialNumber: serialNumber, | |
Subject: pkix.Name{ | |
CommonName: "Autogenerated Cert", | |
}, | |
NotBefore: time.Now(), | |
NotAfter: expiration, | |
KeyUsage: x509.KeyUsageKeyEncipherment, | |
BasicConstraintsValid: true, | |
DNSNames: []string{domain}, | |
} | |
return x509.CreateCertificate(rand.Reader, &template, &template, &privKey.PublicKey, privKey) | |
} | |
func generatePemCert(privKey *rsa.PrivateKey, domain string) ([]byte, error) { | |
derBytes, err := generateDerCert(privKey, time.Time{}, domain) | |
if err != nil { | |
return nil, err | |
} | |
return pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: derBytes}), nil | |
} | |
func pemEncode(key *rsa.PrivateKey) []byte { | |
pemBlock := &pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(key)} | |
return pem.EncodeToMemory(pemBlock) | |
} | |
func NewSelfSignedCert(clientHello *tls.ClientHelloInfo) (*tls.Certificate, error) { | |
rsaPrivKey, err := rsa.GenerateKey(rand.Reader, 2048) | |
if err != nil { | |
return nil, err | |
} | |
tempCertPEM, err := generatePemCert(rsaPrivKey, clientHello.ServerName) | |
if err != nil { | |
return nil, err | |
} | |
rsaPrivPEM := pemEncode(rsaPrivKey) | |
cert, err := tls.X509KeyPair(tempCertPEM, rsaPrivPEM) | |
return &cert, err | |
} | |
func main() { | |
addr := flag.String("addr", ":443", "interface to listen on") | |
flag.Parse() | |
cert, err := NewSelfSignedCert(&tls.ClientHelloInfo{ServerName: "localhost"}) | |
if err != nil { | |
log.Panicf("err %s", err) | |
} | |
config := &tls.Config{ | |
Certificates: []tls.Certificate{*cert}, | |
GetCertificate: NewSelfSignedCert, | |
MinVersion: tls.VersionTLS10, | |
MaxVersion: tls.VersionTLS12, | |
} | |
server := &http.Server{ | |
Addr: *addr, | |
TLSConfig: config, | |
} | |
log.Printf("listening to %v", *addr) | |
err = server.ListenAndServeTLS("", "") | |
if err != nil { | |
log.Printf("%s", err) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment