Hello Elli,

   From what I understand of your architecture, I would configure
RemoteIpValve with :

<Valve
    className       = "org.apache.catalina.connector.RemoteIpValve"
    internalProxies = "@load-balancer-ip"
    trustedProxies  = "@the-trusted-proxy-that-is-not-the-load-balancer"
    protocolHeader = "x-forwarded-proto" />

Note :
- do not forget to "regexp escape' the ip adresses in internalProxies
and trustedProxies attributes.
- do not declare protocolHeader="x-forwarded-proto" if your load
balancer do not manage it
- more docs at http://code.google.com/p/xebia-france/wiki/RemoteIpValve

Thanks to this,
- the 99% direct requests will reach Tomcat with x-forwarded-for="@clientIp"
- 1% proxyfied requests will reach Tomcat with
x-forwarded-for="@clientIp,
@the-trusted-proxy-that-is-not-the-load-balancer"

Does it make sense ?

Cyrille

--
Cyrille Le Clerc
clecl...@xebia.fr cyri...@cyrilleleclerc.com
http://blog.xebia.fr

On Wed, Oct 21, 2009 at 6:57 AM, Elli Albek <e...@sustainlane.com> wrote:
>
> A question: How do you know that a proxy is trusted? Is it by providing a 
> list of trusted IPs in the configuration of the filter?
>
> Our load balancer is always adding the client IP as the first in the list, 
> and it does not add its own IP to the list. The header
> has one IP +99% of the times, the other times there is an additional IP of a 
> proxy that is not our load balancer (reverse proxy).
>
> So in that case, we can check that the request comes from a trusted IP list 
> (known load balancers), and only then try to change the
> IP. If the client IP does not come from the load balancer, it is basically a 
> pass through.
>
> For our system the first IP is what the load balancer sees, and the only way 
> to spoof it is to access the server not through the
> load balancer. If you send a request with a spoofed header to the laod 
> balancer, it will still add the IP of the spoofer in the
> beginning of the list.
>
> This may not be the general case for proxies, it is only for this case.
>
> E
>
> -----Original Message-----
> From: Cyrille Le Clerc [mailto:clecl...@xebia.fr]
> Sent: Thursday, October 08, 2009 1:04 AM
> To: Tomcat Users List
> Subject: Re: Cannot set remote address in valve (Tomcat 5.5)
>
>   Hello Elli,
>
>   I am afraid there may be a flaw in the algorythm looking for the
> first IP  of the coma delimited x-forwarded-for header without
> ensuring that this first IP has been set by a trusted proxy and not by
> the requester ( getFirstIP(xforwardedForHeaderValue) ). Such spoofing
> can easily be achieved with tools like Firefox add-ons Modify Headers
> (1) and X-Forwarded-For Spoofer (2) .
>
>   The forthcoming version of Apache Httpd will offer a secure
> mechanism to handle X-Forwarded-For with a module called mod_remoteip
> (3). It relies on the concept of trusted proxies which IP address can
> be 'swallowed'. The first IP of the list that is not a trusted proxy
> is seen as the real remote ip. mod_remoteip would not have been
> tricked by such x-forwarded-for header spoofing.
>
>   Here are two java ports of mod_remoteip to handle X-Forwarded-For
> at the Tomcat level with a valve and at the WAR level with a servlet
> filter : RemoteIpValve (4) and XForwardedFilter (5). In addition to
> handle X-Forwarded-For, they also integrate X-Forwarded-Proto (ssl).
> These java ports integrate the same trusted proxies concept to prevent
> spoofing.
>
>   Cyrille
> --
> Cyrille Le Clerc
> clecl...@xebia.fr cyri...@cyrilleleclerc.com
> http://blog.xebia.fr
>
>
> (1) https://addons.mozilla.org/en-US/firefox/addon/967
> (2) https://addons.mozilla.org/en-US/firefox/addon/5948
> (3) http://httpd.apache.org/docs/trunk/mod/mod_remoteip.html
> (4) http://code.google.com/p/xebia-france/wiki/RemoteIpValve
> (5) http://code.google.com/p/xebia-france/wiki/XForwardedFilter
>
>
> On Mon, Oct 5, 2009 at 11:19 PM, Elli Albek <e...@sustainlane.com> wrote:
> >
> > Hi,
> >
> > We can add the header to the custom valves, but then in addition we have to
> > change a few log file configurations, create a servlet filter and maybe
> > something else I cant think of now. Basically doing the same thing a few
> > times and keeping track of all the places that depend on the header. Ideally
> > this would all be corrected once in the beginning of the request processing
> > pipeline, so log file configuration, other valves and the war files will
> > remain unchanged.
> >
> >
> >
> > Attached a Valve that does that. This is the minimum code necessary, so it
> > should not have any significant performance impact.
> >
> > Feel free to use as is, not guaranteed to work, no expressed on implied
> > warranties, not FDIC insured and may loose value.
> >
> >
> >
> > To configure Tomcat add to server.xml:
> >
> >
> >
> > <Service name="Catalina">
> >
> >      <Connector port="8080" .../>
> >
> >      <Engine defaultHost="localhost" name="Catalina">
> >
> >            <!-- This should precede all other configuration in the engine
> > -->
> >
> >            <Valve className="org.apache.catalina.connector.RemoteIPValve"/>
> >
> >
> >
> > Java class/jar should be placed in /server/lib or /server/classes
> >
> >
> >
> > E
> >
> >
> >
> >
> >
> >
> >
> > package org.apache.catalina.connector;
> >
> >
> >
> > import java.io.IOException;
> >
> > import java.util.regex.Matcher;
> >
> > import java.util.regex.Pattern;
> >
> >
> >
> > import javax.servlet.ServletException;
> >
> >
> >
> > import org.apache.catalina.connector.Request;
> >
> > import org.apache.catalina.connector.Response;
> >
> > import org.apache.catalina.valves.ValveBase;
> >
> >
> >
> > /**
> >
> >  * A valve that extracts the remote IP of the client from an HTTP header
> > field
> >
> >  * passed by the proxy, and set it in the request as the original client IP.
> >
> >  * This valve should be the first valve in the engine, so log valves (and
> >
> >  * others) will see the real client IP without requiring the same code
> > again.
> >
> >  *
> >
> >  * @author Elli Albek, www.sustainlane.com
> >
> >  */
> >
> > public class RemoteIPValve extends ValveBase {
> >
> >
> >
> >      private static final Pattern ipExpr =
> > Pattern.compile("^[\\da-fA-F]+(\\.[\\da-fA-F]+)+");
> >
> >
> >
> >      private String forwardedForHeader = "X-Forwarded-For";
> >
> >
> >
> >      public void invoke(Request request, Response response) throws
> > IOException, ServletException {
> >
> >
> >
> >            String header = request.getHeader(forwardedForHeader);
> >
> >            String forwardedIP = getFirstIP(header);
> >
> >            if (forwardedIP != null)
> >
> >                  request.remoteAddr = forwardedIP;
> >
> >
> >
> >            next.invoke(request, response);
> >
> >      }
> >
> >
> >
> >      /**
> >
> >       * Return the first IP address in a string that may contain an IP list
> >
> >       */
> >
> >      static final String getFirstIP(String header) {
> >
> >            if (header == null)
> >
> >                  return null;
> >
> >            Matcher m = ipExpr.matcher(header);
> >
> >            if (m.find()) {
> >
> >                  return m.group();
> >
> >            }
> >
> >            return null;
> >
> >      }
> >
> >
> >
> >      public void setForwardedForHeader(String forwardedForHeader) {
> >
> >            this.forwardedForHeader = forwardedForHeader;
> >
> >      }
> >
> >
> >
> >      public String getInfo() {
> >
> >            return "RemoteIPValve";
> >
> >      }
> >
> > }
> >
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org
> For additional commands, e-mail: users-h...@tomcat.apache.org
>
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org
> For additional commands, e-mail: users-h...@tomcat.apache.org
>

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org
For additional commands, e-mail: users-h...@tomcat.apache.org

Reply via email to