diff options
author | Matthew Holt <mholt@users.noreply.github.com> | 2020-02-06 13:00:41 -0700 |
---|---|---|
committer | Matthew Holt <mholt@users.noreply.github.com> | 2020-02-06 13:00:41 -0700 |
commit | 4a07a5d41e0f54d1a1ec998b9d956ccf2a880d90 (patch) | |
tree | 3578f3d22c6498afa83c9b7c400c8175b4dbe0c8 /caddyconfig/httpcaddyfile | |
parent | b81ae38686fb9fb133a0308294b3dd898b769dac (diff) |
caddyfile: tls: Ensure there is always a catch-all conn policy (#3005)
If user provides their own certs or makes any hostname-specific TLS
connection policy, it means that no TLS connection would be served for
any other hostnames, even though you'd expect that TLS is enabled for
them, too. So now we append a catch-all conn policy if none exist, which
allows all ClientHellos to be matched and served.
We also fix the consolidation of automation policies, which previously
gobbled up automation policies without hosts in favor of automation
policies with hosts. Instead of a host-specific policy eating up an
identical catch-all policy, the catch-all policy eats up the identical
host-specific policy, ensuring that the policy is applied to all hosts
which need it.
See also:
https://caddy.community/t/v2-automatic-https-certificate-errors/6847/9?u=matt
Diffstat (limited to 'caddyconfig/httpcaddyfile')
-rw-r--r-- | caddyconfig/httpcaddyfile/httptype.go | 51 |
1 files changed, 48 insertions, 3 deletions
diff --git a/caddyconfig/httpcaddyfile/httptype.go b/caddyconfig/httpcaddyfile/httptype.go index 5620c2e..0cd2fca 100644 --- a/caddyconfig/httpcaddyfile/httptype.go +++ b/caddyconfig/httpcaddyfile/httptype.go @@ -372,6 +372,7 @@ func (st *ServerType) serversFromPairings( srv.AutoHTTPS.Skip = append(srv.AutoHTTPS.Skip, autoHTTPSQualifiedHosts...) } else if cpVals, ok := sblock.pile["tls.connection_policy"]; ok { // tls connection policies + var hasCatchAll bool for _, cpVal := range cpVals { cp := cpVal.Value.(*caddytls.ConnectionPolicy) @@ -381,14 +382,31 @@ func (st *ServerType) serversFromPairings( return nil, err } - // TODO: are matchers needed if every hostname of the config is matched? + // TODO: are matchers needed if every hostname of the resulting config is matched? if len(hosts) > 0 { cp.MatchersRaw = caddy.ModuleMap{ "sni": caddyconfig.JSON(hosts, warnings), // make sure to match all hosts, not just auto-HTTPS-qualified ones } + } else { + hasCatchAll = true } + srv.TLSConnPolicies = append(srv.TLSConnPolicies, cp) } + + // a catch-all is necessary to ensure TLS can be offered to + // all hostnames of the server; even though only one policy + // is needed to enable TLS for the server, that policy might + // apply to only certain TLS handshakes; but when using the + // Caddyfile, user would expect all handshakes to at least + // have a matching connection policy, so here we append a + // catch-all/default policy if there isn't one already (it's + // important that it goes at the end) - see issue #3004: + // https://github.com/caddyserver/caddy/issues/3004 + if !hasCatchAll { + srv.TLSConnPolicies = append(srv.TLSConnPolicies, new(caddytls.ConnectionPolicy)) + } + // TODO: consolidate equal conn policies } @@ -569,14 +587,41 @@ func consolidateAutomationPolicies(aps []caddytls.AutomationPolicy) []caddytls.A if j == i { continue } - if reflect.DeepEqual(aps[i].ManagementRaw, aps[j].ManagementRaw) { - aps[i].Hosts = append(aps[i].Hosts, aps[j].Hosts...) + + // if they're exactly equal in every way, just keep one of them + if reflect.DeepEqual(aps[i], aps[j]) { aps = append(aps[:j], aps[j+1:]...) i-- break } + + // if the policy is the same, we can keep just one, but we have + // to be careful which one we keep; if only one has any hostnames + // defined, then we need to keep the one without any hostnames, + // otherwise the one without any hosts (a catch-all) would be + // eaten up by the one with hosts; and if both have hosts, we + // need to combine their lists + if reflect.DeepEqual(aps[i].ManagementRaw, aps[j].ManagementRaw) && + aps[i].ManageSync == aps[j].ManageSync { + if len(aps[i].Hosts) == 0 && len(aps[j].Hosts) > 0 { + aps = append(aps[:j], aps[j+1:]...) + } else if len(aps[i].Hosts) > 0 && len(aps[j].Hosts) == 0 { + aps = append(aps[:i], aps[i+1:]...) + } else { + aps[i].Hosts = append(aps[i].Hosts, aps[j].Hosts...) + aps = append(aps[:j], aps[j+1:]...) + } + i-- + break + } } } + + // ensure any catch-all policies go last + sort.SliceStable(aps, func(i, j int) bool { + return len(aps[i].Hosts) > len(aps[j].Hosts) + }) + return aps } |