caddyserver/caddy · warning

dropping connection

Error message

dropping connection

What it means

Returned by the GetConfigForClient callback during a TLS handshake when the matched connection policy has Drop=true. It is not a malfunction: the operator explicitly configured a matcher + 'default_sni'-style policy whose action is to refuse the connection (e.g. block TLS for unknown SNI values), and Caddy aborts the handshake by returning this error.

Solutions

  1. Confirm this is intended: the matching policy was configured with drop
  2. If the client should be served, add its SNI/domain to the policy's match allowlist or a serving policy that matches earlier
  3. Reorder policies so serving policies for known SNIs come before the catch-all drop policy
  4. To distinguish from misconfig, log matched SNI and compare against the policy list

Example fix

# before
tls {
	policies {
		policy {
			match {
				sni *
			}
			drop
		}
	}
}

# after (serve known SNI, drop only unknown)
tls {
	policies {
		policy {
			match {
				sni example.com
			}
		}
		policy {
			match {
				sni *
			}
			drop
		}
	}
}
Defensive patterns

Strategy: validation

Validate before calling

# Before enabling a drop policy, enumerate the SNIs that will still be served:
# compare your sni matchers against a DNS/inventory list of expected hostnames.
caddy adapt --config Caddyfile --adapter caddyfile | jq '.. | .sni? // empty'

Prevention

When it happens

Trigger: A connection policy with "drop": true whose matchers (commonly sni) matched the incoming ClientHello. In Caddyfile: an @matcher-matched route using tls policies with drop, e.g. blocking connections whose SNI is not in an allowlist.

Common situations: Clients connecting by IP or with an SNI not in the allowlist get a TLS handshake failure; scanners and probes hitting the server; expected behavior after adding a drop policy but the operator forgot which SNIs are allowed.

Related errors


AI-assisted analysis of caddyserver/caddy@50e54ee279 (2026-08-15). Data as JSON: /api/errors/6a9ca7634dc2bff9. Report an issue: GitHub.

Appendix: source

Thrown at modules/caddytls/connpolicy.go:134

	}

	getConfigForClient := func(hello *tls.ClientHelloInfo) (*tls.Config, error) {
		// filter policies by SNI first, if possible, to speed things up
		// when there may be lots of policies
		possiblePolicies := cp
		if indexedPolicies, ok := indexedBySNI[asciiServerNameForMatch(hello.ServerName)]; ok {
			possiblePolicies = indexedPolicies
		}

	policyLoop:
		for _, pol := range possiblePolicies {
			for _, matcher := range pol.matchers {
				if !matcher.Match(hello) {
					continue policyLoop
				}
			}
			if pol.Drop {
				return nil, fmt.Errorf("dropping connection")
			}
			return pol.TLSConfig, nil
		}

		return nil, fmt.Errorf("no server TLS configuration available for ClientHello: %+v", hello)
	}

	tlsCfg := &tls.Config{
		MinVersion:         tls.VersionTLS12,
		GetConfigForClient: getConfigForClient,
	}

	// enable ECH, if configured
	if tlsAppIface, err := ctx.AppIfConfigured("tls"); err == nil {
		tlsApp := tlsAppIface.(*TLS)

		if tlsApp.EncryptedClientHello != nil && len(tlsApp.EncryptedClientHello.configs) > 0 {
			// if no publication was configured, we apply ECH to all server names by default,

View on GitHub (pinned to 50e54ee279)