forwardproxy: add probe_resistance_auth_external for use with external auth
Some checks failed
Build / build_caddy_with_naive (push) Has been cancelled

Add a new field ProbeResistanceAuthExternal that allows probe_resistance
to work without auth_credentials configured in forwardproxy itself.
This enables setups where authentication is handled externally (e.g. via
Caddy's forward_auth directive placed before forward_proxy in the route
order).

- New field: ProbeResistanceAuthExternal (bool)
- Provision() now skips the probe_resistance requires authentication
  check when this flag is set
- Mutually exclusive with auth_credentials
- Caddyfile subdirective: probe_resistance_auth_external
This commit is contained in:
Niko Marmeladkov 2026-06-17 17:22:33 +03:00
parent d62c80d3dd
commit b30a0cfbae
Signed by untrusted user who does not match committer: Niko
GPG key ID: E3B955F9442D44E3
2 changed files with 23 additions and 7 deletions

View file

@ -121,6 +121,16 @@ func (h *Handler) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
h.ProbeResistance = &ProbeResistance{} h.ProbeResistance = &ProbeResistance{}
} }
case "probe_resistance_auth_external":
args := d.RemainingArgs()
if len(args) != 0 {
return d.ArgErr()
}
if h.ProbeResistanceAuthExternal {
return d.Err("probe_resistance_auth_external specified twice")
}
h.ProbeResistanceAuthExternal = true
case "serve_pac": case "serve_pac":
args := d.RemainingArgs() args := d.RemainingArgs()
if len(args) > 1 { if len(args) > 1 {

View file

@ -75,6 +75,11 @@ type Handler struct {
// Optional probe resistance. (See documentation.) // Optional probe resistance. (See documentation.)
ProbeResistance *ProbeResistance `json:"probe_resistance,omitempty"` ProbeResistance *ProbeResistance `json:"probe_resistance,omitempty"`
// ProbeResistanceAuthExternal indicates that authentication for
// probe_resistance is handled externally (e.g., via forward_auth)
// and forwardproxy should not require its own auth_credentials.
ProbeResistanceAuthExternal bool `json:"probe_resistance_auth_external,omitempty"`
// How long to wait before timing out initial TCP connections. // How long to wait before timing out initial TCP connections.
DialTimeout caddy.Duration `json:"dial_timeout,omitempty"` DialTimeout caddy.Duration `json:"dial_timeout,omitempty"`
@ -169,13 +174,14 @@ func (h *Handler) Provision(ctx caddy.Context) error {
} }
h.aclRules = append(h.aclRules, &aclAllRule{allow: true}) h.aclRules = append(h.aclRules, &aclAllRule{allow: true})
if h.ProbeResistance != nil { if h.ProbeResistance != nil && h.AuthCredentials == nil && !h.ProbeResistanceAuthExternal {
if h.AuthCredentials == nil { return fmt.Errorf("probe resistance requires authentication")
return fmt.Errorf("probe resistance requires authentication") }
} if h.ProbeResistanceAuthExternal && h.AuthCredentials != nil {
if len(h.ProbeResistance.Domain) > 0 { return fmt.Errorf("probe_resistance_auth_external and auth_credentials are mutually exclusive")
h.logger.Info("Secret domain used to connect to proxy: " + h.ProbeResistance.Domain) }
} if h.ProbeResistance != nil && len(h.ProbeResistance.Domain) > 0 {
h.logger.Info("Secret domain used to connect to proxy: " + h.ProbeResistance.Domain)
} }
dialer := &net.Dialer{ dialer := &net.Dialer{