Mod extforward » History » Revision 33
Revision 32 (gstrauss, 2020-06-11 19:45) → Revision 33/36 (gstrauss, 2021-10-13 02:30)
h1. mod_extforward {{>toc}} *Module: mod_extforward* h2. Description This module will extract the client's "real" IP from Forwarded or X-Forwarded-For header which is added by Squid or other proxies. It might be useful for servers behind reverse proxy servers. h2. Options * *extforward.headers* Sets headers to search for finding the original addresses. Default: empty, results in searching for "X-Forwarded-For" and "Forwarded-For" Example (for use with a Zeus ZXTM loadbalancer): @extforward.headers = ("X-Cluster-Client-Ip")@ Since lighttpd 1.4.46, mod_extforward supports "Forwarded" (RFC7239). Since the header is spoofable through proxies which do not understand "Forwarded", this is not enabled by default and must be configured e.g. with @extforward.headers = ("Forwarded", "X-Forwarded-For")@ * *extforward.forwarder* Sets trust level of proxy IP's. Default: empty Example of usage: @extforward.forwarder = ("10.0.0.232" => "trust")@ will translate ip addresses coming from 10.0.0.232 to real ip addresses extracted from X-Forwarded-For (or whatever is specified in extforward.headers) HTTP request header. CIDR masks (e.g. "10.0.0.0/8" => "trust") are supported (since 1.4.50), but only for trusted IPs (not "untrusted"). *Important note*: The effect of this module is variable on $HTTP["remoteip"] directives and other module's remote ip dependent actions. Things done by modules before we change the remoteip or after we reset it will match on the proxy's IP. Things done in between these two moments will match on the real client's IP. The moment things are done by a module depends on in which hook it does things and within the same hook on whether they are before/after us in the module loading order (order in the server.modules directive in the config file). Tested behaviours: mod_access: Will match on the real client. mod_accesslog: In order to see the "real" ip address in access log, you'll have to load mod_extforward after mod_accesslog, like this: <pre> @server.modules server.modules = ( ...., .... "mod_accesslog", "mod_extforward", .... )@ (This is no longer necessary with lighttpd 1.4.61 or later) "mod_extforward" ) </pre> * *extforward.params* (since 1.4.46) When processing "Forwarded" request header, @extforward.params@ sets which values to propagate. "for" and "proto" are always enabled (not configurable) to maintain the existing behavior in mod_extforward. See also [[Docs_ModProxy]] for @proxy.forwarded@. <pre> extforward.params = ( #"host" => 1, # overwrite "Host" with Forwarded value #"remote_user" => 1, # set REMOTE_USER with Forwarded value ) </pre> * *extforward.hap-PROXY* (since 1.4.46) Enable processing of HAProxy PROXY protocol v1 or v2 (http://www.haproxy.org/download/1.8/doc/proxy-protocol.txt) mod_extforward must be loaded _after_ mod_openssl in @server.modules@ for this to work. Also, note that when @extforward.hap-PROXY = "enable"@, mod_extforward will process HAProxy PROXY protocol requests only for trusted proxies configured in @extforward.forwarder@. The client IP address presented to other modules such as mod_access and mod_accesslog will be the IP address provided by the HAProxy PROXY protocol. * *extforward.hap-PROXY-ssl-client-verify* (since 1.4.46) Enable setting SSL_CLIENT_VERIFY from HAProxy PROXY protocol. h2. Samples Trust proxy 2001:db8::232, 2001:db8::233, 10.0.0.232 and 10.0.0.233 <pre> extforward.forwarder = ( "2001:db8::232" => "trust", "2001:db8::233" => "trust" "10.0.0.232" => "trust", "10.0.0.233" => "trust" ) </pre> Restore visitor original IP when using Cloudflare proxy (https://www.cloudflare.com/ips-v4) <pre> extforward.forwarder = ( "173.245.48.0/20" => "trust", "103.21.244.0/22" => "trust", "103.22.200.0/22" => "trust", "103.31.4.0/22" => "trust", "141.101.64.0/18" => "trust", "108.162.192.0/18" => "trust", "190.93.240.0/20" => "trust", "188.114.96.0/20" => "trust", "197.234.240.0/22" => "trust", "198.41.128.0/17" => "trust", "162.158.0.0/15" => "trust", "104.16.0.0/12" => "trust", "172.64.0.0/13" => "trust", "131.0.72.0/22" => "trust", ) extforward.headers = ("CF-Connecting-IP") </pre> Trust all proxies (NOT RECOMMENDED!) <pre> extforward.forwarder = ( "all" => "trust") </pre> Note that "all" has precedence over specific entries, so "all except" setups will not work. h2. Using $HTTP["scheme"] rules If you are running lighttpd behind a reverse proxy (such as haproxy) to provide HTTPS termination, you may want to configure lighttpd rules which act on $HTTP["scheme"] == "https" etc As of lighttpd 1.4.40, mod_extforward is able to detect the scheme from the front proxy, allowing you to use scheme based conditional rules in lighttpd.conf In order to do this, extforward.headers (default X-Forwarded-For, Forwarded-For) must match a corresponding HTTP request header, as well as the proxy being "trusted" via extforward.forwarder h2. Security In general, data from external sources should not be trusted. This includes HTTP request headers. In certain _controlled_ environments, it may be desirable to extend limited trust to _some_ of this information. mod_extforward trusts some information provided by proxies with IPs that mod_extforward has been configured to trust. These proxies must, in turn, be configured to _always_ append information to the headers mod_extforward trusts, e.g. X-Forwarded-For. There are many (non-standard) HTTP request header extensions and conventions proposed over the years in order to propagate IP and other information through proxies since that information might otherwise be unavailable to proxies further down the line. Depending on the specific configuration of an environment, and the specific security requirements of that environment, it may be desirable to have lighttpd forcefully remove one or more non-standard HTTP request headers, e.g. using [[lighttpd:Docs_ModSetEnv|mod_setenv]] @setenv.set-request-header@ (since 1.4.46) and setting the values to blank @""@ to have them omitted. This may be useful if lighttpd [[lighttpd:Docs_ModProxy|mod_proxy]] is going to act as reverse proxy, or if it is undesirable in a specific environment to have CGI, FastCGI, SCGI, etc. see these request headers. <pre> setenv.set-request-header = ( #"Forwarded" => "", # RFC7239; the only standard HTTP request header in this list #"X-Forwarded-For" => "", # most common convention (non-standard HTTP request header) #"X-Forwarded-Proto" => "", # (used by mod_extforward if extforward.headers uses X-Forwarded-For) #"X-Host" => "", # set by lighttpd with Host #"X-Forwarded-Host" => "", # most common convention to which to append Host (set in lighttpd 1.4.46) "X-Forwarded-Server" => "", # fallback used by some frameworks if X-Forwarded-Host not present "X-Forwarded-By" => "", "X-Forwarded-Ssl" => "", "X-Origin-IP" => "", "X-Original-To" => "", "X-Real-IP" => "", "Forwarded-For" => "", "Via" => "", #... (more; not an exhaustive list) ) </pre>