MCPcopy
hub / github.com/caddyserver/caddy / TLSConfig

Method TLSConfig

modules/caddytls/connpolicy.go:98–181  ·  view source on GitHub ↗

TLSConfig returns a standard-lib-compatible TLS configuration which selects the first matching policy based on the ClientHello.

(ctx caddy.Context)

Source from the content-addressed store, hash-verified

96// TLSConfig returns a standard-lib-compatible TLS configuration which
97// selects the first matching policy based on the ClientHello.
98func (cp ConnectionPolicies) TLSConfig(ctx caddy.Context) *tls.Config {
99 // using ServerName to match policies is extremely common, especially in configs
100 // with lots and lots of different policies; we can fast-track those by indexing
101 // them by SNI, so we don't have to iterate potentially thousands of policies
102 // (TODO: this map does not account for wildcards, see if this is a problem in practice? look for reports of high connection latency with wildcard certs but low latency for non-wildcards in multi-thousand-cert deployments)
103 indexedBySNI := make(map[string]ConnectionPolicies)
104 if len(cp) > 30 {
105 for _, p := range cp {
106 for _, m := range p.matchers {
107 if sni, ok := m.(MatchServerName); ok {
108 for _, sniName := range sni {
109 // index for fast lookups during handshakes
110 indexName := asciiServerNameForMatch(sniName)
111 indexedBySNI[indexName] = append(indexedBySNI[indexName], p)
112 }
113 }
114 }
115 }
116 }
117
118 getConfigForClient := func(hello *tls.ClientHelloInfo) (*tls.Config, error) {
119 // filter policies by SNI first, if possible, to speed things up
120 // when there may be lots of policies
121 possiblePolicies := cp
122 if indexedPolicies, ok := indexedBySNI[asciiServerNameForMatch(hello.ServerName)]; ok {
123 possiblePolicies = indexedPolicies
124 }
125
126 policyLoop:
127 for _, pol := range possiblePolicies {
128 for _, matcher := range pol.matchers {
129 if !matcher.Match(hello) {
130 continue policyLoop
131 }
132 }
133 if pol.Drop {
134 return nil, fmt.Errorf("dropping connection")
135 }
136 return pol.TLSConfig, nil
137 }
138
139 return nil, fmt.Errorf("no server TLS configuration available for ClientHello: %+v", hello)
140 }
141
142 tlsCfg := &tls.Config{
143 MinVersion: tls.VersionTLS12,
144 GetConfigForClient: getConfigForClient,
145 }
146
147 // enable ECH, if configured
148 if tlsAppIface, err := ctx.AppIfConfigured("tls"); err == nil {
149 tlsApp := tlsAppIface.(*TLS)
150
151 if tlsApp.EncryptedClientHello != nil && len(tlsApp.EncryptedClientHello.configs) > 0 {
152 // if no publication was configured, we apply ECH to all server names by default,
153 // but the TLS app needs to know what they are in this case, since they don't appear
154 // in its config (remember, TLS connection policies are used by *other* apps to
155 // run TLS servers) -- we skip names with placeholders

Callers 3

replaceRemoteAdminServerFunction · 0.80
StartMethod · 0.80

Calls 5

ReplaceAllMethod · 0.95
asciiServerNameForMatchFunction · 0.85
AppIfConfiguredMethod · 0.80
RegisterServerNamesMethod · 0.80
MatchMethod · 0.65