Forum Discussion

Adi82_183873's avatar
Adi82_183873
Icon for Nimbostratus rankNimbostratus
Jan 23, 2015

iRule and data group not matching properly

Hi all,

We have the following devices: 2 BIG-IPs version is version 11.4.1. HA enabled.

Network topology is : Akamai --- BIG-IP --- WAF --- Servers HTTP

The issue is :

1) We have several iRules for maintenance purpose.Used when we are making changes on the http servers. The Rule has an if/else statement.

During a maintenance window site customers requests will be redirected to a maintenance page and only a few selected IPs(engineers) will be sent to the normal page.
Sample iRule:

when HTTP_REQUEST {
HTTP::header insert X-Forwarded-For [HTTP::header "True-Client-IP"]

if { [class match [HTTP::header "True-Client-IP"] equals "DATAGROUP"] } {

}
else {
    HTTP::redirect "http://maintenance.com/maint.html"
}

}

            DATAGROUP definition 

            ltm data-group internal DATAGROUP {
records {
    IP1 { }
    IP2 { }
    IP3 { }
}
type string

2) The above rule works ( general customers are redirected to the maintenance page and engineers are going to the normal one ) but when parsing http server logs weve found out that

general customers IPs accessed the normal page during maintenance window.

We didnt found any errors in the /var/log/ltm or tmsh show sys log ltm

What could be the cause of the general customer passing through towards the normal page and not matching the iRule ? Is it a known bug, new bug ? A iRule syntax , parsing problem ?

Thanks for helping.

