Wrapping listeners is useful for composing custom behavior related
to accepting, closing, reading/writing connections (etc) below the
application layer; for example, the PROXY protocol.
When using the default automation policy specifically, ap.Issuer would
be nil, so we'd end up overwriting the ap.magic.Issuer's default value
(after New()) with nil; this instead sets Issuer on the template before
New() is called, and no overwriting is done.
* pki: Initial commit of PKI app (WIP) (see #2502 and #3021)
* pki: Ability to use root/intermediates, and sign with root
* pki: Fix benign misnamings left over from copy+paste
* pki: Only install root if not already trusted
* Make HTTPS port the default; all names use auto-HTTPS; bug fixes
* Fix build - what happened to our CI tests??
* Fix go.mod
It's still not perfect but I think it should be more correct for
slightly more complex configs. Might still fall apart for complex
configs that use on-demand TLS or at a large scale (workarounds are
to just implement your own redirects, very easy to do anyway).
* ability to specify that client cert must be present in SSL
* changed the clientauthtype to string and make room for the values supported by go as in caddy1
* renamed the config parameter according to review comments and added documentation on allowed values
* missed a reference
* Minor cleanup; docs enhancements
Co-authored-by: Matthew Holt <mholt@users.noreply.github.com>
This is a breaking change primarily in two areas:
- Storage paths for certificates have changed
- Slight changes to JSON config parameters
Huge improvements in this commit, to be detailed more in
the release notes.
The upcoming PKI app will be powered by Smallstep libraries.
This makes it more convenient to configure quick proxies that use HTTPS
but also introduces a lot of logical complexity. We have to do a lot of
verification for consistency and errors.
Path and query string is not supported (i.e. no rewriting).
Scheme and port can be inferred from each other if HTTP(S)/80/443.
If omitted, defaults to HTTP.
Any explicit transport config must be consistent with the upstream
schemes, and the upstream schemes must all match too.
But, this change allows a config that used to require this:
reverse_proxy example.com:443 {
transport http {
tls
}
}
to be reduced to this:
reverse_proxy https://example.com
which is really nice syntactic sugar (and is reminiscent of Caddy 1).
* httpcaddyfile: Begin implementing log directive, and debug mode
For now, debug mode just sets the log level for all logs to DEBUG
(unless a level is specified explicitly).
* httpcaddyfile: Finish 'log' directive
Also rename StringEncoder -> SingleFieldEncoder
* Fix minor bug in replacer (when vals are empty)
* caddytls: Add CipherSuiteName and ProtocolName functions
The cipher_suites.go file is derived from a commit to the Go master
branch that's slated for Go 1.14. Once Go 1.14 is released, this file
can be removed.
* caddyhttp: Use commonLogEmptyValue in common_log replacer
* caddyhttp: Add TLS placeholders
* caddytls: update unsupportedProtocols
Don't export unsupportedProtocols and update its godoc to mention that
it's used for logging only.
* caddyhttp: simplify getRegTLSReplacement signature
getRegTLSReplacement should receive a string instead of a pointer.
* caddyhttp: Remove http.request.tls.client.cert replacer
The previous behavior of printing the raw certificate bytes was ported
from Caddy 1, but the usefulness of that approach is suspect. Remove
the client cert replacer from v2 until a use case is presented.
* caddyhttp: Use tls.CipherSuiteName from Go 1.14
Remove ported version of CipherSuiteName in the process.
* Add handler for unhandled errors in errorChain
Currently, when an error chain is defined, the default error handler is
bypassed entirely - even if the error chain doesn't handle every error.
This results in pages returning a blank 200 OK page.
For instance, it's possible for an error chain to match on the error
status code and only handle a certain subtype of errors (like 403s). In
this case, we'd want any other errors to still go through the default
handler and return an empty page with the status code.
This PR changes the "suffix handler" passed to errorChain.Compile to
set the status code of the response to the error status code.
Fixes#3053
* Move the errorHandlerChain middleware to variable
* Style fix
* Fix crash when specifying "*" to header directive.
Fixes#3060
* Look Host header in header and header_regexp.
Also, if more than one header is provided, header_regexp now looks for
extra headers values to reflect the behavior from header.
Fixes#3059
* Fix parsing of named header_regexp in Caddyfile.
See #3059
The documentation specifies that the hash algorithm defaults to bcrypt.
However, the implementation returns an error in provision if no hash is
provided.
Fix this inconsistency by *actually* defaulting to bcrypt.
We don't load the provider directly, because the lego provider types
aren't designed for JSON configuration and they are not implemented
as Caddy modules (there are some setup steps which a Provision call
would need to do, but they do not have Provision methods, they have
their own constructor functions that we have to wrap).
Instead of loading the challenge providers directly, the modules are
simple wrappers over the challenge providers, to facilitate the JSON
config structure and to provide a consistent experience. This also lets
us swap out the underlying challenge providers transparently if needed;
it acts as a layer of abstraction.
This is temporary as we prepare for a stable v2 release. We don't want
to make promises we don't know we can keep, and the Starlark integration
deserves much more focused attention which resources and funding do not
currently permit. When the project is financially stable, I will be able
to revisit this properly and add flexible, robust Starlark scripting
support to Caddy 2.
This ensure that if there are multiple certs that match a particular
ServerName or other parameter, then specifically the one the user
provided in the Caddyfile will be used.
This is necessary to avoid a race for sockets. Both the HTTP servers and
CertMagic solvers will try to bind the HTTP/HTTPS ports, but we need to
make sure that our HTTP servers bind first. This is kind of a new thing
now that management is async in Caddy 2.
Also update to CertMagic 0.9.2, which fixes some async use cases at
scale.
See https://caddy.community/t/caddy-server-that-returns-only-ip-address-as-text/6928/6?u=matt
In most cases, we will want to apply header operations immediately,
rather than waiting until the response is written. The exceptions are
generally going to be if we are deleting a header field or if a field is
to be overwritten. We now automatically defer header ops if deleting a
header field, and allow the user to manually enable deferred mode with
the defer subdirective.
Paths always begin with a slash, and omitting the leading slash could be
convenient to avoid confusion with a path matcher in the Caddyfile. I do
not think there would be any harm to implicitly add the leading slash.
* v2: add documentation for circuit breaker config and "random selection" load balancing policy
* v2: rename circuit breaker config inline key from `type` to `breaker` to avoid json key clash between the `circuit_breaker` type and the `type` field of the generic circuit breaker Config struct used by circuit breaking implementations
* v2: restore the circuit breaker inline key to `type` and rename the name circuit breaker config field from `Type` to `Factor`
The fix that was initially put forth in #2971 was good, but only for
up to one layer of nesting. The real problem was that we forgot to
increment nesting when already inside a block if we saw another open
curly brace that opens another block (dispenser.go L157-158).
The new 'handle' directive allows HTTP Caddyfiles to be designed more
like nginx location blocks if the user prefers. Inside a handle block,
directives are still ordered just like they are outside of them, but
handler blocks at a given level of nesting are mutually exclusive.
This work benefitted from some refactoring and cleanup.
Before, modifying the path might have affected how a new query string
was built if the query string relied on the path. Now, we build each
component in isolation and only change the URI on the request later.
Also, prevent trailing & in query string.
This splits automatic HTTPS into two phases. The first provisions the
route matchers and uses them to build the domain set and configure
auto HTTP->HTTPS redirects. This happens before the rest of the
provisioning does.
The second phase takes place at the beginning of the app start. It
attaches pointers to the tls app to each server, and begins certificate
management for the domains that were found in the first phase.
Our new parser also preserves original parameter order, rather than
re-encoding using the std lib (which sorts).
The renamed parameters are a breaking change but they're new enough
that I don't think anyone is using them.
* http: path matcher: exact match by default; substring matches (#2959)
This is a breaking change.
* caddyfile: Change "matcher" directive to "@matcher" syntax (#2959)
* cmd: Assume caddyfile adapter for config files named Caddyfile
* Sub-sort handlers by path matcher length (#2959)
Caddyfile-generated subroutes have handlers, which are sorted first by
directive order (this is unchanged), but within directives we now sort
by specificity of path matcher in descending order (longest path first,
assuming that longest path is most specific).
This only applies if there is only one matcher set, and the path
matcher in that set has only one path in it. Path matchers with two or
more paths are not sorted like this; and routes with more than one
matcher set are not sorted like this either, since specificity is
difficult or impossible to infer correctly.
This is a special case, but definitely a very common one, as a lot of
routing decisions are based on paths.
* caddyfile: New 'route' directive for appearance-order handling (#2959)
* caddyfile: Make rewrite directives mutually exclusive (#2959)
This applies only to rewrites in the top-level subroute created by the
HTTP caddyfile.
Previously, all matchers in a route would be evaluated before any
handlers were executed, and a composite route of the matching routes
would be created. This made rewrites especially tricky, since the only
way to defer later matchers' evaluation was to wrap them in a subroute,
or to invoke a "rehandle" which often caused bugs.
Instead, this new sequential design evaluates each route's matchers then
its handlers in lock-step; matcher-handlers-matcher-handlers...
If the first matching route consists of a rewrite, then the second route
will be evaluated against the rewritten request, rather than the original
one, and so on.
This should do away with any need for rehandling.
I've also taken this opportunity to avoid adding new values to the
request context in the handler chain, as this creates a copy of the
Request struct, which may possibly lead to bugs like it has in the past
(see PR #1542, PR #1481, and maybe issue #2463). We now add all the
expected context values in the top-level handler at the server, then
any new values can be added to the variable table via the VarsCtxKey
context key, or just the GetVar/SetVar functions. In particular, we are
using this facility to convey dial information in the reverse proxy.
Had to be careful in one place as the middleware compilation logic has
changed, and moved a bit. We no longer compile a middleware chain per-
request; instead, we can compile it at provision-time, and defer only the
evaluation of matchers to request-time, which should slightly improve
performance. Doing this, however, we take advantage of multiple function
closures, and we also changed the use of HandlerFunc (function pointer)
to Handler (interface)... this led to a situation where, if we aren't
careful, allows one request routed a certain way to permanently change
the "next" handler for all/most other requests! We avoid this by making
a copy of the interface value (which is a lightweight pointer copy) and
using exclusively that within our wrapped handlers. This way, the
original stack frame is preserved in a "read-only" fashion. The comments
in the code describe this phenomenon.
This may very well be a breaking change for some configurations, however
I do not expect it to impact many people. I will make it clear in the
release notes that this change has occurred.
Allows specifying ca certs with by filename in
`reverse_proxy.transport`.
Example
```
reverse_proxy /api api:443 {
transport http {
tls
tls_trusted_ca_certs certs/rootCA.pem
}
}
```
It seems silly to have to add a single, empty TLS connection policy to
a server to enable TLS when it's only listening on the HTTPS port. We
now do this for the user as part of automatic HTTPS (thus, it can be
disabled / overridden).
See https://caddy.community/t/v2-catch-all-server-with-automatic-tls/6692/2?u=matt
This commit goes a long way toward making automated documentation of
Caddy config and Caddy modules possible. It's a broad, sweeping change,
but mostly internal. It allows us to automatically generate docs for all
Caddy modules (including future third-party ones) and make them viewable
on a web page; it also doubles as godoc comments.
As such, this commit makes significant progress in migrating the docs
from our temporary wiki page toward our new website which is still under
construction.
With this change, all host modules will use ctx.LoadModule() and pass in
both the struct pointer and the field name as a string. This allows the
reflect package to read the struct tag from that field so that it can
get the necessary information like the module namespace and the inline
key.
This has the nice side-effect of unifying the code and documentation. It
also simplifies module loading, and handles several variations on field
types for raw module fields (i.e. variations on json.RawMessage, such as
arrays and maps).
I also renamed ModuleInfo.Name -> ModuleInfo.ID, to make it clear that
the ID is the "full name" which includes both the module namespace and
the name. This clarity is helpful when describing module hierarchy.
As of this change, Caddy modules are no longer an experimental design.
I think the architecture is good enough to go forward.
Adds tests for both the path matcher and host matcher for case
insensitivity.
If case sensitivity is required for the path, a regexp matcher can
be used instead.
This is the v2 equivalent fix of PR #2882.
* fix OOM issue caught by fuzzing
* use ParsedAddress as the struct name for the result of ParseNetworkAddress
* simplify code using the ParsedAddress type
* minor cleanups
* Add support for placeholders in Config
Fixes#2870
* Replace placeholders only in logging config.
Placeholders in log level and filename incase of file output are replaced.
* Add Provision to filewriter module for replacing placeholders
Errors in the 4xx range are client errors, and they don't need to be
entered into the server's error logs. 4xx errors are still recorded in
the access logs at the error level.
This makes it easier to make "standard" caddy builds, since you'll only
need to add a single import to get all of Caddy's standard modules.
There is a package for all of Caddy's standard modules (modules/standard)
and a package for the HTTP app's standard modules only
(modules/caddyhttp/standard).
We still need to decide which of these, if not all of them, should be
kept in the standard build. Those which aren't should be moved out of
this repo. See #2780.
* logging: Initial implementation
* logging: More encoder formats, better defaults
* logging: Fix repetition bug with FilterEncoder; add more presets
* logging: DiscardWriter; delete or no-op logs that discard their output
* logging: Add http.handlers.log module; enhance Replacer methods
The Replacer interface has new methods to customize how to handle empty
or unrecognized placeholders. Closes#2815.
* logging: Overhaul HTTP logging, fix bugs, improve filtering, etc.
* logging: General cleanup, begin transitioning to using new loggers
* Fixes after merge conflict
* file_server: Make tests work on Windows
* caddyfile: Fix escaping when character is not escapable
We only escape certain characters depending on inside or outside of
quotes (mainly newlines and quotes). We don't want everyone to have to
escape Windows file paths like C:\\Windows\\... but we can't drop the
\ either if it's just C:\Windows\...
* v2: split golangci-lint configuration into its own file to allow code editors to take advantage of it
* v2: simplify code
* v2: set the correct lint output formatting
* v2: invert the logic of linter's configuration of output formatting to allow the editor convenience over CI-specific customization. Customize the output format in CI by passing the flag.
* v2: remove irrelevant golangci-lint config
This PR enables the use of placeholders in an upstream's Dial address.
A Dial address must represent precisely one socket after replacements.
See also #998 and #1639.
This implements HTTP basicauth into Caddy 2. The basic auth module will
not work with passwords that are not securely hashed, so a subcommand
hash-password was added to make it convenient to produce those hashes.
Also included is Caddyfile support.
Closes#2747.
This migrates a feature that was previously reserved for enterprise
users, according to #2786.
The Starlark integration needs to be updated since this was made before
some significant changes in the v2 code base. When functional, it makes
it possible to have very dynamic HTTP handlers. This will be a long-term
ongoing project.
Credit to Danny Navarro
This migrates a feature that was previously reserved for enterprise
users, according to https://github.com/caddyserver/caddy/issues/2786.
Custom certificate selection policies allow advanced control over which
cert is selected when multiple qualify to satisfy a TLS handshake.
This migrates a feature that was previously reserved for enterprise
users, according to https://github.com/caddyserver/caddy/issues/2786.
TLS session ticket keys are sensitive, so they should be rotated on a
regular basis. Only Caddy does this by default. However, a cluster of
servers that rotate keys without synchronization will lose the benefits
of having sessions in the first place if the client is routed to a
different backend. This module coordinates STEK rotation in a fleet so
the same keys are used, and rotated, across the whole cluster. No other
server does this, but Twitter wrote about how they hacked together a
solution a few years ago:
https://blog.twitter.com/engineering/en_us/a/2013/forward-secrecy-at-twitter.html
This migrates a feature that was previously reserved for enterprise
users, according to https://github.com/caddyserver/caddy/issues/2786.
The PEM loader allows you to embed PEM files (certificates and keys)
directly into your config, rather than requiring them to be stored on
potentially insecure storage, which adds attack vectors. This is useful
in automated settings where sensitive key material is stored only in
memory.
Note that if the config is persisted to disk, that added benefit may go
away, but there will still be the benefit of having lesser dependence on
external files.
This migrates a feature that was previously reserved for enterprise
users, according to https://github.com/caddyserver/caddy/issues/2786.
The local circuit breaker is a simple metrics counter that can cause
the reverse proxy to consider a backend unhealthy before it actually
goes offline, by measuring recent latencies over a sliding window.
Credit to Danny Navarro
This migrates a feature that was previously reserved for enterprise
users, according to https://github.com/caddyserver/caddy/issues/2786.
The cache HTTP handler will be a high-performing, distributed cache
layer for HTTP requests. Right now, the implementation is a very basic
proof-of-concept, and further development is required.
Making them pointers makes for cleaner JSON when adapting configs, if
the struct is empty now it will be omitted entirely.
The x/time/rate package was updated to support changing the burst, so
we've incorporated that here and removed a TODO.
Before this change, only response headers could be manipulated with the
Caddyfile's 'header' directive.
Also handle the request Host header specially, since the Go standard
library treats it separately from the other header fields...