Files
protocol/xtls/tls.go
2024-06-13 23:08:01 -07:00

76 lines
1.9 KiB
Go

package xtls
import (
"crypto/tls"
"crypto/x509"
"errors"
"fmt"
"os"
)
type Config struct {
Enabled bool `json:"enabled" yaml:"enabled"`
// Skip server certificate and domain verification.
Insecure bool `json:"insecure" yaml:"insecure" config:"allowempty"`
// Server name indication for TLS.
ServerName string `json:"serverName" yaml:"server_name" config:"allowempty"`
// File containing trusted root certificates for verifying the server.
CACertFile string `json:"caCertFile" yaml:"ca_cert_file" config:"allowempty"`
// File containing client certificate (public key), to present to the
// server. Must also provide @ClientKey option.
ClientCertFile string `json:"clientCertFile" yaml:"client_cert_file" config:"allowempty"`
// File containing client private key, to present to the server.
// Must also provide @ClientCert option.
ClientKeyFile string `json:"clientKeyFile" yaml:"client_key_file" config:"allowempty"`
}
var ErrFailedToLoadCACert = errors.New("failed to load CACertificate")
func (c *Config) ClientTLSConfig() (*tls.Config, error) {
tlsConf := tls.Config{
MinVersion: tls.VersionTLS12,
}
if c.ClientCertFile != "" {
// Load the client certificates from disk
certificate, err := tls.LoadX509KeyPair(c.ClientCertFile, c.ClientKeyFile)
if err != nil {
return nil, fmt.Errorf("could not load client key pair: %w", err)
}
tlsConf.Certificates = []tls.Certificate{certificate}
}
if c.Insecure {
// #nosec G402
tlsConf.InsecureSkipVerify = true
}
if c.ServerName != "" {
tlsConf.ServerName = c.ServerName
}
if c.CACertFile != "" {
// Create a certificate pool from the certificate authority
certPool := x509.NewCertPool()
ca, err := os.ReadFile(c.CACertFile)
if err != nil {
return nil, fmt.Errorf("could not read ca certificate: %w", err)
}
if ok := certPool.AppendCertsFromPEM(ca); !ok {
return nil, ErrFailedToLoadCACert
}
tlsConf.RootCAs = certPool
}
return &tlsConf, nil
}