Forum Discussion
VictorC
Jun 21, 2011Nimbostratus
HTTP VS: Only allow specific client IP but open specific /uri for all.
Hi,
Currently I have an iRule on a HTTP VS that discards requests if the client IP is not in the allow class. Now I have to add an extra requirement to allow 'all' if a specific /uri is given. Here's my current iRule (thanks to previous posts found in the forum).
class myallowedclients {
host 111.22.33.1
host 111.22.33.2
}
rule restrict-rule {
when CLIENT_ACCEPTED {
if { [matchclass [IP::client_addr] equals $::myallowedclients] }{
Do nothing...irule will complete and request will be sent to the pool based on virtual server definition
} else {
discard }
}
}
I may have to use this requirement for multiple HTTP VS with the same client allow list, but different pools so it'd be great if I can use one rule for all.
Thanks in advance.
Victor
- hooleylistCirrostratusSo you're testing by sending a 403 for blocked responses, you clear your cache, make a request to the / URI, see the logging for a blocked message but see the content for the root document displayed in the browser? That's really odd. I don't see how a request could be made to / and log the 403 response but still allow the request through to the pool.
when CLIENT_ACCEPTED { if { [matchclass [IP::client_addr] equals $::myallowedclients] }{ set allowed 1 log local0. "[IP::client_addr]:[TCP::client_port]: Client is in allowed class" } else { Client is not in the allowed class set allowed 0 log local0. "[IP::client_addr]:[TCP::client_port]: Client is not in allowed class" } } when HTTP_REQUEST { Save the URI for logging in HTTP_RESPONSE set uri [HTTP::uri] Check if requested URI is whitelisted switch -glob [HTTP::uri] { "/allowed_starts_with/*" - "*/allowed_contains/*" - "/allowed_exact" { set allowed 1 log local0. "[IP::client_addr]:[TCP::client_port]: URI is allowed per whitelist [HTTP::uri]" } } if { $allowed == 0 }{ Disallowed request Reset connection reject Send HTTP reject message HTTP::respond 403 content {blocked!} log local0. "[IP::client_addr]:[TCP::client_port]: Blocking request to [HTTP::uri]" } } when SERVER_CONNECTED { log local0. "[IP::client_addr]:[TCP::client_port]: connected: [IP::server_addr]:[TCP::server_port]" } when HTTP_RESPONSE { log local0. "[IP::client_addr]:[TCP::client_port]: \$uri=$uri, status=[HTTP::status]" }
- VictorCNimbostratusHome page blocked
- Colin_Walker_12Historic F5 AccountYou're not setting $allowed back to 0 anywhere outside of the CLIENT_ACCEPTED event. If someone goes to an authorized URI and gets it set to allowed, everything else will be allowed from then on. You'll need to add a bit to your code by setting a default case in your switch statement that sets allowed to 0 unless the IP is allowed.
- hooleylistCirrostratusI didn't think you'd need it in this scenario, but can you add a OneConnect profile to the virtual server and retest? If you're using SNAT on the serverside connections, you can use the default OneConnect profile with a 0.0.0.0 mask. Else with no SNAT create a custom OneConnect profile with a 255.255.255.255 source mask.
- Colin_Walker_12Historic F5 AccountOr frankly use a different variable name. uri_allowed vs ip_allowed. Make ip_allowed override uri_allowed, but if ip_allowed != 1 or doesn't exist, etc. then uri_allowed must == 1.
- hooleylistCirrostratusDoh... thanks for catching that Colin. I was going a bit nuts.
when CLIENT_ACCEPTED { if { [matchclass [IP::client_addr] equals $::myallowedclients] }{ set allowed_ip 1 log local0. "[IP::client_addr]:[TCP::client_port]: Client is in allowed class" } else { Client is not in the allowed class set allowed_ip 0 log local0. "[IP::client_addr]:[TCP::client_port]: Client is not in allowed class" } } when HTTP_REQUEST { Skip the URI checking if the client IP is allowed if {$allowed_ip}{ Exit this event in this rule return } Check if requested URI is whitelisted switch -glob [HTTP::uri] { "/allowed_starts_with/*" - "*/allowed_contains/*" - "/allowed_exact" { log local0. "[IP::client_addr]:[TCP::client_port]: URI is allowed per whitelist [HTTP::uri]" } default { Send HTTP reject message HTTP::respond 403 content {blocked!} log local0. "[IP::client_addr]:[TCP::client_port]: Blocking request to [HTTP::uri]" } } }
- Colin_Walker_12Historic F5 AccountLooks good to me. Though due to personal preference I'd use
if{!($allowed_ip)}
- Colin_Walker_12Historic F5 AccountOh, and you'll want to remove the
set allowed_ip 0
- hooleylistCirrostratusActually, it still doesn't make sense that the iRule would log that it was blocking but allow the request through. I can see how $allowed would be 1 after making a request to an allowed URI and then a blocked one, but it shouldn't have logged the 'blocking request' message. Odd.
- Colin_Walker_12Historic F5 AccountFair point, the
Recent Discussions
Related Content
Â
DevCentral Quicklinks
* Getting Started on DevCentral
* Community Guidelines
* Community Terms of Use / EULA
* Community Ranking Explained
* Community Resources
* Contact the DevCentral Team
* Update MFA on account.f5.com
Discover DevCentral Connects