Learn F5 Technologies, Get Answers & Share Community Solutions Join DevCentral

Filter by:
  • Solution
  • Technology
Answers

irule to Block specific URLs, allow the rest

I need to block traffic from two explicit URLs, but allow all other traffic even if it starts with the same characters as what is blocked. This is my best guess at syntax. Please correct any errors you see.

when HTTP_REQUEST { if { ( [string tolower "[HTTP::host][HTTP::path]"] equals "example.domain.com/xyz/ab/" ) or if { ( [string tolower "[HTTP::host][HTTP::path]"] equals "example.domain.com/xyz/ab" ) reject } } }

Any other iteration that starts the same but has additional characters like "example.domain.com/xyz/ab/abc123/..." should be allowed. Is the equals parameter sufficient?

0
Rate this Question

Answers to this Question

placeholder+image
USER ACCEPTED ANSWER & F5 ACCEPTED ANSWER

If you remove some brackets and one of the "if"s it works. You can always test it by logging the output to /var/log/ltm, see below.

when HTTP_REQUEST {
    if {[string tolower "[HTTP::host][HTTP::path]"] equals "example.domain.com/xyz/ab/"
    or [string tolower "[HTTP::host][HTTP::path]"] equals "example.domain.com/xyz/ab"} {
        log local0. "Rejected Connection [HTTP::host][HTTP::path], converted [string tolower [HTTP::host][HTTP::path]]"
        reject
    }
}
0
Comments on this Answer
Comment made 3 months ago by Chris Olson 359

Thank you so much. I will test. Sadly, we are in a managed environment and I have little access to my own F5's to test and I must rely on your expertise. Thanks again. I will report back on results.

0
Comment made 3 months ago by Chris Olson 359

The rule took, but it's not working. I used both URLs specified but it is not being rejected. I can still hit the site. The logs do not show anything is happening. The only thing I can think of is that it is applied to the HTTPS VIP. However, when I try to change the rule to HTTPS I get an error.

[undefined procedure: HTTPS::host][HTTPS::host] /Common/url_reject_https:2: error: [undefined procedure: HTTPS::path][HTTPS::path]

Any ideas?

0
Comment made 3 months ago by gscholz 118

Even if HTTPS is used the contents of the Rule don't change. It is still an HTTP request and not an HTTPS request. If you want to find out whether the iRule gets hit at all, you could add another logging line, like below. In that case you should see one entry for every HTTP request, and a second one for every rejected request.

when HTTP_REQUEST {
    log local0. "Requested connection [HTTP::host][HTTP::path], converted [string tolower [HTTP::host][HTTP::path]]"
    if {[string tolower "[HTTP::host][HTTP::path]"] equals "example.domain.com/xyz/ab/"
    or [string tolower "[HTTP::host][HTTP::path]"] equals "example.domain.com/xyz/ab"} {
        log local0. "Rejected Connection [HTTP::host][HTTP::path], converted [string tolower [HTTP::host][HTTP::path]]"
        reject
    }
}

If you are unsure which virtual server gets hit you should be able to see that in a packet capture using tcpdump. Do you have shell access? (In theory packet capture is possible via the GUI as well, but I found it rather painful.)

0
Comment made 2 months ago by Chris Olson 359

I am digging into this again. The only other anomaly is that the pool members listen on 8080 (webcache). I would not think that to be an issue since the F5 handles SSL and any initial connection so it should be rejected BEFORE it hit's the server. Any assistance in syntax for a packet capture would be appreciated. I can do the basics, like capturing based on source, destination or port, but not sure how to create a capture based on a URL.

0
Comment made 2 months ago by gscholz 118

Just to make it easier for me to understand your setup so far: You have got one virtual server listening on port 443 with clientside SSL, and you have applied the iRule to this virtual server, right? Do you not see any log entries at all? It should get triggered for all incoming HTTP requests on that virtual server, so if there are no log entries at all I would guess the virtual server does not get hit by your tests.

0
placeholder+image
USER ACCEPTED ANSWER & F5 ACCEPTED ANSWER

Hi,

the code provided by gscholz may work.

You can also try this code which check both host and path in 2 conditions instead of concatenate, then use string match with no case instead of equals for performance optimization according to this article, and finally respond with a 403 error page instead of reject.

when HTTP_REQUEST {
    log local0. "Requested connection [HTTP::host][HTTP::path], converted [string tolower [HTTP::host][HTTP::path]]"
    if {[string match -nocase "example.domain.com" [HTTP::host]] && [string match -nocase "/xyz/ab" [string trimright [HTTP::path]]]} {
        log local0. "Rejected Connection [HTTP::host][HTTP::path], converted [string tolower [HTTP::host][HTTP::path]]"
        HTTP::respond 403 content{request Forbidden}
    }
}
0
Comments on this Answer
Comment made 2 months ago by Chris Olson 359

RULE:

when HTTP_REQUEST { log local0. "Requested connection [HTTP::host][HTTP::path], converted [string tolower [HTTP::host][HTTP::path]]" if {[string tolower "[HTTP::host][HTTP::path]"] equals "example.domain.com/xyz/ab/" or [string tolower "[HTTP::host][HTTP::path]"] equals "example.domain.com/xyz/ab"} { log local0. "Rejected Connection [HTTP::host][HTTP::path], converted [string tolower [HTTP::host][HTTP::path]]" reject } } }