10 Replies

  • We do something very similar but use a data group of ADDRESS rather than STRING e.g.

    ltm data-group internal CLASS_WHITELIST {
    app-service none
    description none
    partition TEST
    records {
        192.168.1.1/32 {
            data none
        }
    }
    type ip
    }
    
  • Arie's avatar
    Arie
    Icon for Altostratus rankAltostratus

    @LyonsG is right - you want to use "type ip" and preferably netmasks.

    A couple of questions:

    1. Where does the value for "True-Client-IP" come from?
    2. Is there a specific reason you're inserting XFF via an iRule instead of in the HTTP-Profile?
    3. Is there a specific reason you're using a header value to get to the client IP address (vs. using
      IP::client_addr
      )?
    4. Wouldn't it be better to return a 503 (Service Unavailable) instead of a 302 (Temporary Redirect) followed by (presumably) a 200 (OK)?
    5. How are you activating the maintenance rule? (if you're changing the iRule that may not affect existing connections).
  • Thanks for the reply.

     

    Answers.

     

    1. True-Client-IP comes from Akamai . Requests via Akamai have the same source IP so the Akamai sets L7 header as True-Client-IP

       

    2. We need to send engineers IPs to the normal page and general users /site customers to the maintenance page. Can the HTTP-Profile do this?

       

    3.The reason is numer 1 answer. All requests coming from Akamai have the same source IP . So were using L7 header info to match cliens IP.

     

    1. Can you please tell us how to set a 503 return?

       

    2. From CLI i used one command This will remove the existing rule and replacing with the maintenance one.

       

    tmsh modify ltm virtual NAME rules { maintenance_rule }

     

    From tmsh show sys connection the TCP session remains until timer expires 300s.

     

    But we have seen new connections being establis hed from apache logs after inserting the maintenance rule.

     

    Thank you.

     

  • Hi Adi82,

    here is a sample iRule to return a 503:
    when RULE_INIT {
         Logging/classification (on=1|off=0)
        set static::http_debug              1
        set static::error_code_version      "503"
        set static::error_page_version      "Error 505HTTP - Service Unavailable"
        set static::error_server            "Webserver"
    }
    
    when HTTP_REQUEST {
        if {  } {
            if { $static::http_debug > 0 } {
                log local0. "Returned 503 (Service Unavailable) - <[IP::client_addr]:[TCP::client_port]>"
            }
            HTTP::respond $static::error_code_version content $static::error_page_version noserver Server $static::error_server Connection close
            return
        }
    }
    

    Just put in the condition you want, please.

    Regarding the question about new log messages on the Apache:

    It is very likely due to using keep-alive connection and maybe OneConnect.

    A changed iRule will affect new connections only. Existing connections (HTTP keep-alive) will still be handled according to the iRule applied while the TCP connection end-to-end was established.

    It would be an alternative to put all logic into a single iRule and to modify a global variable to switch between policies.

    Thanks, Stephan
  • Hi Stephan

     

    Thank you for the very useful reply.

     

    Were nit using Oneconnect. We saw new tcp connections being established on the server.Besides of the keep-alive ones.

     

    Can you please teach us how to use the rule with the global variable? The global variable will not affect CMP feature?

     

    Thank you very much.

     

  • Hi Adi,

     

    each TMM instance (Traffic Management Microkernel) of the CMP cluster will hold an individual copy of a global variable.

     

    If you change it on a single TMM only (i.e. to count events in an iRules) the other TMMs will not be updated. This saves lots of processing cycles and record locking. So this approach has performance advantages but is limited regarding using it as a global counter.

     

    Applying a change to the iRule configuration will update (initialize) the global variable setting on all TMMs and is a common approach i.e. to enable/disable logging globally.

     

    I saw other customers using datagroup entries (referenced in iRules) to trigger different decision algorithms.

     

    Thanks, Stephan

     

  • Hi Stephan,

     

    Thank you again for the professional reply.

     

    You're posts helped us to Lear more about rules.

     

    Can you please write an example of an an iRule holding all the logic with a global variable to switch between policies ?

     

    Thank you for you support.

     

  • Hi Adi82,

    I used a new datagroup of type IP to summarize the IP whitelist clients.

     tmsh list ltm data-group
    ltm data-group internal datagroup_whitelist_ip {
        records {
            10.131.141.0/24 { }
        }
        type ip
    }
    

    It will be necessary to create this datagroup first before importing the following iRule:

    when RULE_INIT {
    
         application operation mode (on=1|off=0)
        set static::app_operation   1
    
         Logging/classification (on=1|off=0)
        set static::app_http_debug  1
    
        set static::app_maint_code  "503"
        set static::app_maint_page  "Error 503Web Service Temporarily Unavailable"
        set static::app_redir_code  "302"
        set static::app_maint_locn  "http://10.131.131.100/maint.html"
    
        set static::app_servr_strn  "Webserver"
    }
    
    when HTTP_REQUEST {
    
         evaluate client IP depending on existing header (inserted by CDN) or IP header
        if {[HTTP::header exists True-Client-IP]} {
            set var_true_client_ip [HTTP::header True-Client-IP]
        } else {
            set var_true_client_ip [IP::client_addr]
        }
    
         serve maintenance page (to serve maintenance page by virtual server)
        if { [string tolower [HTTP::path]] starts_with "/maint.html" } {
            if { $static::app_http_debug > 0 } {
                log local0. "Operational mode <$static::app_operation>, returned 503 (service unavailable) - <[IP::client_addr]:[TCP::client_port]>"
            }
            HTTP::respond $static::app_maint_code content $static::app_maint_page noserver Server $static::app_servr_strn Connection close
            return
        }
    
         switch depending on maintenance mode
        if { $static::app_http_debug > 0 } {
                log local0. "Operational mode <$static::app_operation>, request from IP <$var_true_client_ip> received <[HTTP::method] [HTTP::uri] [HTTP::version]>"
        }
        switch $static::app_operation {
        0   {
                 policies to run service in maintenance mode
                if { ! ([class match $var_true_client_ip equals datagroup_whitelist_ip]) } {
                    if { $static::app_http_debug > 0 } {
                        log local0. "Maintenance mode <$static::app_operation>, redirecting client to maintenance page"
                    }
                    HTTP::respond $static::app_redir_code noserver Server $static::app_servr_strn Location $static::app_maint_locn Connection Close
                    return
                } else {
                    if { $static::app_http_debug > 0 } {
                        log local0. "Maintenance mode <$static::app_operation>, whitelist client request forwarded"
                    }
                }
            }
        1   {
                 policies to run service in operational mode
                HTTP::header insert X-Forwarded-For $var_true_client_ip
            }
        }
    }
    

    Please modify the value of the global static variable static::app_operation according to the current state of your application (operational=1|maintenance=0) to switch between modes.

    Logging can be turned on|off same way.

    Thanks, Stephan

  • Hi Stephan,

     

    WOW. Thank you very much. You're an iRule guru.

     

    I'm trying to figure out what every line does. I'm a networking guy , programming it's not my stength.

     

    Very good answers and support. I will test it and let you know the result.

     

    Thank you.

     

    • StephanManthey's avatar
      StephanManthey
      Icon for MVP rankMVP
      Hi Adi82, thanks. Please let us know if you have any questions. In the iRule I globally enabled logging. You can monitor the log facility by using the following command: tail -f /var/log/ltm Thanks, Stephan