Project

General

Profile

Trust and relay downstream HTTP Remote-User header behind proxy

Added by markfqs 3 months ago

Hi there

Running lighttpd/1.4.57 on alpine linux docker container.

Scenario:

I have lighttpd configured to do authentication on specific requests of the website. As usual (I think) the CGI backend checks for the REMOTE_USER environment variable to check for the authenticated user. This setup is working fine.

I want to put this lighttpd instance behind a proxy which also provide authentication. The proxy pass the HTTP Remote-User header request to lightty indicating the authenticated username.

The CGI take care about authorization by itself, lighttpd must only provide authentication (the username). That's why I manually set the REMOTE_USER to 'nobody' when auth not available (like a anonymous access).

My goal:

Make lightty TRUST the HTTP-Remote-User header if present and pass it downstream to the backend CGI thru the REMOTE_USER environment variable (as the standard authentication do). However if the header is not present (i.e. not authenticated by the proxy) then failback to its own authentication-backend.

My configuration (snippet with relevant comments):

# Requests requiring authentication
$HTTP["url"] =~ "^/private/" {
    # Check if Authenticated by proxy
    $REQUEST_HEADER["Remote-User"] == "" {
        # No auth present, auth ourselves
        auth.require = (
            "" => (
                "method" => "basic",
                "realm" => "Private",
                "require" => "valid-user" 
            )
        )
    } else {
        # Already autenticated by the proxy
        # WHAT TO DO HERE ?
    }
} else {
    # Anonymous requests
    setenv.add-request-header = ("Remote-User" => "nobody")
    setenv.add-environment += (
        "REMOTE_USER"  => "nobody" 
    )
}

The configuration snippets works fine on identifying the requests that need to be secured (HTTP[url] block) as well as when the Proxy sent the HTTP-Remote-User header (REQUEST_HEADER['Remote-User'] block). What I'm failing to achieve is to pass this forwarded header to the CGI Environment REMOTE_USER.

What I tried:

The config block where I'm struggling is the "WHAT TO DO HERE?" comment part. I should set REMOTE_USER to the upstream Remote-User HTTP header, but I haven't found how to do so.

I tried using extforward module:

extforward.forwarder = ( "all" => "trust" ) # I know this is insecure
extforward.headers = (
    "X-Forwarded-For",
    "X-Forwarded-Host",
    "X-Forwarded-Port",
    "X-Forwarded-Proto",
    "X-Forwarded-Server",
    "Remote-User" 
)
extforward.params = (
    "host"          => 1,
    "remote_user"   => 1
)

Also tried with the (documentation on https://redmine.lighttpd.net/projects/lighttpd/wiki/Docs_ModAuth) states:


# check REMOTE_USER (if set) against require rules prior to applying auth.backend
# REMOTE_USER might be set by another module, e.g. mod_openssl client cert verification
# and REMOTE_USER configured with ssl.verifyclient.username)
# (since lighttpd 1.4.46)
auth.extern-authn = "enable" 

Another option would be to manually set the REMOTE_USER environment to the upstream header, but I don't know how to (which syntax) assing variable values (not constant literals) to an environment variable in lighttpd:

setenv.add-environment += (
    "REMOTE_USER"  => "$HTTP_REMOTE_USER" ??
)

As the order of loading modules is relevant, these are the ones I use:

server.modules = (
    "mod_extforward",
    "mod_setenv",
    "mod_rewrite",
    "mod_alias",
    "mod_auth",
    "mod_access",
    "mod_status",
    "mod_accesslog",
    "mod_cgi" 
)

I know the CGI could check the HTTP Remote-User header by itself, but currently expect this to be set on REMOTE_USER Environment variable and I don't want to dive into the code to modify this (as there are multiple CGIs there all using REMOTE_USER env var).

Thanks much for any hint or pointing me to the right direction. Let me know if further details, config or information you might need.

Regards


Replies (1)

RE: Trust and relay downstream HTTP Remote-User header behind proxy - Added by gstrauss 3 months ago

Another option would be to manually set the REMOTE_USER environment to the upstream header, but I don't know how to (which syntax) assing variable values (not constant literals) to an environment variable in lighttpd:

No, not an option. lighttpd configuration syntax is not a Turing-complete programming language, and does not intend to be one.

Possible solution: What I think you're looking for is mod_magnet where you can write a few short lines of Lua code to take your arbitrary header and set REMOTE_USER in the environment that is then passed to CGI.

Please take precautions to trust that "Remote-User" header only from trusted proxies (or ensure that only trusted proxies can directly reach the lighttpd server).

    (1-1/1)