LOG:

The below is expected. The string is being converted to lower case per the rule.

1/10/19 7:43:31.000 AM Jan 10 07:43:31 10.28.128.210 Jan 10 07:43:31 S608109CH3LB01 info tmm1[11583]: Rule /Common/url_reject_logall : Requested connection example.domain.com/xyz/ab, converted example.domain.com/xyz/ab

The next log shows another conversion but I don't know where it is coming from:

1/10/19 7:43:31.000 AM Jan 10 07:43:31 10.28.128.210 Jan 10 07:43:31 S608109CH3LB01 info tmm1[11583]: Rule /Common/url_reject_logall : Requested connection example.domain.com/XYZ/portal/1806061437/InfoView/logon.faces, converted example.domain.com/xyz/portal/1806061437/infoview/logon.faces

I assume there something in the server code that redirects to:

example.domain.com/XYZ/portal/....

Why isn't the F5 rejecting it in the first request?

0
Comment made 2 months ago by Stanislas Piron 10481

Did you clear cache before trying it?

You may have prefetch content that is cached on browser! If true, the browser may have cached it must download this file before it find reference in html file! This behavior happens in some application deployment!

For a better user experience, try with the http 403 response.

0
Comment made 2 months ago by Chris Olson 359

I will try the new one. However, I am confused on how/when the F5 reads the string. My assumption is that when I type in the URL, the F5 reads it BEFORE it reaches the server. Thus, it should not matter what the application says, F5 should reject it prior to making the connection to a pool member. I am obviously wrong since I suspect your comment regarding caching is true. I cleared cache and even used a different browser but was still never rejected. Can you tell me the methodology involved or point me to some documentation? Also, does your 403 response rule somehow remediate this? Thank you very much for your continued help and support!

0
Comment made 2 months ago by Chris Olson 359

I think we are close. I used the latest one and now get a blank page when using example.domain.com/xyz/ab However, I still get in when using the forward slash : example.domain.com/xyz/ab/

I need to have denies on both. Not sure of correct syntax with your new rule. I assume I need to add an "OR" somewhere in there. Would the below work? (Sadly, I don't have the ability to test without entering a change which can take up to 8 hours for every iteration)

when HTTP_REQUEST { log local0. "Requested connection [HTTP::host][HTTP::path], converted [string tolower [HTTP::host][HTTP::path]]" if {[string match -nocase "example.domain.com" [HTTP::host]] && [string match -nocase "/xyz/ab" or [string match -nocase "example.domain.com" [HTTP::host]] && [string match -nocase "/xyz/ab/" [string trimright [HTTP::path]]]} { log local0. "Rejected Connection [HTTP::host][HTTP::path], converted [string tolower [HTTP::host][HTTP::path]]" HTTP::respond 403 content{request Forbidden} } }

Thank you, Chris

0
Comment made 2 months ago by Chris Olson 359

Both rules applied properly but they are failing; I can still hit our site. It is very likely due to the prefetch comment made above. I am still unclear as to how the rule works. As mentioned above, I assume that the irule is hit at the VIP level and is rejected or denied PRIOR to hitting any server. Obviously, I am wrong. How does this traffic flow?

0
Comment made 2 months ago by Stanislas Piron 10481

Hi,

I forgot / in the trimright command... to remove last / if ending with /

when HTTP_REQUEST {
    log local0. "Requested connection [HTTP::host][HTTP::path], converted [string tolower [HTTP::host][HTTP::path]]"
    if {[string match -nocase "example.domain.com" [HTTP::host]] && [string match -nocase "/xyz/ab" [string trimright [HTTP::path] "/"]]} {
        log local0. "Rejected Connection [HTTP::host][HTTP::path], converted [string tolower [HTTP::host][HTTP::path]]"
        HTTP::respond 403 content{request Forbidden}
    }
}

I did following test with tcsh (I don't test all codes in irules but in this shell)

set host example.domain.com
# define all path I want to check: 
set path_list [list /XYZ/portal/1806061437/InfoView/logon.faces /XYZ/ab /XYZ/ab/ /XYZ/ab/foo/bar]

foreach path $uri_list {
    if {[string match -nocase "example.domain.com" $host] && [string match -nocase "/xyz/ab" [string trimright $path /]]} {
        puts "Rejected Connection $host$path, converted [string tolower $host$path]"
    } else {
        puts "Allowed Connection $host$path, converted [string tolower $host$path]"
    }
}

The result is the following

Allowed Connection example.domain.com/XYZ/portal/1806061437/InfoView/logon.faces, converted example.domain.com/xyz/portal/1806061437/infoview/logon.faces
Rejected Connection example.domain.com/XYZ/ab, converted example.domain.com/xyz/ab
Rejected Connection example.domain.com/XYZ/ab/, converted example.domain.com/xyz/ab/
Allowed Connection example.domain.com/XYZ/ab/foo/bar, converted example.domain.com/xyz/ab/foo/bar
0