Forum Discussion

ant77's avatar
ant77
Icon for Cirrostratus rankCirrostratus
Jan 27, 2022
Solved

Monitor two pool maintenance page iRule using XFF not working...

Does anyone know why if either the  "INTERNAL" server pool goes down, the traffic for internal users still works? Is there a better way to group these monitors up? 

Please let me know what I am doing wrong...When I disable all nodes in the internal POOL, traffic to the internal pool works and they get sent there...It seems that only the monitor for the External Pool works...Can you have two monitors in the same iRULE? Does this iRule care about the secondary monitor for the internal pool?

Note: When I disable the EXTERNAL pool members, the external users gets sent to the correct maintenace page, while the internal users still works as it should...But we need to have the same thing happen when the INTERNAL pool goes down....

Objective:

1. Using XFF, if the "EXTERNAL" pool goes down, and the XFF IP of the client "Does Not" match the IP in the"DG-INTERNAL-USERS-XFF" data group, send the
users to "http://maintenace-page.com/external"

2.  Using XFF, if the "INTERNAL" pool goes down, and the XFF IP of the client "Matches" the IP in the"DG-INTERNAL-USERS-XFF" data group, send the users
to "http://maintenace-page.com/external"

 

when HTTP_REQUEST {
set CHECK_IP [lindex [lsearch -all -inline -not -exact [split [HTTP::header values X-Forwarded-For] "\{\} ,"] {}] 0] 
    if { !([class match -- $CHECK_IP eq DG-INTERNAL-USERS-XFF]) } {
       if { [class match -- [HTTP::uri] eq DG-ALLOWED-URI-LIST] } {
          reject
          log local0. "Client IP Discard: \ [HTTP::host][HTTP::uri]->[IP::client_addr]" 
           }              
   if { [active_members EXTERNAL-POOL] < 1 } {
    if { !([class match -- $CHECK_IP eq DG-INTERNAL-USERS-XFF]) } {
    HTTP::redirect "http://maintenance-page.com/external" 
    return
   
  
  if { [active_members INTERNAL-POOL] < 1 } {
   if { ([class match -- $CHECK_IP eq DG-INTERNAL-USERS-XFF]) } {
    HTTP::redirect "http://maintenance-page.com/internal" 
   return
   
    pool EXTERNAL-POOL
    
   } else {
   
     pool INTERNAL-POOL
log local0. "the X-Forwarded-For header value is $CHECK_IP"
        
     }
    }
   }
  }
 }
}

 

 

 

 

  • before working on this, it's very similar to your other one and I was curious if this is on the same virtual? If so, is the other logic in this rule as well or a different rule? 

  • I am not sure if the new site is formatting your iRule incorrectly or what but, it does not appear that the iRule will function as you want in the state I see it right now.

    There are several things wrong with the logic so I am re-posting it here with clearing formatting and commented with the logic as it is:

    when HTTP_REQUEST {
        set CHECK_IP [lindex [lsearch -all -inline -not -exact [split [HTTP::header values X-Forwarded-For] "\{\} ,"] {}] 0] 
        # Check if userds are NOT in internal user DG
        if { !([class match -- $CHECK_IP eq DG-INTERNAL-USERS-XFF]) } {
            # Check if uri is in allowed list
            if { [class match -- [HTTP::uri] eq DG-ALLOWED-URI-LIST] } {
                #blocks external users (i.e. IPs  Not in Interal Users DG)
                reject
                log local0. "Client IP Discard: \ [HTTP::host][HTTP::uri]->[IP::client_addr]" 
            }
            # Check if External Pool has zero active members
            if { [active_members EXTERNAL-POOL] < 1 } {
                #IF so, check if they are "external" users (i.e. NOt in Internal users DG 
                if { !([class match -- $CHECK_IP eq DG-INTERNAL-USERS-XFF]) } {
                    #redirect external users to maintenance-page
                    HTTP::redirect "http://maintenance-page.com/external" 
                    # returns form proccessing this event ####  No other code in this iRuel will run!!!!!!!
                    return
                    ######  Rest of this logic will never be processed!!!!   ####################
                    
                    # Check if internal Pool is down
                    if { [active_members INTERNAL-POOL] < 1 } {
                        # Check if IP IS in the Internal Uers group  
                        if { ([class match -- $CHECK_IP eq DG-INTERNAL-USERS-XFF]) } {
                            #  redirect internal users to the maiantinace page if the internal pool is down
                            HTTP::redirect "http://maintenance-page.com/internal"
                            # returns form proccessing this event ####  No other code in this iRuel will run!!!!!!!  But we would never get this far anyway.
                            return
                            ######  Rest of this logic will never be processed!!!!   ####################
                            
                            # Send traffic to external pool
                            pool EXTERNAL-POOL
                        # IF you are NOT in Internal Users DG
                        } else {
                            # Send to Internal Pool
                            pool INTERNAL-POOL
                            log local0. "the X-Forwarded-For header value is $CHECK_IP"
                        }
                    }
                }
            }
        }
    }


    It is diffiucult to tell from the current logic exactly what you were trying to accomplish But this is my best guess at what it SHOULD look like:

    when HTTP_REQUEST {
        set CHECK_IP [lindex [lsearch -all -inline -not -exact [split [HTTP::header values X-Forwarded-For] "\{\} ,"] {}] 0] 
        # Block external IPs form getting to ALLOWED-URI-LiST
        if { !([class match -- $CHECK_IP eq DG-INTERNAL-USERS-XFF]) } {
            if { [class match -- [HTTP::uri] eq DG-ALLOWED-URI-LIST] } {
                reject
                log local0. "Client IP Discard: \ [HTTP::host][HTTP::uri]->[IP::client_addr]" 
            }
        }
        # If External Pool is down, redirect enternal users, and send internal users to Internal Pool
        if { [active_members EXTERNAL-POOL] < 1 } {
            if { !([class match -- $CHECK_IP eq DG-INTERNAL-USERS-XFF]) } {
                HTTP::redirect "http://maintenance-page.com/external" 
                return
            } else {
                pool INTERNAL-POOL
                log local0. "the X-Forwarded-For header value is $CHECK_IP"
            }
        }
        # Check if Internal Pool is down, redirect External users to maintiencace page, and allow everyone else to External Pool
        if { [active_members INTERNAL-POOL] < 1 } {
            if { (![class match -- $CHECK_IP eq DG-INTERNAL-USERS-XFF]) } {
                HTTP::redirect "http://maintenance-page.com/internal"
                return
            } else {
                pool EXTERNAL-POOL
                log local0. "the X-Forwarded-For header value is $CHECK_IP"
            }
        }
    }



