Forum Discussion

mtobkes_64700's avatar
mtobkes_64700
Icon for Nimbostratus rankNimbostratus
Mar 11, 2010

Can iRule Reject Requests Based on 'True-Client-IP'

Can someone please tell me if the LTM v9.4.7 can take action on requests, based on the HTTP header value for 'True-Client-IP'?

 

 

We will be 'Akamaizing' parts of our website and will no longer see the clients address in the IP header.

 

 

Akamai will insert the client's IP in the HTTP header 'True-Client-IP'. We will now need the ability to block requests based on this layer 7 information.

 

 

Here is an iRule I found posted:

 

 

when HTTP_REQUEST {

 

if { [HTTP::header exists "True-Client-IP"] } {

 

set xff [HTTP::header "True-Client-IP"]

 

xff may be in format of addr1,addr2,addr3

 

set addrs [split $xff ","]

 

foreach addr $addrs {

 

if { [matchclass $::banned_addr_list equals $addr] } {

 

reject

 

}

 

}

 

}

 

}

 

 

 

Will this iRule accomplish what I am trying to do?

 

 

Thanks,

 

-MT

 

6 Replies

  • Hamish's avatar
    Hamish
    Icon for Cirrocumulus rankCirrocumulus
    Without checking your syntax, the logic looks OK (It'd have done it slightly differently, but that's just optimisation).

     

     

    However you'd want to make sure that Akamai aren't pipelining multiple client requests in a single connection (And I think they will be from memory). Otherwise you'll be adding to the overhead by rejecting a connection seemingly at random (To them).

     

     

    The best approach in this situation would be to give back an HTTP/404 result everytime rather than a reject. So the connection stays up for the next request.

     

     

    H.
  • You might also check to see if Akamai strips out any previously existing True-Client-IP headers before inserting it's own. You could test this to see. If they don't then you could check to see whether Akamai's header is always inserted last. In that case, you should be fine using hte iRule as HTTP::header retrieves the value for the last named header.

    I don't think Akamai would append the client IP they get to an existing True-Client-IP header, so you could probably skip the split/loop on the True-Client-IP header value. If you did want to keep the split/loop, you could eliminate some intermediate variables:

      
      when HTTP_REQUEST {  
         if { [HTTP::header "True-Client-IP"] ne ""} {  
        
             header may be in format of addr1,addr2,addr3  
            foreach addr [split [HTTP::header "True-Client-IP"] ","] {  
               if { [matchclass banned_addr_list equals $addr] } {  
                  HTTP::respond 403  
               }  
            }  
         }  
      }  
      

    Aaron
  • Thanks!

     

     

    I'd would like to remove the split/loop in my iRule and send a 301 if the 'True-Client-IP' matches my data list 'banned_addr_list'.

     

     

    Can you tell me if the syntax is correct and/or if I'm missing anything?

     

     

     

    when HTTP_REQUEST {

     

    if { [HTTP::header "True-Client-IP"] ne ""} {

     

    if { [matchclass $::banned_addr_list equals $addr] } {

     

    HTTP::respond 403

     

    }

     

    }

     

    }

     

     

     

     

    Thanks

     

    -MT
  • That looks good. For 9.4.4+ you can remove the $:: prefix from the datagroup to make the iRule CMP compatible (assuming you have a CMP compatible platform Click here).

     

     

    I'd be careful using a 301 response as intermediate proxies could cache the response and serve it to clients who would have otherwise been allowed through to the pool. A 302 shouldn't be cached and still allows you to redirect the client to a new location.

     

     

    Aaron
  • Sorry for the confusion. What I meant to say was that I'd like to send a 403 or 404 if the 'True-Client-IP' matches my data list 'banned_addr_list' (my iRule shows a 404 response). This was suggested by Hamish in his previous reply:

     

     

    Posted By Hamish on 03/11/2010 9:17 AM

     

     

    " The best approach in this situation would be to give back an HTTP/404 result everytime rather than a reject. So the connection stays up for the next request. "

     

     

    Would either of these responses work better? The goal is to stop the requests from hitting the servers, but not take down the connection.

     

     

    Thanks again,

     

    -MT

     

     

  • RFC2616 states that you should send a 403 for this case. But what you actually use is up to you. 404 could be appropriate. Just make sure to set cache control headers if you use a 404 to prevent proxies from caching the response.

     

     

    HTTP::respond 404 Cache-Control No-Cache Pragma No-Cache

     

     

     

    http://tools.ietf.org/html/rfc2616section-10.4.4

     

     

    10.4.4 403 Forbidden

     

     

     

    The server understood the request, but is refusing to fulfill it.

     

    Authorization will not help and the request SHOULD NOT be repeated.

     

    If the request method was not HEAD and the server wishes to make

     

    public why the request has not been fulfilled, it SHOULD describe the

     

    reason for the refusal in the entity. If the server does not wish to

     

    make this information available to the client, the status code 404

     

    (Not Found) can be used instead.

     

     

    10.4.5 404 Not Found

     

     

    The server has not found anything matching the Request-URI. No

     

    indication is given of whether the condition is temporary or

     

    permanent. The 410 (Gone) status code SHOULD be used if the server

     

    knows, through some internally configurable mechanism, that an old

     

    resource is permanently unavailable and has no forwarding address.

     

    This status code is commonly used when the server does not wish to

     

    reveal exactly why the request has been refused, or when no other

     

    response is applicable.

     

     

     

     

     

    Aaron