cloudflared-mirror/tlsconfig/tlsconfig.go

104 lines
3.2 KiB
Go
Raw Normal View History

2017-10-16 11:44:03 +00:00
// Package tlsconfig provides convenience functions for configuring TLS connections from the
// command line.
package tlsconfig
import (
"crypto/tls"
"crypto/x509"
"io/ioutil"
2018-02-20 21:13:56 +00:00
"net"
2017-10-16 11:44:03 +00:00
2018-02-20 21:13:56 +00:00
log "github.com/sirupsen/logrus"
2017-10-16 11:44:03 +00:00
cli "gopkg.in/urfave/cli.v2"
)
// CLIFlags names the flags used to configure TLS for a command or subsystem.
// The nil value for a field means the flag is ignored.
type CLIFlags struct {
Cert string
Key string
ClientCert string
RootCA string
}
// GetConfig returns a TLS configuration according to the flags defined in f and
// set by the user.
func (f CLIFlags) GetConfig(c *cli.Context) *tls.Config {
config := &tls.Config{}
if c.IsSet(f.Cert) && c.IsSet(f.Key) {
cert, err := tls.LoadX509KeyPair(c.String(f.Cert), c.String(f.Key))
if err != nil {
log.WithError(err).Fatal("Error parsing X509 key pair")
}
config.Certificates = []tls.Certificate{cert}
config.BuildNameToCertificate()
}
if c.IsSet(f.ClientCert) {
// set of root certificate authorities that servers use if required to verify a client certificate
// by the policy in ClientAuth
config.ClientCAs = LoadCert(c.String(f.ClientCert))
// server's policy for TLS Client Authentication. Default is no client cert
config.ClientAuth = tls.RequireAndVerifyClientCert
}
// set of root certificate authorities that clients use when verifying server certificates
if c.IsSet(f.RootCA) {
config.RootCAs = LoadCert(c.String(f.RootCA))
}
return config
}
// LoadCert creates a CertPool containing all certificates in a PEM-format file.
func LoadCert(certPath string) *x509.CertPool {
caCert, err := ioutil.ReadFile(certPath)
if err != nil {
log.WithError(err).Fatalf("Error reading certificate %s", certPath)
}
ca := x509.NewCertPool()
if !ca.AppendCertsFromPEM(caCert) {
log.WithError(err).Fatalf("Error parsing certificate %s", certPath)
}
return ca
}
2018-02-20 21:13:56 +00:00
func LoadOriginCertsPool() *x509.CertPool {
// First, obtain the system certificate pool
certPool, systemCertPoolErr := x509.SystemCertPool()
if systemCertPoolErr != nil {
log.Warn("error obtaining the system certificates: %s", systemCertPoolErr)
certPool = x509.NewCertPool()
}
// Next, append the Cloudflare CA pool into the system pool
if !certPool.AppendCertsFromPEM([]byte(cloudflareRootCA)) {
log.Warn("could not append the CF certificate to the system certificate pool")
if systemCertPoolErr != nil { // Obtaining both certificates failed; this is a fatal error
log.WithError(systemCertPoolErr).Fatalf("Error loading the certificate pool")
}
}
// Finally, add the Hello certificate into the pool (since it's self-signed)
helloCertificate, err := GetHelloCertificateX509()
if err != nil {
log.Warn("error obtaining the Hello server certificate")
}
certPool.AddCert(helloCertificate)
return certPool
}
func CreateTunnelConfig(c *cli.Context, addrs []string) *tls.Config {
tlsConfig := CLIFlags{RootCA: "cacert"}.GetConfig(c)
if tlsConfig.RootCAs == nil {
tlsConfig.RootCAs = GetCloudflareRootCA()
tlsConfig.ServerName = "cftunnel.com"
} else if len(addrs) > 0 {
// Set for development environments and for testing specific origintunneld instances
tlsConfig.ServerName, _, _ = net.SplitHostPort(addrs[0])
}
return tlsConfig
}