diff --git a/cmd/anubis/main.go b/cmd/anubis/main.go index add0fec..9c1dab7 100644 --- a/cmd/anubis/main.go +++ b/cmd/anubis/main.go @@ -56,6 +56,7 @@ var ( 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, set to an empty string to disable proxying when only using auth request") + targetHost = flag.String("target-host", "", "if set, the value of the Host header when forwarding requests to the target") targetInsecureSkipVerify = flag.Bool("target-insecure-skip-verify", false, "if true, skips TLS validation for the backend") 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") @@ -135,7 +136,7 @@ func setupListener(network string, address string) (net.Listener, string) { return listener, formattedAddress } -func makeReverseProxy(target string, insecureSkipVerify bool) (http.Handler, error) { +func makeReverseProxy(target string, targetHost string, insecureSkipVerify bool) (http.Handler, error) { targetUri, err := url.Parse(target) if err != nil { return nil, fmt.Errorf("failed to parse target URL: %w", err) @@ -167,6 +168,14 @@ func makeReverseProxy(target string, insecureSkipVerify bool) (http.Handler, err rp := httputil.NewSingleHostReverseProxy(targetUri) rp.Transport = transport + if targetHost != "" { + originalDirector := rp.Director + rp.Director = func(req *http.Request) { + originalDirector(req) + req.Host = targetHost + } + } + return rp, nil } @@ -205,7 +214,7 @@ func main() { // 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, *targetInsecureSkipVerify) + rp, err = makeReverseProxy(*target, *targetHost, *targetInsecureSkipVerify) if err != nil { log.Fatalf("can't make reverse proxy: %v", err) } diff --git a/docs/docs/CHANGELOG.md b/docs/docs/CHANGELOG.md index 702f4ac..a32c42c 100644 --- a/docs/docs/CHANGELOG.md +++ b/docs/docs/CHANGELOG.md @@ -18,6 +18,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Updated the nonce value in the challenge JWT cookie to be a string instead of a number - Rename cookies in response to user feedback - Ensure cookie renaming is consistent across configuration options +- Add `--target-host` flag/envvar to allow changing the value of the Host header in requests forwarded to the target service. - Bump AI-robots.txt to version 1.30 (add QualifiedBot) - Add `RuntimeDirectory` to systemd unit settings so native packages can listen over unix sockets diff --git a/docs/docs/admin/installation.mdx b/docs/docs/admin/installation.mdx index 431386f..1bbcd5b 100644 --- a/docs/docs/admin/installation.mdx +++ b/docs/docs/admin/installation.mdx @@ -84,6 +84,7 @@ If you don't know or understand what these settings mean, ignore them. These are | Environment Variable | Default value | Explanation | | :---------------------------- | :------------ | :-------------------------------------------------------------------------------------------------------------------------------------------------- | +| `TARGET_HOST` | unset | If set, overrides the Host header in requests forwarded to `TARGET`. | | `TARGET_INSECURE_SKIP_VERIFY` | `false` | If `true`, skip TLS certificate validation for targets that listen over `https`. If your backend does not listen over `https`, ignore this setting. |