mirror of
https://github.com/caddyserver/caddy.git
synced 2025-05-24 02:02:26 -04:00
caddytls: Don't publish ECH configs if other records don't exist
Some checks failed
Tests / test (./cmd/caddy/caddy, ~1.24.1, ubuntu-latest, 0, 1.24, linux) (push) Failing after 1m27s
Tests / test (s390x on IBM Z) (push) Has been skipped
Tests / goreleaser-check (push) Has been skipped
Cross-Build / build (~1.24.1, 1.24, aix) (push) Successful in 1m17s
Cross-Build / build (~1.24.1, 1.24, darwin) (push) Successful in 1m23s
Cross-Build / build (~1.24.1, 1.24, dragonfly) (push) Successful in 1m22s
Cross-Build / build (~1.24.1, 1.24, freebsd) (push) Successful in 1m14s
Cross-Build / build (~1.24.1, 1.24, illumos) (push) Successful in 1m15s
Cross-Build / build (~1.24.1, 1.24, linux) (push) Successful in 1m13s
Cross-Build / build (~1.24.1, 1.24, netbsd) (push) Successful in 1m26s
Cross-Build / build (~1.24.1, 1.24, openbsd) (push) Successful in 1m13s
Cross-Build / build (~1.24.1, 1.24, solaris) (push) Successful in 1m16s
Cross-Build / build (~1.24.1, 1.24, windows) (push) Successful in 1m13s
Lint / lint (ubuntu-latest, linux) (push) Successful in 1m51s
Lint / govulncheck (push) Successful in 1m7s
Tests / test (./cmd/caddy/caddy, ~1.24.1, macos-14, 0, 1.24, mac) (push) Has been cancelled
Tests / test (./cmd/caddy/caddy.exe, ~1.24.1, windows-latest, True, 1.24, windows) (push) Has been cancelled
Lint / lint (macos-14, mac) (push) Has been cancelled
Lint / lint (windows-latest, windows) (push) Has been cancelled
Some checks failed
Tests / test (./cmd/caddy/caddy, ~1.24.1, ubuntu-latest, 0, 1.24, linux) (push) Failing after 1m27s
Tests / test (s390x on IBM Z) (push) Has been skipped
Tests / goreleaser-check (push) Has been skipped
Cross-Build / build (~1.24.1, 1.24, aix) (push) Successful in 1m17s
Cross-Build / build (~1.24.1, 1.24, darwin) (push) Successful in 1m23s
Cross-Build / build (~1.24.1, 1.24, dragonfly) (push) Successful in 1m22s
Cross-Build / build (~1.24.1, 1.24, freebsd) (push) Successful in 1m14s
Cross-Build / build (~1.24.1, 1.24, illumos) (push) Successful in 1m15s
Cross-Build / build (~1.24.1, 1.24, linux) (push) Successful in 1m13s
Cross-Build / build (~1.24.1, 1.24, netbsd) (push) Successful in 1m26s
Cross-Build / build (~1.24.1, 1.24, openbsd) (push) Successful in 1m13s
Cross-Build / build (~1.24.1, 1.24, solaris) (push) Successful in 1m16s
Cross-Build / build (~1.24.1, 1.24, windows) (push) Successful in 1m13s
Lint / lint (ubuntu-latest, linux) (push) Successful in 1m51s
Lint / govulncheck (push) Successful in 1m7s
Tests / test (./cmd/caddy/caddy, ~1.24.1, macos-14, 0, 1.24, mac) (push) Has been cancelled
Tests / test (./cmd/caddy/caddy.exe, ~1.24.1, windows-latest, True, 1.24, windows) (push) Has been cancelled
Lint / lint (macos-14, mac) (push) Has been cancelled
Lint / lint (windows-latest, windows) (push) Has been cancelled
Publishing a DNS record for a name that doesn't have any could make wildcards ineffective, which would be surprising for site owners and could lead to downtime.
This commit is contained in:
parent
2ac09fdb20
commit
1f8dab572c
@ -163,6 +163,7 @@ func (app *App) automaticHTTPSPhase1(ctx caddy.Context, repl *caddy.Replacer) er
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// trim the list of domains covered by wildcards, if configured
|
||||||
if srv.AutoHTTPS.PreferWildcard {
|
if srv.AutoHTTPS.PreferWildcard {
|
||||||
wildcards := make(map[string]struct{})
|
wildcards := make(map[string]struct{})
|
||||||
for d := range serverDomainSet {
|
for d := range serverDomainSet {
|
||||||
@ -184,6 +185,17 @@ func (app *App) automaticHTTPSPhase1(ctx caddy.Context, repl *caddy.Replacer) er
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// build the list of domains that could be used with ECH (if enabled)
|
||||||
|
// so the TLS app can know to publish ECH configs for them; we do this
|
||||||
|
// after trimming domains covered by wildcards because, presumably,
|
||||||
|
// if the user wants to use wildcard certs, they also want to use the
|
||||||
|
// wildcard for ECH, rather than individual subdomains
|
||||||
|
echDomains := make([]string, 0, len(serverDomainSet))
|
||||||
|
for d := range serverDomainSet {
|
||||||
|
echDomains = append(echDomains, d)
|
||||||
|
}
|
||||||
|
app.tlsApp.RegisterServerNames(echDomains)
|
||||||
|
|
||||||
// nothing more to do here if there are no domains that qualify for
|
// nothing more to do here if there are no domains that qualify for
|
||||||
// automatic HTTPS and there are no explicit TLS connection policies:
|
// automatic HTTPS and there are no explicit TLS connection policies:
|
||||||
// if there is at least one domain but no TLS conn policy (F&&T), we'll
|
// if there is at least one domain but no TLS conn policy (F&&T), we'll
|
||||||
@ -205,7 +217,6 @@ func (app *App) automaticHTTPSPhase1(ctx caddy.Context, repl *caddy.Replacer) er
|
|||||||
// for all the hostnames we found, filter them so we have
|
// for all the hostnames we found, filter them so we have
|
||||||
// a deduplicated list of names for which to obtain certs
|
// a deduplicated list of names for which to obtain certs
|
||||||
// (only if cert management not disabled for this server)
|
// (only if cert management not disabled for this server)
|
||||||
var echDomains []string
|
|
||||||
if srv.AutoHTTPS.DisableCerts {
|
if srv.AutoHTTPS.DisableCerts {
|
||||||
logger.Warn("skipping automated certificate management for server because it is disabled", zap.String("server_name", srvName))
|
logger.Warn("skipping automated certificate management for server because it is disabled", zap.String("server_name", srvName))
|
||||||
} else {
|
} else {
|
||||||
@ -232,14 +243,10 @@ func (app *App) automaticHTTPSPhase1(ctx caddy.Context, repl *caddy.Replacer) er
|
|||||||
}
|
}
|
||||||
|
|
||||||
uniqueDomainsForCerts[d] = struct{}{}
|
uniqueDomainsForCerts[d] = struct{}{}
|
||||||
echDomains = append(echDomains, d)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// let the TLS server know we have some hostnames that could be protected behind ECH
|
|
||||||
app.tlsApp.RegisterServerNames(echDomains)
|
|
||||||
|
|
||||||
// tell the server to use TLS if it is not already doing so
|
// tell the server to use TLS if it is not already doing so
|
||||||
if srv.TLSConnPolicies == nil {
|
if srv.TLSConnPolicies == nil {
|
||||||
srv.TLSConnPolicies = caddytls.ConnectionPolicies{new(caddytls.ConnectionPolicy)}
|
srv.TLSConnPolicies = caddytls.ConnectionPolicies{new(caddytls.ConnectionPolicy)}
|
||||||
|
@ -639,8 +639,16 @@ func (dnsPub *ECHDNSPublisher) PublishECHConfigList(ctx context.Context, innerNa
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
// get any existing HTTPS record for this domain, and augment
|
relName := libdns.RelativeName(domain+".", zone)
|
||||||
// our ech SvcParamKey with any other existing SvcParams
|
// TODO: libdns.RelativeName should probably return "@" instead of "". (The latest commits of libdns do this, so remove this logic once upgraded.)
|
||||||
|
if relName == "" {
|
||||||
|
relName = "@"
|
||||||
|
}
|
||||||
|
|
||||||
|
// get existing records for this domain; we need to make sure another
|
||||||
|
// record exists for it so we don't accidentally trample a wildcard; we
|
||||||
|
// also want to get any HTTPS record that may already exist for it so
|
||||||
|
// we can augment the ech SvcParamKey with any other existing SvcParams
|
||||||
recs, err := dnsPub.provider.GetRecords(ctx, zone)
|
recs, err := dnsPub.provider.GetRecords(ctx, zone)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
dnsPub.logger.Error("unable to get existing DNS records to publish ECH data to HTTPS DNS record",
|
dnsPub.logger.Error("unable to get existing DNS records to publish ECH data to HTTPS DNS record",
|
||||||
@ -648,17 +656,29 @@ func (dnsPub *ECHDNSPublisher) PublishECHConfigList(ctx context.Context, innerNa
|
|||||||
zap.Error(err))
|
zap.Error(err))
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
relName := libdns.RelativeName(domain+".", zone)
|
|
||||||
// TODO: libdns.RelativeName should probably return "@" instead of "".
|
|
||||||
if relName == "" {
|
|
||||||
relName = "@"
|
|
||||||
}
|
|
||||||
var httpsRec libdns.Record
|
var httpsRec libdns.Record
|
||||||
|
var nameHasExistingRecord bool
|
||||||
for _, rec := range recs {
|
for _, rec := range recs {
|
||||||
if rec.Name == relName && rec.Type == "HTTPS" && (rec.Target == "" || rec.Target == ".") {
|
if rec.Name == relName {
|
||||||
|
nameHasExistingRecord = true
|
||||||
|
if rec.Type == "HTTPS" && (rec.Target == "" || rec.Target == ".") {
|
||||||
httpsRec = rec
|
httpsRec = rec
|
||||||
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
if !nameHasExistingRecord {
|
||||||
|
// Turns out if you publish a DNS record for a name that doesn't have any DNS record yet,
|
||||||
|
// any wildcard records won't apply for the name anymore, meaning if a wildcard A/AAAA record
|
||||||
|
// is used to resolve the domain to a server, publishing an HTTPS record could break resolution!
|
||||||
|
// In theory, this should be a non-issue, at least for A/AAAA records, if the HTTPS record
|
||||||
|
// includes ipv[4|6]hint SvcParamKeys,
|
||||||
|
dnsPub.logger.Warn("domain does not have any existing records, so skipping publication of HTTPS record",
|
||||||
|
zap.String("domain", domain),
|
||||||
|
zap.String("relative_name", relName),
|
||||||
|
zap.String("zone", zone))
|
||||||
|
continue
|
||||||
|
}
|
||||||
params := make(svcParams)
|
params := make(svcParams)
|
||||||
if httpsRec.Value != "" {
|
if httpsRec.Value != "" {
|
||||||
params, err = parseSvcParams(httpsRec.Value)
|
params, err = parseSvcParams(httpsRec.Value)
|
||||||
|
@ -563,7 +563,7 @@ func (t *TLS) Manage(names []string) error {
|
|||||||
// (keeping only the hotsname) and filters IP addresses, which can't be
|
// (keeping only the hotsname) and filters IP addresses, which can't be
|
||||||
// used with ECH.
|
// used with ECH.
|
||||||
//
|
//
|
||||||
// EXPERIMENTAL: This function and its behavior are subject to change.
|
// EXPERIMENTAL: This function and its semantics/behavior are subject to change.
|
||||||
func (t *TLS) RegisterServerNames(dnsNames []string) {
|
func (t *TLS) RegisterServerNames(dnsNames []string) {
|
||||||
t.serverNamesMu.Lock()
|
t.serverNamesMu.Lock()
|
||||||
for _, name := range dnsNames {
|
for _, name := range dnsNames {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user