Forum Discussion

shipszky_319427's avatar
shipszky_319427
Icon for Nimbostratus rankNimbostratus
Jan 29, 2018

Ip filter iRule with multiple data groups

I currently have an iRule in place to do ip filtering in multiple places in a website. I had an oversight when this was first written and failed to put a rule in for the entire website.

    when HTTP_REQUEST {
    if { [string tolower [HTTP::uri]] eq "/t/lccc/" } then {
        if { [class match [IP::client_addr] equals /Education/tableau_lccc] } then {
             Let the request pass...
        } else {
            HTTP::respond 403 content "Access Denied"
        }        
    } elseif { [string tolower [HTTP::uri]] eq "/t/wwcc/" } then {
        if { [class match [IP::client_addr] equals /Education/tableau_wwcc] } then {
             Let the request pass...
        } else {
            HTTP::respond 403 content "Access Denied"
        }        
    } elseif { [string tolower [HTTP::uri]] eq "/t/nwccd/" } then {
        if { [class match [IP::client_addr] equals /Education/tableau_nwccd] } then {
             Let the request pass...
        } else {
            HTTP::respond 403 content "Access Denied"
        }        
    } elseif { [string tolower [HTTP::uri]] eq "/t/nwc/" } then {
        if { [class match [IP::client_addr] equals /Education/tableau_nwc] } then {
             Let the request pass...
        } else {
            HTTP::respond 403 content "Access Denied"
        }        
    }  elseif { [string tolower [HTTP::uri]] eq "/t/ewc/" } then {
        if { [class match [IP::client_addr] equals /Education/tableau_ewc] } then {
             Let the request pass...
        } else {
            HTTP::respond 403 content "Access Denied"
        }        
    }  elseif { [string tolower [HTTP::uri]] eq "/t/cwc/" } then {
        if { [class match [IP::client_addr] equals /Education/tableau_cwc] } then {
             Let the request pass...
        } else {
            HTTP::respond 403 content "Access Denied"
        }        
    }   elseif { [string tolower [HTTP::uri]] eq "/t/cc/" } then {
        if { [class match [IP::client_addr] equals /Education/tableau_cc] } then {
             Let the request pass...
        } else {
            HTTP::respond 403 content "Access Denied"
        }        
    } else {
         Let the request pass...   
    }
}

From this point I would like to add something to filter the top level of the site, using each of the above data groups. Would this go after the final "else"? Also, is this the proper way to refer to multiple data groups?

 } elseif { { [string tolower [HTTP::uri]] eq "/" } then {
            if { [class match [IP::client_addr] equals /Education/tableau_cc, /Education/tableau_cwc,/Education/tableau_ewc, etc, etc, etc ] } then {
                 Let the request pass...
                 } else {
            HTTP::respond 403 content "Access Denied"  
        }
    }

Thanks

  • JG's avatar
    JG
    Icon for Cumulonimbus rankCumulonimbus

    Would the following do (untested)?

    } elseif { { [string tolower [HTTP::uri]] eq "/" } then {
        set dg_list {dgrp1 dgrp2 dgrp3}
        set allowed 0
    
        foreach dg $dg_list {
            if { [class match [IP::client_addr] equals dg] }{
                set allowed 1
                break
            }
        }
    
        if { $allowed < 1} {
            HTTP::respond 403 content "Access Denied"
        }
    }
    

    (Replace dgrp* with real data group names.) .

  • The code is too complicated.

     

    I recommend to create only 2 Datagroups

     

    • /Education/DG_URI containing URI as key and the list of allowed roups as value
    • /Education/tableau_global containing IP addresses as key and the group membership as value

    Then use following irule.

     

    when HTTP_REQUEST {
     Search if the URI have an IP address restriction, store the allowed groups in a variable
        if { [set AllowedGroups [class match -value [string tolower [HTTP::uri]] equals /Education/DG_URI]] ne "" } then {
             Search if the IP address is known in a the IP addresses Datagroup and filter based on previous search
            if { [set IPGroups [class match -value [IP::client_addr] equals /Education/tableau_global]] ne "" && ($AllowedGroups contains $IPGroups)} then {
                 Let the request pass...
            } else {
                HTTP::respond 403 content "Access Denied"
            }
        }
    }
  • Hi shipszky,

    If you want to stick to your existing iRule structure then take a look below to see how multiple data-groups can be queried in a serial manner for

    [HTTP::uri] eq /
    .

    Note: But I second Stanislas opinion, that an approach with just two data-groups (one to identify the IPs and a second one to identify the URI) makes way more sense (e.g. easier to maintain, better flexibility).

    when HTTP_REQUEST {
        set low_uri [string tolower [HTTP::uri]]
        if { $low_uri eq "/t/lccc/" } then {
            if { [class match [IP::client_addr] equals /Education/tableau_lccc] } then {
                 Let the request pass...
            } else {
                HTTP::respond 403 content "Access Denied"
            }        
        } elseif { $low_uri eq "/t/wwcc/" } then {
            if { [class match [IP::client_addr] equals /Education/tableau_wwcc] } then {
                 Let the request pass...
            } else {
                HTTP::respond 403 content "Access Denied"
            }        
        } elseif { $low_uri eq "/t/nwccd/" } then {
            if { [class match [IP::client_addr] equals /Education/tableau_nwccd] } then {
                 Let the request pass...
            } else {
                HTTP::respond 403 content "Access Denied"
            }        
        } elseif { $low_uri eq "/t/nwc/" } then {
            if { [class match [IP::client_addr] equals /Education/tableau_nwc] } then {
                 Let the request pass...
            } else {
                HTTP::respond 403 content "Access Denied"
            }        
        } elseif { $low_uri eq "/t/ewc/" } then {
            if { [class match [IP::client_addr] equals /Education/tableau_ewc] } then {
                 Let the request pass...
            } else {
                HTTP::respond 403 content "Access Denied"
            }        
        } elseif { $low_uri eq "/t/cwc/" } then {
            if { [class match [IP::client_addr] equals /Education/tableau_cwc] } then {
                 Let the request pass...
            } else {
                HTTP::respond 403 content "Access Denied"
            }        
        } elseif { $low_uri eq "/t/cc/" } then {
            if { [class match [IP::client_addr] equals /Education/tableau_cc] } then {
                 Let the request pass...
            } else {
                HTTP::respond 403 content "Access Denied"
            }
        } elseif { $low_uri eq "/" } then {
            if { ( [class match [IP::client_addr] equals /Education/tableau_lccc] ) 
              or ( [class match [IP::client_addr] equals /Education/tableau_wwcc] )
              or ( [class match [IP::client_addr] equals /Education/tableau_nwccd] )
              or ( [class match [IP::client_addr] equals /Education/tableau_nwc] )
              or ( [class match [IP::client_addr] equals /Education/tableau_ewc] )
              or ( [class match [IP::client_addr] equals /Education/tableau_cwc] )
              or ( [class match [IP::client_addr] equals /Education/tableau_cc] ) } then {
                 Let the request pass...
            } else {
                HTTP::respond 403 content "Access Denied"
            }
        } else {
             Let the request pass...   
        }
    }
    

    Note: I've changed your existing syntax slightly so that LTM computes the lower URI just a single time (aka.

    set low_uri [string tolower [HTTP::uri]]
    at the beginning) and then reuses the computed
    $low_uri
    result for the individual
    [if]
    statements.

    Cheers, Kai

  • Thank you for all these answers everyone. I'm going to go with Kai's as a quick fix, but implement Stanislas's answer once I can get the data groups merged.