Add check endpoint which can be used with nginx' auth_request function (#266)

* Add check endpoint which can be used with nginx' auth_request function

* feat(cmd): allow configuring redirect domains

* test: add test environment for the nginx_auth PR

This is a full local setup of the nginx_auth PR including HTTPS so that
it's easier to validate in isolation.

This requires an install of k3s (https://k3s.io) with traefik set to
listen on localhost. This will be amended in the future but for now this
works enough to ship it.

Signed-off-by: Xe Iaso <me@xeiaso.net>

* fix(cmd|lib): allow empty redirect domains variable

Signed-off-by: Xe Iaso <me@xeiaso.net>

* fix(test): add space to target variable in anubis container

Signed-off-by: Xe Iaso <me@xeiaso.net>

* docs(admin): rewrite subrequest auth docs, make generic

* docs(install): document REDIRECT_DOMAINS flag

Signed-off-by: Xe Iaso <me@xeiaso.net>

* feat(lib): clamp redirects to the same HTTP host

Only if REDIRECT_DOMAINS is not set.

Signed-off-by: Xe Iaso <me@xeiaso.net>

---------

Signed-off-by: Xe Iaso <me@xeiaso.net>
Co-authored-by: Xe Iaso <me@xeiaso.net>
This commit is contained in:
Sandro 2025-04-25 19:38:02 +02:00 committed by GitHub
parent a5d796c679
commit 6858f66a62
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
20 changed files with 610 additions and 52 deletions

View file

@ -50,8 +50,9 @@ var (
socketMode = flag.String("socket-mode", "0770", "socket mode (permissions) for unix domain sockets.")
robotsTxt = flag.Bool("serve-robots-txt", false, "serve a robots.txt file that disallows all robots")
policyFname = flag.String("policy-fname", "", "full path to anubis policy document (defaults to a sensible built-in policy)")
redirectDomains = flag.String("redirect-domains", "", "list of domains separated by commas which anubis is allowed to redirect to. Leaving this unset allows any domain.")
slogLevel = flag.String("slog-level", "INFO", "logging level (see https://pkg.go.dev/log/slog#hdr-Levels)")
target = flag.String("target", "http://localhost:3923", "target to reverse proxy to")
target = flag.String("target", "http://localhost:3923", "target to reverse proxy to, set to an empty string to disable proxying when only using auth request")
healthcheck = flag.Bool("healthcheck", false, "run a health check against Anubis")
useRemoteAddress = flag.Bool("use-remote-address", false, "read the client's IP address from the network request, useful for debugging and running Anubis on bare metal")
debugBenchmarkJS = flag.Bool("debug-benchmark-js", false, "respond to every request with a challenge for benchmarking hashrate")
@ -195,9 +196,14 @@ func main() {
return
}
rp, err := makeReverseProxy(*target)
if err != nil {
log.Fatalf("can't make reverse proxy: %v", err)
var rp http.Handler
// when using anubis via Systemd and environment variables, then it is not possible to set targe to an empty string but only to space
if strings.TrimSpace(*target) != "" {
var err error
rp, err = makeReverseProxy(*target)
if err != nil {
log.Fatalf("can't make reverse proxy: %v", err)
}
}
policy, err := libanubis.LoadPoliciesOrDefault(*policyFname, *challengeDifficulty)
@ -252,6 +258,20 @@ func main() {
slog.Warn("generating random key, Anubis will have strange behavior when multiple instances are behind the same load balancer target, for more information: see https://anubis.techaro.lol/docs/admin/installation#key-generation")
}
var redirectDomainsList []string
if *redirectDomains != "" {
domains := strings.Split(*redirectDomains, ",")
for _, domain := range domains {
_, err = url.Parse(domain)
if err != nil {
log.Fatalf("cannot parse redirect-domain %q: %s", domain, err.Error())
}
redirectDomainsList = append(redirectDomainsList, strings.TrimSpace(domain))
}
} else {
slog.Warn("REDIRECT_DOMAINS is not set, Anubis will only redirect to the same domain a request is coming from, see https://anubis.techaro.lol/docs/admin/configuration/redirect-domains")
}
s, err := libanubis.New(libanubis.Options{
Next: rp,
Policy: policy,
@ -261,6 +281,7 @@ func main() {
CookiePartitioned: *cookiePartitioned,
OGPassthrough: *ogPassthrough,
OGTimeToLive: *ogTimeToLive,
RedirectDomains: redirectDomainsList,
Target: *target,
WebmasterEmail: *webmasterEmail,
})