4 Replies

  • I am not sure if the new site is formatting your iRule incorrectly or what but, it does not appear that the iRule will function as you want in the state I see it right now.

    There are several things wrong with the logic so I am re-posting it here with clearing formatting and commented with the logic as it is:

    when HTTP_REQUEST {
        set CHECK_IP [lindex [lsearch -all -inline -not -exact [split [HTTP::header values X-Forwarded-For] "\{\} ,"] {}] 0] 
        # Check if userds are NOT in internal user DG
        if { !([class match -- $CHECK_IP eq DG-INTERNAL-USERS-XFF]) } {
            # Check if uri is in allowed list
            if { [class match -- [HTTP::uri] eq DG-ALLOWED-URI-LIST] } {
                #blocks external users (i.e. IPs  Not in Interal Users DG)
                reject
                log local0. "Client IP Discard: \ [HTTP::host][HTTP::uri]->[IP::client_addr]" 
            }
            # Check if External Pool has zero active members
            if { [active_members EXTERNAL-POOL] < 1 } {
                #IF so, check if they are "external" users (i.e. NOt in Internal users DG 
                if { !([class match -- $CHECK_IP eq DG-INTERNAL-USERS-XFF]) } {
                    #redirect external users to maintenance-page
                    HTTP::redirect "http://maintenance-page.com/external" 
                    # returns form proccessing this event ####  No other code in this iRuel will run!!!!!!!
                    return
                    ######  Rest of this logic will never be processed!!!!   ####################
                    
                    # Check if internal Pool is down
                    if { [active_members INTERNAL-POOL] < 1 } {
                        # Check if IP IS in the Internal Uers group  
                        if { ([class match -- $CHECK_IP eq DG-INTERNAL-USERS-XFF]) } {
                            #  redirect internal users to the maiantinace page if the internal pool is down
                            HTTP::redirect "http://maintenance-page.com/internal"
                            # returns form proccessing this event ####  No other code in this iRuel will run!!!!!!!  But we would never get this far anyway.
                            return
                            ######  Rest of this logic will never be processed!!!!   ####################
                            
                            # Send traffic to external pool
                            pool EXTERNAL-POOL
                        # IF you are NOT in Internal Users DG
                        } else {
                            # Send to Internal Pool
                            pool INTERNAL-POOL
                            log local0. "the X-Forwarded-For header value is $CHECK_IP"
                        }
                    }
                }
            }
        }
    }


    It is diffiucult to tell from the current logic exactly what you were trying to accomplish But this is my best guess at what it SHOULD look like:

    when HTTP_REQUEST {
        set CHECK_IP [lindex [lsearch -all -inline -not -exact [split [HTTP::header values X-Forwarded-For] "\{\} ,"] {}] 0] 
        # Block external IPs form getting to ALLOWED-URI-LiST
        if { !([class match -- $CHECK_IP eq DG-INTERNAL-USERS-XFF]) } {
            if { [class match -- [HTTP::uri] eq DG-ALLOWED-URI-LIST] } {
                reject
                log local0. "Client IP Discard: \ [HTTP::host][HTTP::uri]->[IP::client_addr]" 
            }
        }
        # If External Pool is down, redirect enternal users, and send internal users to Internal Pool
        if { [active_members EXTERNAL-POOL] < 1 } {
            if { !([class match -- $CHECK_IP eq DG-INTERNAL-USERS-XFF]) } {
                HTTP::redirect "http://maintenance-page.com/external" 
                return
            } else {
                pool INTERNAL-POOL
                log local0. "the X-Forwarded-For header value is $CHECK_IP"
            }
        }
        # Check if Internal Pool is down, redirect External users to maintiencace page, and allow everyone else to External Pool
        if { [active_members INTERNAL-POOL] < 1 } {
            if { (![class match -- $CHECK_IP eq DG-INTERNAL-USERS-XFF]) } {
                HTTP::redirect "http://maintenance-page.com/internal"
                return
            } else {
                pool EXTERNAL-POOL
                log local0. "the X-Forwarded-For header value is $CHECK_IP"
            }
        }
    }



    • ant77's avatar
      ant77
      Icon for Cirrostratus rankCirrostratus

      Joe/Jason -

      thanks for your guidence. I have modified the irule a bit and got it working.

      Thanks again guys!

       

  • before working on this, it's very similar to your other one and I was curious if this is on the same virtual? If so, is the other logic in this rule as well or a different rule? 

  • ant77's avatar
    ant77
    Icon for Cirrostratus rankCirrostratus

    Hi Jason,

    Yes, this is similar to the previous iRule, but for a different Virtual. We need to do this for the other one also...It seems that you can't have two monitor in one iRule, one monitoring an external pool, and the other monitoring the internal Pool...We need to use XFF to distinguish what traffic is what....I have tried re-ording the monitors, and when you disable the members for the "internal" pool, traffic still gets sent there...Is this a bug or something? This has nothing to do with the irule, but more of a pool configuration/disabling member...why does the website still comes up...and when you add the secondary monitor in the script in, external users will be routed to the internal pool instead of the external pool....Right now, i only have the script to include the external monitor...we can't have two for some reason..not sure if this is a bug or not...

    Thanks!