Connection Policies govern the establishment of TLS connections in Caddy by providing per-connection TLS configuration during handshakes. A connection policy determines which certificates, cipher suites, protocol versions, client authentication requirements, and other TLS parameters apply to a specific TLS connection based on matching criteria from the ClientHello.
Connection policies are part of Caddy's TLS module and are used by HTTP servers and other applications that need to serve TLS connections. For information about certificate acquisition and renewal, see Certificate Management. For client authentication details, see Client Authentication. For ECH configuration, see Encrypted ClientHello (ECH).
Sources: modules/caddytls/connpolicy.go44-47 modules/caddytls/connpolicy.go182-256
ConnectionPolicies is an ordered slice of ConnectionPolicy pointers. The first policy whose matchers all match a TLS ClientHello is selected for that connection. This ordered matching allows for specific policies to take precedence over more general ones.
Sources: modules/caddytls/connpolicy.go44-47 modules/caddytls/connpolicy.go96-180
| Field | Type | Purpose |
|---|---|---|
MatchersRaw | caddy.ModuleMap | Modules that match against ClientHello (namespace: tls.handshake_match) |
CertSelection | *CustomCertSelectionPolicy | Algorithm for choosing certificates when multiple match |
CipherSuites | []string | Allowed cipher suites for this policy |
Curves | []string | Elliptic curves for key exchange |
ALPN | []string | Application-Layer Protocol Negotiation values |
ProtocolMin | string | Minimum TLS version (default: tls1.2) |
ProtocolMax | string | Maximum TLS version (default: tls1.3) |
Drop | bool | Reject connections matching this policy |
ClientAuthentication | *ClientAuthentication | mTLS configuration |
DefaultSNI | string | ServerName to use if ClientHello has no SNI |
FallbackSNI | string | ServerName to use if no matching certificate found |
InsecureSecretsLog | string | NSS key log file path for debugging (compromises security) |
TLSConfig | *tls.Config | Fully-formed standard library TLS config |
Sources: modules/caddytls/connpolicy.go184-257
Connection policies use ConnectionMatcher modules to determine if a policy applies to a given TLS ClientHello. All matchers in a policy must match for the policy to be selected (AND logic).
Sources: modules/caddytls/connpolicy.go96-180 modules/caddytls/connpolicy.go117-139
When there are more than 30 policies, Caddy builds an SNI index to avoid iterating thousands of policies on every handshake. Policies with MatchServerName matchers are indexed by their SNI values for O(1) lookup.
Sources: modules/caddytls/connpolicy.go99-115
Connection matchers implement the ConnectionMatcher interface and are loaded from the tls.handshake_match namespace. Common matchers include:
Sources: modules/caddytls/connpolicy.go54-61 modules/caddytls/connpolicy.go187-188
Each connection policy pre-builds a standard library tls.Config during provisioning to optimize handshake performance. The config is constructed in buildStandardTLSConfig and stored in the TLSConfig field.
Sources: modules/caddytls/connpolicy.go268-433
The GetCertificate callback in the TLS config is invoked during each handshake to select and obtain the appropriate certificate. This callback integrates with CertMagic for certificate management.
Sources: modules/caddytls/connpolicy.go281-317
Connection policies specify ALPN (Application-Layer Protocol Negotiation) values. By default, HTTP/2 and HTTP/1.1 are enabled. The ACME TLS-ALPN-01 challenge protocol is automatically appended to support certificate issuance.
Sources: modules/caddytls/connpolicy.go64-66 modules/caddytls/connpolicy.go362-366
The CertSelection field allows customizing how certificates are chosen when multiple certificates match the requested ServerName. This is useful for scenarios like preferring certain key types or certificate authorities.
Sources: modules/caddytls/connpolicy.go192 modules/caddytls/connpolicy.go295-301
| Field | Purpose | Use Case |
|---|---|---|
DefaultSNI | ServerName to use if ClientHello has empty SNI | Legacy clients that don't send SNI |
FallbackSNI | ServerName to use if no certificate matches the requested SNI | CDN scenarios where downstream SNI differs from origin certificate |
Example CDN Scenario: A CDN passes through the client's SNI (e.g., example.com) but can accept a certificate for the origin hostname (e.g., origin.cdn.com). Setting FallbackSNI to origin.cdn.com allows the handshake to succeed.
Sources: modules/caddytls/connpolicy.go218-232 modules/caddytls/connpolicy.go303-304
The ClientAuthentication struct configures mutual TLS (mTLS) for verifying client certificates. It supports multiple verification modes and custom verifier modules.
| Field | Type | Purpose |
|---|---|---|
CARaw | json.RawMessage | CA pool source module (namespace: tls.ca_pool.source) |
TrustedCACerts | []string | Deprecated: base64 DER-encoded CA certificates |
TrustedCACertPEMFiles | []string | Deprecated: PEM file paths for CA certificates |
TrustedLeafCerts | []string | Deprecated: base64 DER-encoded leaf certificates to accept |
VerifiersRaw | []json.RawMessage | Custom verifier modules (namespace: tls.client_auth.verifier) |
Mode | string | Authentication mode: request, require, verify_if_given, require_and_verify |
Sources: modules/caddytls/connpolicy.go588-639
The default mode is require_and_verify if any CA certificates are configured, otherwise require.
Sources: modules/caddytls/connpolicy.go624-636 modules/caddytls/connpolicy.go840-864
Sources: modules/caddytls/connpolicy.go892-910
When client authentication is enabled, session tickets are disabled to prevent privilege escalation. This prevents a client from resuming a session with a different certificate or across different server identities.
Sources: modules/caddytls/connpolicy.go388-401
Connection policies can specify a custom list of cipher suites. Caddy's defaults are optimized based on hardware AES-NI support:
With AES-NI (hardware acceleration):
TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305Without AES-NI: ChaCha20-Poly1305 suites are prioritized over AES-GCM.
Sources: modules/caddytls/connpolicy.go339-350 modules/caddytls/values.go52-82
Supported curves for key exchange:
| Curve Name | TLS Constant | Notes |
|---|---|---|
x25519mlkem768 | tls.X25519MLKEM768 | Post-quantum hybrid KEM |
x25519 | tls.X25519 | Fast, modern (default) |
secp256r1 | tls.CurveP256 | Widely compatible (default) |
secp384r1 | tls.CurveP384 | Higher security margin |
secp521r1 | tls.CurveP521 | Highest classical security |
Default curves include only those with fast implementations or post-quantum security.
Sources: modules/caddytls/connpolicy.go352-360 modules/caddytls/values.go84-117
Caddy supports TLS 1.2 and TLS 1.3:
tls1.2 (tls.VersionTLS12)tls1.3 (tls.VersionTLS13)Policies enforce that ProtocolMin ≤ ProtocolMax.
Sources: modules/caddytls/connpolicy.go368-377 modules/caddytls/values.go120-133
Setting Drop: true causes the policy to reject matching connections with an error. This is experimental and can be used for denying access based on ClientHello characteristics.
Sources: modules/caddytls/connpolicy.go132-134
The InsecureSecretsLog field enables logging TLS secrets in NSS key log format for debugging with tools like Wireshark. This completely compromises connection security and should only be used for debugging.
Sources: modules/caddytls/connpolicy.go234-242 modules/caddytls/connpolicy.go403-426
The experimental HandshakeContext module allows modifying the context passed to CertMagic's certificate management functions during handshakes. This can be used to inject custom behavior based on ClientHello information.
Sources: modules/caddytls/connpolicy.go244-266 modules/caddytls/connpolicy.go306-314
Connection policies integrate with ECH (Encrypted ClientHello) to protect the true server name from observers. When ECH is configured in the TLS app, the GetConfigForClient callback is enhanced with GetEncryptedClientHelloKeys.
Sources: modules/caddytls/connpolicy.go147-177
When ECH publication is not explicitly configured, Caddy automatically registers all server names from connection policy matchers as inner names to protect. This happens during TLSConfig() construction to ensure ECH covers all configured domains.
Sources: modules/caddytls/connpolicy.go155-169
Sources: modules/caddytls/connpolicy.go49-94
Connection policies provide helper methods for validation and comparison:
SettingsEmpty(): Returns true if all fields except matchers are empty/unsetSettingsEqual(q): Compares policy settings (excluding matchers) for equalityThese are used during configuration optimization to deduplicate policies with identical settings.
Sources: modules/caddytls/connpolicy.go435-456
Connection policies can be configured via Caddyfile with the following syntax:
connection_policy {
match {
# matcher modules
}
alpn h2 http/1.1
ciphers TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 ...
curves x25519 secp256r1
protocols tls1.2 tls1.3
cert_selection {
# certificate selection policy
}
client_auth {
mode require_and_verify
trust_pool inline {
# CA certificates
}
verifier leaf {
# leaf certificate verification
}
}
default_sni example.com
fallback_sni fallback.example.com
drop
insecure_secrets_log /path/to/log
}
Sources: modules/caddytls/connpolicy.go458-586
Connection policies are the mechanism by which Caddy selects per-connection TLS configuration during handshakes. They form an ordered list where the first matching policy applies. Key capabilities include:
Connection policies bridge the TLS app's configuration with the actual Go standard library tls.Config structures used during handshakes, enabling Caddy's flexible and powerful TLS management capabilities.
Sources: modules/caddytls/connpolicy.go44-943 modules/caddytls/ech.go146-177
Refresh this wiki