From be53e432fcac0a9b9accbc36885304639e8ca70b Mon Sep 17 00:00:00 2001 From: Francis Lavoie Date: Wed, 22 Feb 2023 13:41:01 -0500 Subject: caddytls: Relax the warning for on-demand (#5384) --- modules/caddytls/tls.go | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) (limited to 'modules/caddytls') diff --git a/modules/caddytls/tls.go b/modules/caddytls/tls.go index 8051653..92004b8 100644 --- a/modules/caddytls/tls.go +++ b/modules/caddytls/tls.go @@ -22,6 +22,7 @@ import ( "log" "net/http" "runtime/debug" + "strings" "sync" "time" @@ -259,7 +260,17 @@ func (t *TLS) Start() error { if t.Automation.OnDemand == nil || (t.Automation.OnDemand.Ask == "" && t.Automation.OnDemand.RateLimit == nil) { for _, ap := range t.Automation.Policies { - if ap.OnDemand { + isWildcardOrDefault := false + if len(ap.Subjects) == 0 { + isWildcardOrDefault = true + } + for _, sub := range ap.Subjects { + if strings.HasPrefix(sub, "*") { + isWildcardOrDefault = true + break + } + } + if ap.OnDemand && isWildcardOrDefault { t.logger.Warn("YOUR SERVER MAY BE VULNERABLE TO ABUSE: on-demand TLS is enabled, but no protections are in place", zap.String("docs", "https://caddyserver.com/docs/automatic-https#on-demand-tls")) break -- cgit v1.2.3 From b97c76fb4789b8da0b80f5a2c1c1c5bebba163b5 Mon Sep 17 00:00:00 2001 From: Matthew Holt Date: Tue, 14 Mar 2023 10:02:44 -0600 Subject: caddytls: Require 'ask' endpoint for on-demand TLS --- modules/caddytls/automation.go | 32 ++++++++++++++++++-------------- 1 file changed, 18 insertions(+), 14 deletions(-) (limited to 'modules/caddytls') diff --git a/modules/caddytls/automation.go b/modules/caddytls/automation.go index 7f216d5..526aef5 100644 --- a/modules/caddytls/automation.go +++ b/modules/caddytls/automation.go @@ -168,22 +168,26 @@ func (ap *AutomationPolicy) Provision(tlsApp *TLS) error { // on-demand TLS var ond *certmagic.OnDemandConfig if ap.OnDemand { + // ask endpoint is now required after a number of negligence cases causing abuse + if tlsApp.Automation == nil || tlsApp.Automation.OnDemand == nil || tlsApp.Automation.OnDemand.Ask == "" { + return fmt.Errorf("on-demand TLS cannot be enabled without an 'ask' endpoint to prevent abuse; please refer to documentation for details") + } ond = &certmagic.OnDemandConfig{ DecisionFunc: func(name string) error { - // if an "ask" endpoint was defined, consult it first - if tlsApp.Automation != nil && - tlsApp.Automation.OnDemand != nil && - tlsApp.Automation.OnDemand.Ask != "" { - if err := onDemandAskRequest(tlsApp.logger, tlsApp.Automation.OnDemand.Ask, name); err != nil { - // distinguish true errors from denials, because it's important to log actual errors - if !errors.Is(err, errAskDenied) { - tlsApp.logger.Error("request to 'ask' endpoint failed", - zap.Error(err), - zap.String("endpoint", tlsApp.Automation.OnDemand.Ask), - zap.String("domain", name)) - } - return err + if err := onDemandAskRequest(tlsApp.logger, tlsApp.Automation.OnDemand.Ask, name); err != nil { + // distinguish true errors from denials, because it's important to elevate actual errors + if errors.Is(err, errAskDenied) { + tlsApp.logger.Debug("certificate issuance denied", + zap.String("ask_endpoint", tlsApp.Automation.OnDemand.Ask), + zap.String("domain", name), + zap.Error(err)) + } else { + tlsApp.logger.Error("request to 'ask' endpoint failed", + zap.String("ask_endpoint", tlsApp.Automation.OnDemand.Ask), + zap.String("domain", name), + zap.Error(err)) } + return err } // check the rate limiter last because // doing so makes a reservation @@ -404,7 +408,7 @@ type OnDemandConfig struct { // issuance of certificates from handshakes. RateLimit *RateLimit `json:"rate_limit,omitempty"` - // If Caddy needs to obtain or renew a certificate + // REQUIRED. If Caddy needs to obtain/renew a certificate // during a TLS handshake, it will perform a quick // HTTP request to this URL to check if it should be // allowed to try to get a certificate for the name -- cgit v1.2.3 From a7af7c486e5240da974e02b7dfee9d265aaa654a Mon Sep 17 00:00:00 2001 From: Matthew Holt Date: Tue, 14 Mar 2023 10:29:27 -0600 Subject: caddytls: Allow on-demand w/o ask for internal-only --- modules/caddytls/automation.go | 76 +++++++++++++++++++++++------------------- 1 file changed, 42 insertions(+), 34 deletions(-) (limited to 'modules/caddytls') diff --git a/modules/caddytls/automation.go b/modules/caddytls/automation.go index 526aef5..fffc0a3 100644 --- a/modules/caddytls/automation.go +++ b/modules/caddytls/automation.go @@ -165,40 +165,6 @@ func (ap *AutomationPolicy) Provision(tlsApp *TLS) error { ap.storage = cmStorage } - // on-demand TLS - var ond *certmagic.OnDemandConfig - if ap.OnDemand { - // ask endpoint is now required after a number of negligence cases causing abuse - if tlsApp.Automation == nil || tlsApp.Automation.OnDemand == nil || tlsApp.Automation.OnDemand.Ask == "" { - return fmt.Errorf("on-demand TLS cannot be enabled without an 'ask' endpoint to prevent abuse; please refer to documentation for details") - } - ond = &certmagic.OnDemandConfig{ - DecisionFunc: func(name string) error { - if err := onDemandAskRequest(tlsApp.logger, tlsApp.Automation.OnDemand.Ask, name); err != nil { - // distinguish true errors from denials, because it's important to elevate actual errors - if errors.Is(err, errAskDenied) { - tlsApp.logger.Debug("certificate issuance denied", - zap.String("ask_endpoint", tlsApp.Automation.OnDemand.Ask), - zap.String("domain", name), - zap.Error(err)) - } else { - tlsApp.logger.Error("request to 'ask' endpoint failed", - zap.String("ask_endpoint", tlsApp.Automation.OnDemand.Ask), - zap.String("domain", name), - zap.Error(err)) - } - return err - } - // check the rate limiter last because - // doing so makes a reservation - if !onDemandRateLimiter.Allow() { - return fmt.Errorf("on-demand rate limit exceeded") - } - return nil - }, - } - } - // we don't store loaded modules directly in the certmagic config since // policy provisioning may happen more than once (during auto-HTTPS) and // loading a module clears its config bytes; thus, load the module and @@ -255,6 +221,40 @@ func (ap *AutomationPolicy) Provision(tlsApp *TLS) error { storage = tlsApp.ctx.Storage() } + // on-demand TLS + var ond *certmagic.OnDemandConfig + if ap.OnDemand { + // ask endpoint is now required after a number of negligence cases causing abuse + if !ap.onlyInternalIssuer() && (tlsApp.Automation == nil || tlsApp.Automation.OnDemand == nil || tlsApp.Automation.OnDemand.Ask == "") { + return fmt.Errorf("on-demand TLS cannot be enabled without an 'ask' endpoint to prevent abuse; please refer to documentation for details") + } + ond = &certmagic.OnDemandConfig{ + DecisionFunc: func(name string) error { + if err := onDemandAskRequest(tlsApp.logger, tlsApp.Automation.OnDemand.Ask, name); err != nil { + // distinguish true errors from denials, because it's important to elevate actual errors + if errors.Is(err, errAskDenied) { + tlsApp.logger.Debug("certificate issuance denied", + zap.String("ask_endpoint", tlsApp.Automation.OnDemand.Ask), + zap.String("domain", name), + zap.Error(err)) + } else { + tlsApp.logger.Error("request to 'ask' endpoint failed", + zap.String("ask_endpoint", tlsApp.Automation.OnDemand.Ask), + zap.String("domain", name), + zap.Error(err)) + } + return err + } + // check the rate limiter last because + // doing so makes a reservation + if !onDemandRateLimiter.Allow() { + return fmt.Errorf("on-demand rate limit exceeded") + } + return nil + }, + } + } + template := certmagic.Config{ MustStaple: ap.MustStaple, RenewalWindowRatio: ap.RenewalWindowRatio, @@ -286,6 +286,14 @@ func (ap *AutomationPolicy) Provision(tlsApp *TLS) error { return nil } +func (ap *AutomationPolicy) onlyInternalIssuer() bool { + if len(ap.Issuers) != 1 { + return false + } + _, ok := ap.Issuers[0].(*InternalIssuer) + return ok +} + // DefaultIssuers returns empty Issuers (not provisioned) to be used as defaults. // This function is experimental and has no compatibility promises. func DefaultIssuers() []certmagic.Issuer { -- cgit v1.2.3 From 0cc49c053f77bf6efa8107fa50d2e256a91d0ff8 Mon Sep 17 00:00:00 2001 From: Matt Holt Date: Mon, 20 Mar 2023 12:06:00 -0600 Subject: caddytls: Zero out throttle window first (#5443) * caddytls: Zero out throttle window first * Don't error for on-demand Fixes https://github.com/caddyserver/caddy/commit/b97c76fb4789b8da0b80f5a2c1c1c5bebba163b5 --------- Co-authored-by: Francis Lavoie --- modules/caddytls/automation.go | 23 +++++++++++++++++++++-- modules/caddytls/tls.go | 15 ++------------- 2 files changed, 23 insertions(+), 15 deletions(-) (limited to 'modules/caddytls') diff --git a/modules/caddytls/automation.go b/modules/caddytls/automation.go index fffc0a3..1cfb28c 100644 --- a/modules/caddytls/automation.go +++ b/modules/caddytls/automation.go @@ -19,6 +19,7 @@ import ( "errors" "fmt" "net/http" + "strings" "time" "github.com/caddyserver/caddy/v2" @@ -224,8 +225,10 @@ func (ap *AutomationPolicy) Provision(tlsApp *TLS) error { // on-demand TLS var ond *certmagic.OnDemandConfig if ap.OnDemand { - // ask endpoint is now required after a number of negligence cases causing abuse - if !ap.onlyInternalIssuer() && (tlsApp.Automation == nil || tlsApp.Automation.OnDemand == nil || tlsApp.Automation.OnDemand.Ask == "") { + // ask endpoint is now required after a number of negligence cases causing abuse; + // but is still allowed for explicit subjects (non-wildcard, non-unbounded), + // and for the internal issuer since it doesn't cause ACME issuer pressure + if ap.isWildcardOrDefault() && !ap.onlyInternalIssuer() && (tlsApp.Automation == nil || tlsApp.Automation.OnDemand == nil || tlsApp.Automation.OnDemand.Ask == "") { return fmt.Errorf("on-demand TLS cannot be enabled without an 'ask' endpoint to prevent abuse; please refer to documentation for details") } ond = &certmagic.OnDemandConfig{ @@ -294,6 +297,22 @@ func (ap *AutomationPolicy) onlyInternalIssuer() bool { return ok } +// isWildcardOrDefault determines if the subjects include any wildcard domains, +// or is the "default" policy (i.e. no subjects) which is unbounded. +func (ap *AutomationPolicy) isWildcardOrDefault() bool { + isWildcardOrDefault := false + if len(ap.Subjects) == 0 { + isWildcardOrDefault = true + } + for _, sub := range ap.Subjects { + if strings.HasPrefix(sub, "*") { + isWildcardOrDefault = true + break + } + } + return isWildcardOrDefault +} + // DefaultIssuers returns empty Issuers (not provisioned) to be used as defaults. // This function is experimental and has no compatibility promises. func DefaultIssuers() []certmagic.Issuer { diff --git a/modules/caddytls/tls.go b/modules/caddytls/tls.go index 92004b8..486a58c 100644 --- a/modules/caddytls/tls.go +++ b/modules/caddytls/tls.go @@ -22,7 +22,6 @@ import ( "log" "net/http" "runtime/debug" - "strings" "sync" "time" @@ -182,8 +181,8 @@ func (t *TLS) Provision(ctx caddy.Context) error { onDemandRateLimiter.SetWindow(time.Duration(t.Automation.OnDemand.RateLimit.Interval)) } else { // remove any existing rate limiter - onDemandRateLimiter.SetMaxEvents(0) onDemandRateLimiter.SetWindow(0) + onDemandRateLimiter.SetMaxEvents(0) } // run replacer on ask URL (for environment variables) -- return errors to prevent surprises (#5036) @@ -260,17 +259,7 @@ func (t *TLS) Start() error { if t.Automation.OnDemand == nil || (t.Automation.OnDemand.Ask == "" && t.Automation.OnDemand.RateLimit == nil) { for _, ap := range t.Automation.Policies { - isWildcardOrDefault := false - if len(ap.Subjects) == 0 { - isWildcardOrDefault = true - } - for _, sub := range ap.Subjects { - if strings.HasPrefix(sub, "*") { - isWildcardOrDefault = true - break - } - } - if ap.OnDemand && isWildcardOrDefault { + if ap.OnDemand && ap.isWildcardOrDefault() { t.logger.Warn("YOUR SERVER MAY BE VULNERABLE TO ABUSE: on-demand TLS is enabled, but no protections are in place", zap.String("docs", "https://caddyserver.com/docs/automatic-https#on-demand-tls")) break -- cgit v1.2.3 From e16a886814d8cd43d545de38a4d6b98313fb31cb Mon Sep 17 00:00:00 2001 From: Francis Lavoie Date: Mon, 27 Mar 2023 17:16:22 -0400 Subject: caddytls: Eval replacer on automation policy subjects (#5459) Also renamed the field to SubjectsRaw, which can be considered a breaking change but I don't expect this to affect much. --- modules/caddytls/automation.go | 24 +++++++++++++++++++----- modules/caddytls/tls.go | 21 +++++++++++++-------- 2 files changed, 32 insertions(+), 13 deletions(-) (limited to 'modules/caddytls') diff --git a/modules/caddytls/automation.go b/modules/caddytls/automation.go index 1cfb28c..58ffe4c 100644 --- a/modules/caddytls/automation.go +++ b/modules/caddytls/automation.go @@ -85,7 +85,7 @@ type AutomationConfig struct { // TLS app to properly provision a new policy. type AutomationPolicy struct { // Which subjects (hostnames or IP addresses) this policy applies to. - Subjects []string `json:"subjects,omitempty"` + SubjectsRaw []string `json:"subjects,omitempty"` // The modules that may issue certificates. Default: internal if all // subjects do not qualify for public certificates; othewise acme and @@ -147,12 +147,21 @@ type AutomationPolicy struct { Issuers []certmagic.Issuer `json:"-"` Managers []certmagic.Manager `json:"-"` - magic *certmagic.Config - storage certmagic.Storage + subjects []string + magic *certmagic.Config + storage certmagic.Storage } // Provision sets up ap and builds its underlying CertMagic config. func (ap *AutomationPolicy) Provision(tlsApp *TLS) error { + // replace placeholders in subjects to allow environment variables + repl := caddy.NewReplacer() + subjects := make([]string, len(ap.SubjectsRaw)) + for i, sub := range ap.SubjectsRaw { + subjects[i] = repl.ReplaceAll(sub, "") + } + ap.subjects = subjects + // policy-specific storage implementation if ap.StorageRaw != nil { val, err := tlsApp.ctx.LoadModule(ap, "StorageRaw") @@ -289,6 +298,11 @@ func (ap *AutomationPolicy) Provision(tlsApp *TLS) error { return nil } +// Subjects returns the list of subjects with all placeholders replaced. +func (ap *AutomationPolicy) Subjects() []string { + return ap.subjects +} + func (ap *AutomationPolicy) onlyInternalIssuer() bool { if len(ap.Issuers) != 1 { return false @@ -301,10 +315,10 @@ func (ap *AutomationPolicy) onlyInternalIssuer() bool { // or is the "default" policy (i.e. no subjects) which is unbounded. func (ap *AutomationPolicy) isWildcardOrDefault() bool { isWildcardOrDefault := false - if len(ap.Subjects) == 0 { + if len(ap.subjects) == 0 { isWildcardOrDefault = true } - for _, sub := range ap.Subjects { + for _, sub := range ap.subjects { if strings.HasPrefix(sub, "*") { isWildcardOrDefault = true break diff --git a/modules/caddytls/tls.go b/modules/caddytls/tls.go index 486a58c..9b5b552 100644 --- a/modules/caddytls/tls.go +++ b/modules/caddytls/tls.go @@ -126,7 +126,12 @@ func (t *TLS) Provision(ctx caddy.Context) error { // special case; these will be loaded in later using our automation facilities, // which we want to avoid doing during provisioning if automateNames, ok := modIface.(*AutomateLoader); ok && automateNames != nil { - t.automateNames = []string(*automateNames) + repl := caddy.NewReplacer() + subjects := make([]string, len(*automateNames)) + for i, sub := range *automateNames { + subjects[i] = repl.ReplaceAll(sub, "") + } + t.automateNames = subjects } else { return fmt.Errorf("loading certificates with 'automate' requires array of strings, got: %T", modIface) } @@ -231,13 +236,13 @@ func (t *TLS) Validate() error { var hasDefault bool hostSet := make(map[string]int) for i, ap := range t.Automation.Policies { - if len(ap.Subjects) == 0 { + if len(ap.subjects) == 0 { if hasDefault { return fmt.Errorf("automation policy %d is the second policy that acts as default/catch-all, but will never be used", i) } hasDefault = true } - for _, h := range ap.Subjects { + for _, h := range ap.subjects { if first, ok := hostSet[h]; ok { return fmt.Errorf("automation policy %d: cannot apply more than one automation policy to host: %s (first match in policy %d)", i, h, first) } @@ -388,8 +393,8 @@ func (t *TLS) AddAutomationPolicy(ap *AutomationPolicy) error { // first see if existing is superset of ap for all names var otherIsSuperset bool outer: - for _, thisSubj := range ap.Subjects { - for _, otherSubj := range existing.Subjects { + for _, thisSubj := range ap.subjects { + for _, otherSubj := range existing.subjects { if certmagic.MatchWildcard(thisSubj, otherSubj) { otherIsSuperset = true break outer @@ -398,7 +403,7 @@ func (t *TLS) AddAutomationPolicy(ap *AutomationPolicy) error { } // if existing AP is a superset or if it contains fewer names (i.e. is // more general), then new AP is more specific, so insert before it - if otherIsSuperset || len(existing.Subjects) < len(ap.Subjects) { + if otherIsSuperset || len(existing.SubjectsRaw) < len(ap.SubjectsRaw) { t.Automation.Policies = append(t.Automation.Policies[:i], append([]*AutomationPolicy{ap}, t.Automation.Policies[i:]...)...) return nil @@ -420,10 +425,10 @@ func (t *TLS) getConfigForName(name string) *certmagic.Config { // public certificate or not. func (t *TLS) getAutomationPolicyForName(name string) *AutomationPolicy { for _, ap := range t.Automation.Policies { - if len(ap.Subjects) == 0 { + if len(ap.subjects) == 0 { return ap // no host filter is an automatic match } - for _, h := range ap.Subjects { + for _, h := range ap.subjects { if certmagic.MatchWildcard(name, h) { return ap } -- cgit v1.2.3 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 --- modules/caddytls/connpolicy.go | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'modules/caddytls') 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 From a02ecb0f88cb1c290c0cf940431aff8a6e1891ed Mon Sep 17 00:00:00 2001 From: Matt Holt Date: Sat, 13 May 2023 07:09:20 -0600 Subject: caddytls: Check for nil ALPN; close #5470 (#5473) * Check for nil ALPN; close #5470 * Apply patch * Actually I want to try this --- modules/caddytls/connpolicy.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'modules/caddytls') diff --git a/modules/caddytls/connpolicy.go b/modules/caddytls/connpolicy.go index 46a8eda..a4dc411 100644 --- a/modules/caddytls/connpolicy.go +++ b/modules/caddytls/connpolicy.go @@ -54,7 +54,7 @@ func (cp ConnectionPolicies) Provision(ctx caddy.Context) error { } // enable HTTP/2 by default - if len(pol.ALPN) == 0 { + if pol.ALPN == nil { pol.ALPN = append(pol.ALPN, defaultALPN...) } @@ -283,7 +283,7 @@ func (p *ConnectionPolicy) buildStandardTLSConfig(ctx caddy.Context) error { break } } - if !alpnFound { + if !alpnFound && (cfg.NextProtos == nil || len(cfg.NextProtos) > 0) { cfg.NextProtos = append(cfg.NextProtos, acmez.ACMETLS1Protocol) } -- cgit v1.2.3 From 96919acc9d583ef11ea1f9c72a9991fb3f8aab9f Mon Sep 17 00:00:00 2001 From: Matt Holt Date: Mon, 15 May 2023 10:47:30 -0600 Subject: caddyhttp: Refactor cert Managers (fix #5415) (#5533) --- modules/caddytls/automation.go | 21 +++++++++++++-------- modules/caddytls/certmanagers.go | 15 +-------------- 2 files changed, 14 insertions(+), 22 deletions(-) (limited to 'modules/caddytls') diff --git a/modules/caddytls/automation.go b/modules/caddytls/automation.go index 58ffe4c..1664762 100644 --- a/modules/caddytls/automation.go +++ b/modules/caddytls/automation.go @@ -95,9 +95,11 @@ type AutomationPolicy struct { // Modules that can get a custom certificate to use for any // given TLS handshake at handshake-time. Custom certificates // can be useful if another entity is managing certificates - // and Caddy need only get it and serve it. + // and Caddy need only get it and serve it. Specifying a Manager + // enables on-demand TLS, i.e. it has the side-effect of setting + // the on_demand parameter to `true`. // - // TODO: This is an EXPERIMENTAL feature. It is subject to change or removal. + // TODO: This is an EXPERIMENTAL feature. Subject to change or removal. ManagersRaw []json.RawMessage `json:"get_certificate,omitempty" caddy:"namespace=tls.get_certificate inline_key=via"` // If true, certificates will be requested with MustStaple. Not all @@ -233,15 +235,18 @@ func (ap *AutomationPolicy) Provision(tlsApp *TLS) error { // on-demand TLS var ond *certmagic.OnDemandConfig - if ap.OnDemand { + if ap.OnDemand || len(ap.Managers) > 0 { // ask endpoint is now required after a number of negligence cases causing abuse; // but is still allowed for explicit subjects (non-wildcard, non-unbounded), - // and for the internal issuer since it doesn't cause ACME issuer pressure + // for the internal issuer since it doesn't cause ACME issuer pressure if ap.isWildcardOrDefault() && !ap.onlyInternalIssuer() && (tlsApp.Automation == nil || tlsApp.Automation.OnDemand == nil || tlsApp.Automation.OnDemand.Ask == "") { return fmt.Errorf("on-demand TLS cannot be enabled without an 'ask' endpoint to prevent abuse; please refer to documentation for details") } ond = &certmagic.OnDemandConfig{ DecisionFunc: func(name string) error { + if tlsApp.Automation == nil || tlsApp.Automation.OnDemand == nil { + return nil + } if err := onDemandAskRequest(tlsApp.logger, tlsApp.Automation.OnDemand.Ask, name); err != nil { // distinguish true errors from denials, because it's important to elevate actual errors if errors.Is(err, errAskDenied) { @@ -264,6 +269,7 @@ func (ap *AutomationPolicy) Provision(tlsApp *TLS) error { } return nil }, + Managers: ap.Managers, } } @@ -277,10 +283,9 @@ func (ap *AutomationPolicy) Provision(tlsApp *TLS) error { DisableStapling: ap.DisableOCSPStapling, ResponderOverrides: ap.OCSPOverrides, }, - Storage: storage, - Issuers: issuers, - Managers: ap.Managers, - Logger: tlsApp.logger, + Storage: storage, + Issuers: issuers, + Logger: tlsApp.logger, } ap.magic = certmagic.New(tlsApp.certCache, template) diff --git a/modules/caddytls/certmanagers.go b/modules/caddytls/certmanagers.go index 1b701ab..23af19d 100644 --- a/modules/caddytls/certmanagers.go +++ b/modules/caddytls/certmanagers.go @@ -23,14 +23,6 @@ func init() { // Tailscale is a module that can get certificates from the local Tailscale process. type Tailscale struct { - // If true, this module will operate in "best-effort" mode and - // ignore "soft" errors; i.e. try Tailscale, and if it doesn't connect - // or return a certificate, oh well. Failure to connect to Tailscale - // results in a no-op instead of an error. Intended for the use case - // where this module is added implicitly for convenience, even if - // Tailscale isn't necessarily running. - Optional bool `json:"optional,omitempty"` - logger *zap.Logger } @@ -60,16 +52,11 @@ func (ts Tailscale) GetCertificate(ctx context.Context, hello *tls.ClientHelloIn // canHazCertificate returns true if Tailscale reports it can get a certificate for the given ClientHello. func (ts Tailscale) canHazCertificate(ctx context.Context, hello *tls.ClientHelloInfo) (bool, error) { - if ts.Optional && !strings.HasSuffix(strings.ToLower(hello.ServerName), tailscaleDomainAliasEnding) { + if !strings.HasSuffix(strings.ToLower(hello.ServerName), tailscaleDomainAliasEnding) { return false, nil } status, err := tscert.GetStatus(ctx) if err != nil { - if ts.Optional { - // ignore error if we don't expect/require it to work anyway, but log it for debugging - ts.logger.Debug("error getting tailscale status", zap.Error(err), zap.String("server_name", hello.ServerName)) - return false, nil - } return false, err } for _, domain := range status.CertDomains { -- cgit v1.2.3 From 4ba03c9d38aae134bd8616178315086589b69ba8 Mon Sep 17 00:00:00 2001 From: Matthew Holt Date: Sun, 4 Jun 2023 22:15:50 -0600 Subject: caddytls: Clarify some JSON config docs --- modules/caddytls/automation.go | 7 +++++++ modules/caddytls/tls.go | 15 ++++++++++++--- 2 files changed, 19 insertions(+), 3 deletions(-) (limited to 'modules/caddytls') diff --git a/modules/caddytls/automation.go b/modules/caddytls/automation.go index 1664762..de88201 100644 --- a/modules/caddytls/automation.go +++ b/modules/caddytls/automation.go @@ -85,6 +85,13 @@ type AutomationConfig struct { // TLS app to properly provision a new policy. type AutomationPolicy struct { // Which subjects (hostnames or IP addresses) this policy applies to. + // + // This list is a filter, not a command. In other words, it is used + // only to filter whether this policy should apply to a subject that + // needs a certificate; it does NOT command the TLS app to manage a + // certificate for that subject. To have Caddy automate a certificate + // or specific subjects, use the "automate" certificate loader module + // of the TLS app. SubjectsRaw []string `json:"subjects,omitempty"` // The modules that may issue certificates. Default: internal if all diff --git a/modules/caddytls/tls.go b/modules/caddytls/tls.go index 9b5b552..52f1159 100644 --- a/modules/caddytls/tls.go +++ b/modules/caddytls/tls.go @@ -39,9 +39,16 @@ func init() { // TLS provides TLS facilities including certificate // loading and management, client auth, and more. type TLS struct { - // Caches certificates in memory for quick use during + // Certificates to load into memory for quick recall during // TLS handshakes. Each key is the name of a certificate - // loader module. All loaded certificates get pooled + // loader module. + // + // The "automate" certificate loader module can be used to + // specify a list of subjects that need certificates to be + // managed automatically. The first matching automation + // policy will be applied to manage the certificate(s). + // + // All loaded certificates get pooled // into the same cache and may be used to complete TLS // handshakes for the relevant server names (SNI). // Certificates loaded manually (anything other than @@ -557,7 +564,9 @@ type Certificate struct { // // Technically, this is a no-op certificate loader module that is treated as // a special case: it uses this app's automation features to load certificates -// for the list of hostnames, rather than loading certificates manually. +// for the list of hostnames, rather than loading certificates manually. But +// the end result is the same: certificates for these subject names will be +// loaded into the in-memory cache and may then be used. type AutomateLoader []string // CaddyModule returns the Caddy module information. -- cgit v1.2.3 From 0e2c7e1d35b287fc0e56d6db2951f791e09b5a37 Mon Sep 17 00:00:00 2001 From: Matt Holt Date: Tue, 11 Jul 2023 13:10:58 -0600 Subject: caddytls: Reuse certificate cache through reloads (#5623) * caddytls: Don't purge cert cache on config reload * Update CertMagic This actually avoids reloading managed certs from storage when already in the cache, d'oh. * Fix bug; re-implement HasCertificateForSubject * Update go.mod: CertMagic tag --- modules/caddytls/automation.go | 4 +- modules/caddytls/tls.go | 91 +++++++++++++++++++++++++++++++++++++----- 2 files changed, 83 insertions(+), 12 deletions(-) (limited to 'modules/caddytls') diff --git a/modules/caddytls/automation.go b/modules/caddytls/automation.go index de88201..114d7aa 100644 --- a/modules/caddytls/automation.go +++ b/modules/caddytls/automation.go @@ -294,7 +294,9 @@ func (ap *AutomationPolicy) Provision(tlsApp *TLS) error { Issuers: issuers, Logger: tlsApp.logger, } - ap.magic = certmagic.New(tlsApp.certCache, template) + certCacheMu.RLock() + ap.magic = certmagic.New(certCache, template) + certCacheMu.RUnlock() // sometimes issuers may need the parent certmagic.Config in // order to function properly (for example, ACMEIssuer needs diff --git a/modules/caddytls/tls.go b/modules/caddytls/tls.go index 52f1159..1456d29 100644 --- a/modules/caddytls/tls.go +++ b/modules/caddytls/tls.go @@ -36,6 +36,11 @@ func init() { caddy.RegisterModule(AutomateLoader{}) } +var ( + certCache *certmagic.Cache + certCacheMu sync.RWMutex +) + // TLS provides TLS facilities including certificate // loading and management, client auth, and more. type TLS struct { @@ -77,12 +82,15 @@ type TLS struct { certificateLoaders []CertificateLoader automateNames []string - certCache *certmagic.Cache ctx caddy.Context storageCleanTicker *time.Ticker storageCleanStop chan struct{} logger *zap.Logger events *caddyevents.App + + // set of subjects with managed certificates, + // and hashes of manually-loaded certificates + managing, loaded map[string]struct{} } // CaddyModule returns the Caddy module information. @@ -103,6 +111,7 @@ func (t *TLS) Provision(ctx caddy.Context) error { t.ctx = ctx t.logger = ctx.Logger() repl := caddy.NewReplacer() + t.managing, t.loaded = make(map[string]struct{}), make(map[string]struct{}) // set up a new certificate cache; this (re)loads all certificates cacheOpts := certmagic.CacheOptions{ @@ -121,7 +130,14 @@ func (t *TLS) Provision(ctx caddy.Context) error { if cacheOpts.Capacity <= 0 { cacheOpts.Capacity = 10000 } - t.certCache = certmagic.NewCache(cacheOpts) + + certCacheMu.Lock() + if certCache == nil { + certCache = certmagic.NewCache(cacheOpts) + } else { + certCache.SetOptions(cacheOpts) + } + certCacheMu.Unlock() // certificate loaders val, err := ctx.LoadModule(t, "CertificatesRaw") @@ -209,7 +225,8 @@ func (t *TLS) Provision(ctx caddy.Context) error { // provision so that other apps (such as http) can know which // certificates have been manually loaded, and also so that // commands like validate can be a better test - magic := certmagic.New(t.certCache, certmagic.Config{ + certCacheMu.RLock() + magic := certmagic.New(certCache, certmagic.Config{ Storage: ctx.Storage(), Logger: t.logger, OnEvent: t.onEvent, @@ -217,16 +234,18 @@ func (t *TLS) Provision(ctx caddy.Context) error { DisableStapling: t.DisableOCSPStapling, }, }) + certCacheMu.RUnlock() for _, loader := range t.certificateLoaders { certs, err := loader.LoadCertificates() if err != nil { return fmt.Errorf("loading certificates: %v", err) } for _, cert := range certs { - err := magic.CacheUnmanagedTLSCertificate(ctx, cert.Certificate, cert.Tags) + hash, err := magic.CacheUnmanagedTLSCertificate(ctx, cert.Certificate, cert.Tags) if err != nil { return fmt.Errorf("caching unmanaged certificate: %v", err) } + t.loaded[hash] = struct{}{} } } @@ -305,16 +324,44 @@ func (t *TLS) Stop() error { // Cleanup frees up resources allocated during Provision. func (t *TLS) Cleanup() error { - // stop the certificate cache - if t.certCache != nil { - t.certCache.Stop() - } - // stop the session ticket rotation goroutine if t.SessionTickets != nil { t.SessionTickets.stop() } + // if a new TLS app was loaded, remove certificates from the cache that are no longer + // being managed or loaded by the new config; if there is no more TLS app running, + // then stop cert maintenance and let the cert cache be GC'ed + if nextTLS := caddy.ActiveContext().AppIfConfigured("tls"); nextTLS != nil { + nextTLSApp := nextTLS.(*TLS) + + // compute which certificates were managed or loaded into the cert cache by this + // app instance (which is being stopped) that are not managed or loaded by the + // new app instance (which just started), and remove them from the cache + var noLongerManaged, noLongerLoaded []string + for subj := range t.managing { + if _, ok := nextTLSApp.managing[subj]; !ok { + noLongerManaged = append(noLongerManaged, subj) + } + } + for hash := range t.loaded { + if _, ok := nextTLSApp.loaded[hash]; !ok { + noLongerLoaded = append(noLongerLoaded, hash) + } + } + + certCacheMu.RLock() + certCache.RemoveManaged(noLongerManaged) + certCache.Remove(noLongerLoaded) + certCacheMu.RUnlock() + } else { + // no more TLS app running, so delete in-memory cert cache + certCache.Stop() + certCacheMu.Lock() + certCache = nil + certCacheMu.Unlock() + } + return nil } @@ -339,6 +386,9 @@ func (t *TLS) Manage(names []string) error { if err != nil { return fmt.Errorf("automate: manage %v: %v", names, err) } + for _, name := range names { + t.managing[name] = struct{}{} + } } return nil @@ -449,8 +499,27 @@ func (t *TLS) getAutomationPolicyForName(name string) *AutomationPolicy { // AllMatchingCertificates returns the list of all certificates in // the cache which could be used to satisfy the given SAN. -func (t *TLS) AllMatchingCertificates(san string) []certmagic.Certificate { - return t.certCache.AllMatchingCertificates(san) +func AllMatchingCertificates(san string) []certmagic.Certificate { + return certCache.AllMatchingCertificates(san) +} + +func (t *TLS) HasCertificateForSubject(subject string) bool { + certCacheMu.RLock() + allMatchingCerts := certCache.AllMatchingCertificates(subject) + certCacheMu.RUnlock() + for _, cert := range allMatchingCerts { + // check if the cert is manually loaded by this config + if _, ok := t.loaded[cert.Hash()]; ok { + return true + } + // check if the cert is automatically managed by this config + for _, name := range cert.Names { + if _, ok := t.managing[name]; ok { + return true + } + } + } + return false } // keepStorageClean starts a goroutine that immediately cleans up all -- cgit v1.2.3 From b32f265ecad60404c3818cc9d42e367a8e4eb7d4 Mon Sep 17 00:00:00 2001 From: Jacob Gadikian Date: Tue, 8 Aug 2023 03:40:31 +0800 Subject: ci: Use gofumpt to format code (#5707) --- modules/caddytls/connpolicy.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'modules/caddytls') diff --git a/modules/caddytls/connpolicy.go b/modules/caddytls/connpolicy.go index a4dc411..74c8324 100644 --- a/modules/caddytls/connpolicy.go +++ b/modules/caddytls/connpolicy.go @@ -316,7 +316,7 @@ func (p *ConnectionPolicy) buildStandardTLSConfig(ctx caddy.Context) error { return err } logFile, _, err := secretsLogPool.LoadOrNew(filename, func() (caddy.Destructor, error) { - w, err := os.OpenFile(filename, os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0600) + w, err := os.OpenFile(filename, os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0o600) return destructableWriter{w}, err }) if err != nil { -- cgit v1.2.3 From 080db938170ce154def7c6eb860634ffc6168c1c Mon Sep 17 00:00:00 2001 From: Matthew Holt Date: Wed, 9 Aug 2023 11:15:01 -0600 Subject: caddytls: Update docs for on-demand config --- modules/caddytls/automation.go | 35 +++++++++++++++++++---------------- 1 file changed, 19 insertions(+), 16 deletions(-) (limited to 'modules/caddytls') diff --git a/modules/caddytls/automation.go b/modules/caddytls/automation.go index 114d7aa..1416f4f 100644 --- a/modules/caddytls/automation.go +++ b/modules/caddytls/automation.go @@ -459,29 +459,32 @@ type DNSChallengeConfig struct { // Caddy can "ask" if it should be allowed to manage // certificates for a given hostname. type OnDemandConfig struct { - // An optional rate limit to throttle the - // issuance of certificates from handshakes. - RateLimit *RateLimit `json:"rate_limit,omitempty"` - - // REQUIRED. If Caddy needs to obtain/renew a certificate - // during a TLS handshake, it will perform a quick - // HTTP request to this URL to check if it should be - // allowed to try to get a certificate for the name - // in the "domain" query string parameter, like so: - // `?domain=example.com`. The endpoint must return a - // 200 OK status if a certificate is allowed; - // anything else will cause it to be denied. + // REQUIRED. If Caddy needs to load a certificate from + // storage or obtain/renew a certificate during a TLS + // handshake, it will perform a quick HTTP request to + // this URL to check if it should be allowed to try to + // get a certificate for the name in the "domain" query + // string parameter, like so: `?domain=example.com`. + // The endpoint must return a 200 OK status if a certificate + // is allowed; anything else will cause it to be denied. // Redirects are not followed. Ask string `json:"ask,omitempty"` + + // DEPRECATED. An optional rate limit to throttle + // the checking of storage and the issuance of + // certificates from handshakes if not already in + // storage. WILL BE REMOVED IN A FUTURE RELEASE. + RateLimit *RateLimit `json:"rate_limit,omitempty"` } -// RateLimit specifies an interval with optional burst size. +// DEPRECATED. RateLimit specifies an interval with optional burst size. type RateLimit struct { - // A duration value. A certificate may be obtained 'burst' - // times during this interval. + // A duration value. Storage may be checked and a certificate may be + // obtained 'burst' times during this interval. Interval caddy.Duration `json:"interval,omitempty"` - // How many times during an interval a certificate can be obtained. + // How many times during an interval storage can be checked or a + // certificate can be obtained. Burst int `json:"burst,omitempty"` } -- cgit v1.2.3 From d6f86cccf5fa5b4eb30141da390cf2439746c5da Mon Sep 17 00:00:00 2001 From: Jacob Gadikian Date: Mon, 14 Aug 2023 23:41:15 +0800 Subject: ci: use gci linter (#5708) * use gofmput to format code * use gci to format imports * reconfigure gci * linter autofixes * rearrange imports a little * export GOOS=windows golangci-lint run ./... --fix --- modules/caddytls/acmeissuer.go | 7 ++++--- modules/caddytls/automation.go | 3 ++- modules/caddytls/certmanagers.go | 5 +++-- modules/caddytls/connpolicy.go | 3 ++- modules/caddytls/distributedstek/distributedstek.go | 3 ++- modules/caddytls/internalissuer.go | 7 ++++--- modules/caddytls/matchers.go | 3 ++- modules/caddytls/storageloader.go | 3 ++- modules/caddytls/tls.go | 5 +++-- modules/caddytls/zerosslissuer.go | 5 +++-- 10 files changed, 27 insertions(+), 17 deletions(-) (limited to 'modules/caddytls') diff --git a/modules/caddytls/acmeissuer.go b/modules/caddytls/acmeissuer.go index ca79981..5e79c2d 100644 --- a/modules/caddytls/acmeissuer.go +++ b/modules/caddytls/acmeissuer.go @@ -24,13 +24,14 @@ import ( "strconv" "time" - "github.com/caddyserver/caddy/v2" - "github.com/caddyserver/caddy/v2/caddyconfig" - "github.com/caddyserver/caddy/v2/caddyconfig/caddyfile" "github.com/caddyserver/certmagic" "github.com/mholt/acmez" "github.com/mholt/acmez/acme" "go.uber.org/zap" + + "github.com/caddyserver/caddy/v2" + "github.com/caddyserver/caddy/v2/caddyconfig" + "github.com/caddyserver/caddy/v2/caddyconfig/caddyfile" ) func init() { diff --git a/modules/caddytls/automation.go b/modules/caddytls/automation.go index 1416f4f..ee25400 100644 --- a/modules/caddytls/automation.go +++ b/modules/caddytls/automation.go @@ -22,10 +22,11 @@ import ( "strings" "time" - "github.com/caddyserver/caddy/v2" "github.com/caddyserver/certmagic" "github.com/mholt/acmez" "go.uber.org/zap" + + "github.com/caddyserver/caddy/v2" ) // AutomationConfig governs the automated management of TLS certificates. diff --git a/modules/caddytls/certmanagers.go b/modules/caddytls/certmanagers.go index 23af19d..ad26468 100644 --- a/modules/caddytls/certmanagers.go +++ b/modules/caddytls/certmanagers.go @@ -9,11 +9,12 @@ import ( "net/url" "strings" - "github.com/caddyserver/caddy/v2" - "github.com/caddyserver/caddy/v2/caddyconfig/caddyfile" "github.com/caddyserver/certmagic" "github.com/tailscale/tscert" "go.uber.org/zap" + + "github.com/caddyserver/caddy/v2" + "github.com/caddyserver/caddy/v2/caddyconfig/caddyfile" ) func init() { diff --git a/modules/caddytls/connpolicy.go b/modules/caddytls/connpolicy.go index 74c8324..64fdd51 100644 --- a/modules/caddytls/connpolicy.go +++ b/modules/caddytls/connpolicy.go @@ -25,9 +25,10 @@ import ( "path/filepath" "strings" - "github.com/caddyserver/caddy/v2" "github.com/mholt/acmez" "go.uber.org/zap" + + "github.com/caddyserver/caddy/v2" ) func init() { diff --git a/modules/caddytls/distributedstek/distributedstek.go b/modules/caddytls/distributedstek/distributedstek.go index 18ed694..f6d0de0 100644 --- a/modules/caddytls/distributedstek/distributedstek.go +++ b/modules/caddytls/distributedstek/distributedstek.go @@ -33,9 +33,10 @@ import ( "runtime/debug" "time" + "github.com/caddyserver/certmagic" + "github.com/caddyserver/caddy/v2" "github.com/caddyserver/caddy/v2/modules/caddytls" - "github.com/caddyserver/certmagic" ) func init() { diff --git a/modules/caddytls/internalissuer.go b/modules/caddytls/internalissuer.go index 3dd6c35..1cf2461 100644 --- a/modules/caddytls/internalissuer.go +++ b/modules/caddytls/internalissuer.go @@ -21,12 +21,13 @@ import ( "encoding/pem" "time" - "github.com/caddyserver/caddy/v2" - "github.com/caddyserver/caddy/v2/caddyconfig/caddyfile" - "github.com/caddyserver/caddy/v2/modules/caddypki" "github.com/caddyserver/certmagic" "github.com/smallstep/certificates/authority/provisioner" "go.uber.org/zap" + + "github.com/caddyserver/caddy/v2" + "github.com/caddyserver/caddy/v2/caddyconfig/caddyfile" + "github.com/caddyserver/caddy/v2/modules/caddypki" ) func init() { diff --git a/modules/caddytls/matchers.go b/modules/caddytls/matchers.go index f541220..af1f898 100644 --- a/modules/caddytls/matchers.go +++ b/modules/caddytls/matchers.go @@ -21,9 +21,10 @@ import ( "net/netip" "strings" - "github.com/caddyserver/caddy/v2" "github.com/caddyserver/certmagic" "go.uber.org/zap" + + "github.com/caddyserver/caddy/v2" ) func init() { diff --git a/modules/caddytls/storageloader.go b/modules/caddytls/storageloader.go index ef9d51e..ddaaa51 100644 --- a/modules/caddytls/storageloader.go +++ b/modules/caddytls/storageloader.go @@ -18,8 +18,9 @@ import ( "crypto/tls" "fmt" - "github.com/caddyserver/caddy/v2" "github.com/caddyserver/certmagic" + + "github.com/caddyserver/caddy/v2" ) func init() { diff --git a/modules/caddytls/tls.go b/modules/caddytls/tls.go index 1456d29..02d5aae 100644 --- a/modules/caddytls/tls.go +++ b/modules/caddytls/tls.go @@ -25,10 +25,11 @@ import ( "sync" "time" - "github.com/caddyserver/caddy/v2" - "github.com/caddyserver/caddy/v2/modules/caddyevents" "github.com/caddyserver/certmagic" "go.uber.org/zap" + + "github.com/caddyserver/caddy/v2" + "github.com/caddyserver/caddy/v2/modules/caddyevents" ) func init() { diff --git a/modules/caddytls/zerosslissuer.go b/modules/caddytls/zerosslissuer.go index 0209294..697bab0 100644 --- a/modules/caddytls/zerosslissuer.go +++ b/modules/caddytls/zerosslissuer.go @@ -25,11 +25,12 @@ import ( "strings" "sync" - "github.com/caddyserver/caddy/v2" - "github.com/caddyserver/caddy/v2/caddyconfig/caddyfile" "github.com/caddyserver/certmagic" "github.com/mholt/acmez/acme" "go.uber.org/zap" + + "github.com/caddyserver/caddy/v2" + "github.com/caddyserver/caddy/v2/caddyconfig/caddyfile" ) func init() { -- cgit v1.2.3 From b377208ededa964893dedd5660734e9616f998f7 Mon Sep 17 00:00:00 2001 From: Matt Holt Date: Wed, 23 Aug 2023 20:47:54 -0600 Subject: chore: Appease gosec linter (#5777) These happen to be harmless memory aliasing but I guess the linter can't know that and we can't really prove it in general. --- modules/caddytls/certselection.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'modules/caddytls') diff --git a/modules/caddytls/certselection.go b/modules/caddytls/certselection.go index 0311f11..1bef890 100644 --- a/modules/caddytls/certselection.go +++ b/modules/caddytls/certselection.go @@ -58,7 +58,8 @@ nextChoice: if len(p.SerialNumber) > 0 { var found bool for _, sn := range p.SerialNumber { - if cert.Leaf.SerialNumber.Cmp(&sn.Int) == 0 { + snInt := sn.Int // avoid taking address of iteration variable (gosec warning) + if cert.Leaf.SerialNumber.Cmp(&snInt) == 0 { found = true break } -- cgit v1.2.3 From 289934f3d16405c6aa791d2b0702c2f893045e0e Mon Sep 17 00:00:00 2001 From: Bas Westerbaan Date: Wed, 11 Oct 2023 21:45:37 +0200 Subject: tls: Add X25519Kyber768Draft00 PQ "curve" behind build tag (#5852) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit … when compiled with cfgo (https://github.com/cloudflare/go). --- modules/caddytls/cf.go | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 modules/caddytls/cf.go (limited to 'modules/caddytls') diff --git a/modules/caddytls/cf.go b/modules/caddytls/cf.go new file mode 100644 index 0000000..e61a59c --- /dev/null +++ b/modules/caddytls/cf.go @@ -0,0 +1,24 @@ +//go:build cfgo + +package caddytls + +// This file adds support for X25519Kyber768Draft00, a post-quantum +// key agreement that is currently being rolled out by Chrome [1] +// and Cloudflare [2,3]. For more context, see the PR [4]. +// +// [1] https://blog.chromium.org/2023/08/protecting-chrome-traffic-with-hybrid.html +// [2] https://blog.cloudflare.com/post-quantum-for-all/ +// [3] https://blog.cloudflare.com/post-quantum-to-origins/ +// [4] https://github.com/caddyserver/caddy/pull/5852 + +import ( + "crypto/tls" +) + +func init() { + SupportedCurves["X25519Kyber768Draft00"] = tls.X25519Kyber768Draft00 + defaultCurves = append( + []tls.CurveID{tls.X25519Kyber768Draft00}, + defaultCurves..., + ) +} -- cgit v1.2.3