mod_extract_forwarded is designed to transparently modify a connection so that it looks like it came from the IP behind a proxy server rather than the proxy itself. This affects all subsequent stages of request processing including access control, logging, and CGIs. It relies on the "X-Forwarded-For" header to do this. This header should be added by all well-behaved proxies. If the proxy doesn't add it, we can't do anything about it. It's possible for a request to pass thru multiple proxies on its request path in which case X-Forwarded-For should contain multiple IPs. You will build a list of trusted proxies (see below) and the first IP in the header which is not trusted will be used as the client IP. Since we are altering the connection record to remove references to the actual connecting IP, it might be useful to remember that IP somewhere. We store it in the environment variable PROXY_ADDR immediately before altering the connection record. So CGIs have access to PROXY_ADDR if they need it. Other Apache modules can also get to PROXY_ADDR via the request_rec's subprocess_env table. Using this module has potentially serious implications for host-based access control to your server. Since "X-Forwarded-For" is just a piece of text in a request header spoofing it is trivial. To compensate for this mod_extract_forwarded provides configuration directives to restrict the proxy hosts for which X-Forwarded-For will be processed. Disallowing a proxy host with these directives doesn't mean the proxy can't get pages from your server, it just means the forwarded IP won't be used. It is _strongly_ advised that you only process "X-Forwarded-For" from proxies you trust. If a request has passed through multiple proxies then the X-Forwarded-For may contain several IPs like this: X-Forwarded-For: client1, proxy1, proxy2 Additionally there is the IP of the requesting host itself which is not included in the header. Let's say the requesting host is proxy3. First we check that the connecting host is in the allow list. Then we traverse the header from right to left and the first encountered IP which is not in the allow list will be treated as the client IP. For example if proxy1, proxy2, and proxy3 are in the allow list then in the above header client1 would be shown as the connecting IP. But in the below header: X-Forwarded-For: client1, untrusted1, proxy1, proxy2 untrusted1 would be shown as the connecting IP even though untrusted1 is proxying for client1. (Because untrusted1 might be lying.) There is also a directive for allow or disallowing the proxies to cache the returned content. You may find yourself in a situation where there may be some hosts behind a caching proxy which are allowed access to a URI but other hosts behind the same proxy which are not allowed. If the proxy caches the content when it responds to an allowed client, it might not re-check with your server before giving the cached content to another client.[1] If you find yourself in this situation use AllowForwarderCaching (described below) to deactivate caching for locations with protected content. The configuration directives are as follows: AllowForwarderCaching: On or Off - will we allow any caches along the request path to cache this response? AddAcceptForwarder: add this IP or hostname to the list of hosts from which we will honor the "X-Forwarded-For" header. RemoveAcceptForwarder: remove this IP or hostname from the list of hosts built with AddAcceptForwarder. If no directives are found the default is to ignore X-Forwarded-For from all proxies and to allow caching.[2] In other words if you load the module but don't configure it, it doesn't do anything. Like many other directives you may specify these at "top level" outside any container directives, then you may specify overriding directives inside containers. You may also use them inside .htaccess files if AllowOverride Options is in effect. The effect of the directives is cumulative. Example: AddAcceptForwarder 10.0.0.1 AddAcceptForwarder 10.0.0.2 AllowForwarderCaching On RemoveAcceptForwarder 10.0.0.2 AllowForwarderCaching Off So now inside /foobar 10.0.0.1 is still accepted but 10.0.0.2 is not, but 10.0.0.1 is not allowed to cache responses. (Perhaps /foobar contains some sensitive content.) AddAcceptForwarder and RemoveAcceptForwarder also take an "all" keyword which does exactly that - "AddAcceptForwarder all" will accept X-Forwarded-For from all proxies and "RemoveAcceptForwarder all" will totally blank the accept list. The "all" keyword makes possible something like this: AddAcceptForwarder all RemoveAcceptFowarder 10.0.0.3 RemoveAcceptForwarder all AddAcceptFowarder 10.0.0.4 At top level we accept from all proxies _except_ 10.0.0.3. Inside /foobaz we totally blank the accept list and then accept from _only_ 10.0.0.4. The ordering in which the directives appear in a container is not fixed, but the order of their processing is explicit: (1) RemoveAcceptForwarder all (2) AddAcceptForwarder all (3) any other RemoveAcceptForwarders (4) any other AddAcceptForwarders Those rules might seem restrictive at first but in practice you won't even have to know them. They are based on the premise that you won't try to remove your own AddAcceptForwarders inside the same container. If you do (why?!) you won't get what your expect. But on the whole the rules will behave very naturally. [1] I wasn't able to get squid 2.2 to do this (i.e. give cached content to a disallowed client) but I also haven't tried any other proxies. The possibility is always there. Once the content is cached, you've lost control of it. [2] The reasoning here is that since we're not honoring any X-Forwarded-Fors we can't be spoofed, so caching is safe. As soon as you put in your first AddAcceptForwarder you should think about caching. ahosey@systhug.com $Id: README,v 1.5 2003/03/18 21:27:31 ahosey Exp $