All code relating to a caddytls.Config and setting it up from the
Caddyfile is still intact; only the certificate management-related
code was removed into a separate package.
I don't expect this to build in CI successfully; updating dependencies
and vendor is coming next.
I've also removed the ad-hoc, half-baked storage plugins that we need
to finish making first-class Caddy plugins (they were never documented
anyway). The new certmagic package has a much better storage interface,
and we can finally move toward making a new storage plugin type, but
it shouldn't be configurable in the Caddyfile, I think, since it doesn't
make sense for a Caddy instance to use more than one storage config...
We also have the option of eliminating DNS provider plugins and just
shipping all of lego's DNS providers by using a lego package (the
caddytls/setup.go file has a comment describing how) -- but it doubles
Caddy's binary size by 100% from about 19 MB to around 40 MB...!
* tls: Add support for the tls-alpn-01 challenge
Also updates lego/acme to latest on master.
TODO: This implementation of the tls-alpn challenge is not yet solvable
in a distributed Caddy cluster like the http challenge is.
* build: Allow building with the race detector
* tls: Support distributed solving of the TLS-ALPN-01 challenge
* Update vendor and add a todo in MITM checker
- Introduce StrictHostMatching mode for sites that require clientauth
- Error if QUIC is enabled whilst TLS clientauth is configured
(Our QUIC implementation does not yet support TLS clientauth, but
maybe it will in the future - fixes#2095)
- Error if one but not all TLS configs for the same hostname have a
different ClientAuth CA pool
See discussion on #2015 for how this situation was discovered. For a
Caddyfile like this:
localhost {
...
}
:2015 {
...
}
Running Caddy like this:
caddy -host localhost
Produces two sites both defined as `localhost:2015` because the flag
changes the default host value to be `localhost`. This should be an
error since the sites are not distinct and it is confusing. It can also
cause issues with TLS handshakes loading the wrong cert, as the linked
discussion shows.
- Expose the list of Caddy instances through caddy.Instances()
- Added arbitrary storage to caddy.Instance
- The cache of loaded certificates is no longer global; now scoped
per-instance, meaning upon reload (like SIGUSR1) the old cert cache
will be discarded entirely, whereas before, aggressively reloading
config that added and removed lots of sites would cause unnecessary
build-up in the cache over time.
- Key certificates in the cache by their SHA-256 hash instead of
by their names. This means certificates will not be duplicated in
memory (within each instance), making Caddy much more memory-efficient
for large-scale deployments with thousands of sites sharing certs.
- Perform name-to-certificate lookups scoped per caddytls.Config instead
of a single global lookup. This prevents certificates from stepping on
each other when they overlap in their names.
- Do not allow TLS configurations keyed by the same hostname to be
different; this now throws an error.
- Updated relevant tests, with a stark awareness that more tests are
needed.
- Change the NewContext function signature to include an *Instance.
- Strongly recommend (basically require) use of caddytls.NewConfig()
to create a new *caddytls.Config, to ensure pointers to the instance
certificate cache are initialized properly.
- Update the TLS-SNI challenge solver (even though TLS-SNI is disabled
currently on the CA side). Store temporary challenge cert in instance
cache, but do so directly by the ACME challenge name, not the hash.
Modified the getCertificate function to check the cache directly for
a name match if one isn't found otherwise. This will allow any
caddytls.Config to be able to help solve a TLS-SNI challenge, with one
extra side-effect that might actually be kind of interesting (and
useless): clients could send a certificate's hash as the SNI and
Caddy would be able to serve that certificate for the handshake.
- Do not attempt to match a "default" (random) certificate when SNI
is present but unrecognized; return no certificate so a TLS alert
happens instead.
- Store an Instance in the list of instances even while the instance
is still starting up (this allows access to the cert cache for
performing renewals at startup, etc). Will be removed from list again
if instance startup fails.
- Laid groundwork for ACMEv2 and Let's Encrypt wildcard support.
Server type plugins will need to be updated slightly to accommodate
minor adjustments to their API (like passing in an Instance). This
commit includes the changes for the HTTP server.
Certain Caddyfile configurations might error out with this change, if
they configured different TLS settings for the same hostname.
This change trades some complexity for other complexity, but ultimately
this new complexity is more correct and robust than earlier logic.
Fixes#1991Fixes#1994Fixes#1303
* templates: Execute template loaded by later middlewares
This is the beginning of an attempt to make the staticfiles file server
the only middleware that hits the disk and loads content. This may have
unknown implications. But the goal is to reduce duplication without
sacrificing performance. (We now call ServeContent here.)
This change loses about 15% of the req/sec of the old way of doing it,
but this way is arguably more correct since the file server is good at
serving static files; duplicating that logic in every middleware that
needs to hit the disk is not practical.
* httpserver: Introduce ResponseRecorder as per Tw's suggestions
It implements io.ReaderFrom and has some allocation-reducing
optimizations baked into it
* templates: Increase execution speed by ~10-15% after perf regression
By using httpserver.ResponseBuffer, we can reduce allocations and still
get what we want. It's a little tricky but it works so far.