1

Summary

When mod_remoteip is in use and some proxy in front of apache HTTPD is configured with the RemoteIPInternalProxy my.proxy.ip directive in the HTTPD server configuration, how to check if an incoming request is actually forwarded by the proxy? Obviously:

 <If "%{REMOTE_ADDR} == 'my.proxy.ip'">

does no longer work.

Which expression would return true if and only if the request is coming in from the proxy IP, no matter for which client IP?

Long Version

In our intranet we have a proxy set up to let the clients access several web applications, like:

   +-------------+
   |             |
   |   Client    |
   |             |
   +-------------+
          |
          |
          |
          V
   +--------------+                     +-----------+
   |              |   Authentication    |           |
   |    Proxy     | <-----------------> |    LDAP   |
   |              |                     |           |
   +--------------+                     +-----------+
          |
          |
          | send header 
          |    Trusted-User: <some.username>
          |
          V
     +-----------------+
     |                 |
  +----------------+   | ...
  |                |   |
  |  Applications  |---+
  |                |
  +----------------+

The proxy also serves as login server, providing SSO across the proxied applications. This works because the applications are configured to acccept a certain HTTP header Trusted-User to contain the name of the user to be logged in.

Of course this header can be easily spoofed; the application web servers need to check that the request is really send by the proxy and reject/ignore the header otherwise. The applications use Apache HTTPD as web server.

Currently every web server has the following section in the configuration for the relevant VirtualHost:

<If "%{REMOTE_ADDR} != 'my.proxy.ip'">
    RequestHeader unset Trusted-User
</If>

This worked so far, but now I have the requirement that some applications should see the actual client IP and not the IP of the proxy.

The obvious way to achieve this is mod_remoteip with a config like:

  <IfModule mod_remoteip.c>
            RemoteIPHeader X-Forwarded-For
            RemoteIPInternalProxy my.proxy.ip
  </IfModule>

However as soon as I do that, the condition which unsets the Trusted-User header breaks the SSO, as this now sees the client IP in the REMOTE_ADDR variable. So I need another way to access the IP the request is currently coming from.

(Admittedly the check is not really necessary as the firewall configuration on every application server is configured to only accept incoming HTTP traffic from the proxy, but just in case there is a mishap I prefer to have this additional check in place.)

Using apache HTTPD 2.4.23 on all application servers.

What I have tried

Use the X-Forwarded-For header in the applications to get the remote client IP

Some applications can be configured to use this header, if present, but others cannot; they use the PHP expression $_SERVER['REMOTE_ADDR'] or the corresponding expression in whatever language that are written to get the client IP, and I really do not want to patch these applications.

Try to access the remoteip-proxy-ip-list variable

From the mod_remoteip documentation

In overriding the client IP, the module stores the list of intermediate hosts in a remoteip-proxy-ip-list note, which mod_log_config can record using the %{remoteip-proxy-ip-list}n format token.

Also the Expression in Apache HTTPD functions reference:

Functions

  [...]
  | note  |  Lookup request note
  [...]

So I tried something like:

<If "! note('remoteip-proxy-ip-list') -strmatch '*my.proxy.ip*'">
    RequestHeader unset Trusted-User
</If>

However this removed the header all the time, too. An inspection via a custom log format showed that the %{remoteip-proxy-ip-list}n always resolved to the empty placeholder -, even though the log format token %{c}a showed the proxy IP, as expected.

It seems to me that I misunderstood the phrase "intermediate hosts", as this variable simply does not do what I think it should.

And nginx ?

As there are several application, some with complicated configurations, I prefer to stick to Apache, if possible. However if what I want is not possible with Apache HTTPD I will consider solutions involving nginx.

1

I should have read the documentation about expression variables more carefully, as it says there:

[...]
| REMOTE_ADDR      | The IP address of the remote host
[...] 
| CONN_REMOTE_ADDR | The peer IP address of the connection (see the mod_remoteip module)
[...]

So there is a predefined variable CONN_REMOTE_ADDR, and

   <If "%{CONN_REMOTE_ADDR} != 'my.proxy.ip'">
       RequestHeader unset Trusted-User
   </If>

does the trick.

0

I haven't tested this, but have you tried to set a Variable to REMOTE_ADDR at the start of your configuration, and use this Variable in your If Statement:

Define ORIG_ADDR %{REMOTE_ADDR}

And use this variable in your If Statement

<If "${ORIG_ADDR} != 'my.proxy.ip'">
    RequestHeader unset Trusted-User
</If>
1
  • I have tried this. but even if I add the Define ORIG_ADDR %{REMOTE_ADDR} at the start of the main apache config file, the variable ${ORIG_ADDR} still ends up being filled with the client IP, not the proxy IP. – Clemens Klein-Robbenhaar Apr 24 '20 at 10:11

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.