From faf0399e80391ba5229321e2ee7d05262e4cc531 Mon Sep 17 00:00:00 2001 From: Matt Holt Date: Wed, 10 May 2023 14:29:29 -0600 Subject: caddytls: Configurable fallback SNI (#5527) * Initial implementation of fallback_sni * Apply upstream patch --- caddyconfig/httpcaddyfile/httptype.go | 11 +++++++++-- caddyconfig/httpcaddyfile/options.go | 1 + go.mod | 2 +- go.sum | 4 ++-- modules/caddytls/connpolicy.go | 13 +++++++++++++ 5 files changed, 26 insertions(+), 5 deletions(-) diff --git a/caddyconfig/httpcaddyfile/httptype.go b/caddyconfig/httpcaddyfile/httptype.go index 18f65bb..aec3d79 100644 --- a/caddyconfig/httpcaddyfile/httptype.go +++ b/caddyconfig/httpcaddyfile/httptype.go @@ -413,6 +413,7 @@ func (st *ServerType) serversFromPairings( ) (map[string]*caddyhttp.Server, error) { servers := make(map[string]*caddyhttp.Server) defaultSNI := tryString(options["default_sni"], warnings) + fallbackSNI := tryString(options["fallback_sni"], warnings) httpPort := strconv.Itoa(caddyhttp.DefaultHTTPPort) if hp, ok := options["http_port"].(int); ok { @@ -570,6 +571,11 @@ func (st *ServerType) serversFromPairings( cp.DefaultSNI = defaultSNI break } + if h == fallbackSNI { + hosts = append(hosts, "") + cp.FallbackSNI = fallbackSNI + break + } } if len(hosts) > 0 { @@ -578,6 +584,7 @@ func (st *ServerType) serversFromPairings( } } else { cp.DefaultSNI = defaultSNI + cp.FallbackSNI = fallbackSNI } // only append this policy if it actually changes something @@ -703,8 +710,8 @@ func (st *ServerType) serversFromPairings( // policy missing for any HTTPS-enabled hosts, if so, add it... maybe? if addressQualifiesForTLS && !hasCatchAllTLSConnPolicy && - (len(srv.TLSConnPolicies) > 0 || !autoHTTPSWillAddConnPolicy || defaultSNI != "") { - srv.TLSConnPolicies = append(srv.TLSConnPolicies, &caddytls.ConnectionPolicy{DefaultSNI: defaultSNI}) + (len(srv.TLSConnPolicies) > 0 || !autoHTTPSWillAddConnPolicy || defaultSNI != "" || fallbackSNI != "") { + srv.TLSConnPolicies = append(srv.TLSConnPolicies, &caddytls.ConnectionPolicy{DefaultSNI: defaultSNI, FallbackSNI: fallbackSNI}) } // tidy things up a bit diff --git a/caddyconfig/httpcaddyfile/options.go b/caddyconfig/httpcaddyfile/options.go index 4e5212b..f9d0b96 100644 --- a/caddyconfig/httpcaddyfile/options.go +++ b/caddyconfig/httpcaddyfile/options.go @@ -33,6 +33,7 @@ func init() { RegisterGlobalOption("grace_period", parseOptDuration) RegisterGlobalOption("shutdown_delay", parseOptDuration) RegisterGlobalOption("default_sni", parseOptSingleString) + RegisterGlobalOption("fallback_sni", parseOptSingleString) RegisterGlobalOption("order", parseOptOrder) RegisterGlobalOption("storage", parseOptStorage) RegisterGlobalOption("storage_clean_interval", parseOptDuration) diff --git a/go.mod b/go.mod index 2e02d09..003da3f 100644 --- a/go.mod +++ b/go.mod @@ -7,7 +7,7 @@ require ( github.com/Masterminds/sprig/v3 v3.2.3 github.com/alecthomas/chroma/v2 v2.7.0 github.com/aryann/difflib v0.0.0-20210328193216-ff5ff6dc229b - github.com/caddyserver/certmagic v0.17.3-0.20230507010158-25b55042e516 + github.com/caddyserver/certmagic v0.17.3-0.20230510193943-53140d52202c github.com/dustin/go-humanize v1.0.1 github.com/go-chi/chi v4.1.2+incompatible github.com/google/cel-go v0.14.0 diff --git a/go.sum b/go.sum index 2cff5ff..afd511b 100644 --- a/go.sum +++ b/go.sum @@ -97,8 +97,8 @@ github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= github.com/boltdb/bolt v1.3.1/go.mod h1:clJnj/oiGkjum5o1McbSZDSLxVThjynRyGBgiAx27Ps= -github.com/caddyserver/certmagic v0.17.3-0.20230507010158-25b55042e516 h1:D+jLysrPbU0EN+IbLvPuGIpvCi6wgoPmQiKxAQCh+gI= -github.com/caddyserver/certmagic v0.17.3-0.20230507010158-25b55042e516/go.mod h1:e0YLTnXIopZ05bBWCLzpIf1Yvk27Q90FGUmGowFRDY8= +github.com/caddyserver/certmagic v0.17.3-0.20230510193943-53140d52202c h1:pEMS0l8kE/5xxrncv+Qq81fzr29R+zk++E7KAYiyBe4= +github.com/caddyserver/certmagic v0.17.3-0.20230510193943-53140d52202c/go.mod h1:e0YLTnXIopZ05bBWCLzpIf1Yvk27Q90FGUmGowFRDY8= github.com/casbin/casbin/v2 v2.1.2/go.mod h1:YcPU1XXisHhLzuxH9coDNf2FbKpjGlbCg3n9yuLkIJQ= github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM= github.com/cenkalti/backoff/v4 v4.2.0 h1:HN5dHm3WBOgndBH6E8V0q2jIYIR3s9yglV8k/+MN3u4= diff --git a/modules/caddytls/connpolicy.go b/modules/caddytls/connpolicy.go index bce69bc..46a8eda 100644 --- a/modules/caddytls/connpolicy.go +++ b/modules/caddytls/connpolicy.go @@ -159,6 +159,18 @@ type ConnectionPolicy struct { // is no policy configured for the empty SNI value. DefaultSNI string `json:"default_sni,omitempty"` + // FallbackSNI becomes the ServerName in a ClientHello if + // the original ServerName doesn't match any certificates + // in the cache. The use cases for this are very niche; + // typically if a client is a CDN and passes through the + // ServerName of the downstream handshake but can accept + // a certificate with the origin's hostname instead, then + // you would set this to your origin's hostname. Note that + // Caddy must be managing a certificate for this name. + // + // This feature is EXPERIMENTAL and subject to change or removal. + FallbackSNI string `json:"fallback_sni,omitempty"` + // Also known as "SSLKEYLOGFILE", TLS secrets will be written to // this file in NSS key log format which can then be parsed by // Wireshark and other tools. This is INSECURE as it allows other @@ -216,6 +228,7 @@ func (p *ConnectionPolicy) buildStandardTLSConfig(ctx caddy.Context) error { cfg.CertSelection = p.CertSelection } cfg.DefaultServerName = p.DefaultSNI + cfg.FallbackServerName = p.FallbackSNI return cfg.GetCertificate(hello) }, MinVersion: tls.VersionTLS12, -- cgit v1.2.3