Forum Discussion
Bypass SSL redirect if URI is....
I have 2 set of iRules that I'd like to combine into 1, however I'm unable to apply the logic without the result ending up in a loop.
The end result needs to be - if the URI is "/articles/2015/09/09/something.aspx" then allow the rest over port 80, else redirect to HTTPS. Always strip the www from the hostname as well.
I've only been able to get this to work on the iRule that I've applied on the port 443 VIP. I removed similar logic to check if the hostname begins with www, as it resulted in a loop. I'd like to be able to have 1 iRule that I could apply to both VIP-80 and VIP-443, however having 2 separate iRules is not a dealbreaker.
iRule applied to VIP-80:
when HTTP_REQUEST {
if { [string tolower [HTTP::uri]] starts_with "/articles/2015/09/09/something.aspx" } {
allow the request
return
} else {
HTTP::redirect https://[getfield [HTTP::host] ":" 1][HTTP::uri]
}
}
iRule applied to VIP-443:
when HTTP_REQUEST {
if { [string tolower [HTTP::uri]] starts_with "/articles/2015/09/09/something.aspx" } {
HTTP::redirect http://[getfield [HTTP::host] ":" 1][HTTP::uri]
} else {
allow the request
return
}
}
25 Replies
- Robert_Teller_7Historic F5 Account
Give the following a try
when HTTP_REQUEST { if { [TCP::remote_port] eq 80 && !([string tolower [HTTP::uri]] starts_with "/articles/2015/09/09/something.aspx") } { HTTP::redirect https://[getfield [HTTP::host] ":" 1][HTTP::uri] } elseif { [TCP::local_port] eq 443 && [string tolower [HTTP::uri]] starts_with "/articles/2015/09/09/something.aspx" } { HTTP::redirect http://[getfield [HTTP::host] ":" 1][HTTP::uri] } else { return } }- Joe_Pipitone
Nimbostratus
This works partially - it doesn't force SSL if the user goes to another article - it should only bypass redirecting to SSL if it IS /articles/2015/09/09/something.aspx. Everything else should be forced to https.
- Kevin_Stewart
Employee
The code looks fine, but seems very specific to a given URI. How does the loop manifest? Do you have a client side capture that shows the looping URLs?
On another note, by nature of doing SSL in the first place, I have to assume you have something you want to protect. It is also very likely that allowing HTTP and HTTPS access to the same site creates information leakage - session cookies and other information in the HTTPS content can bleed over into the HTTP content. I can completely understand the desire to not require encryption for some otherwise trivial content, but for the sake of the content (and users) you're trying to protect it may be worthwhile to consider an "all or nothing" approach to SSL.
- Joe_Pipitone
Nimbostratus
Any idea why this results in a redirect loop?
If someone visits an article other than /articles/2015/09/09/something.aspx, it stays on http. When I added the https redirect to the else statement, this resulted in a loop.
when HTTP_REQUEST { if { [TCP::remote_port] eq 80 && !([string tolower [HTTP::uri]] eq "/articles/2015/09/09/something.aspx") } { HTTP::redirect https://[getfield [HTTP::host] ":" 1][HTTP::uri] } elseif { [TCP::local_port] eq 443 && [string tolower [HTTP::uri]] eq "/articles/2015/09/09/something.aspx" } { HTTP::redirect http://[getfield [HTTP::host] ":" 1][HTTP::uri] } else { HTTP::redirect https://[HTTP::host][HTTP::uri] } } - Brad_Parker_139
Nacreous
Looks like you used "TCP::remote_port" in your first if. That is what caused your loop since its not being matched. Try this:
when HTTP_REQUEST { if { [TCP::local_port] eq 80 && !([string tolower [HTTP::uri]] eq "/articles/2015/09/09/something.aspx") } { HTTP::redirect https://[getfield [HTTP::host] ":" 1][HTTP::uri] } elseif { [TCP::local_port] eq 443 && [string tolower [HTTP::uri]] eq "/articles/2015/09/09/something.aspx" } { HTTP::redirect http://[getfield [HTTP::host] ":" 1][HTTP::uri] } else { HTTP::redirect https://[HTTP::host][HTTP::uri] } }- Brad_Parker_139
Nacreous
Also, your last else statement is not necessary and causes a loop. when HTTP_REQUEST { if { [TCP::local_port] eq 80 && !([string tolower [HTTP::uri]] eq "/articles/2015/09/09/something.aspx") } { HTTP::redirect https://[getfield [HTTP::host] ":" 1][HTTP::uri] } elseif { [TCP::local_port] eq 443 && [string tolower [HTTP::uri]] eq "/articles/2015/09/09/something.aspx" } { HTTP::redirect http://[getfield [HTTP::host] ":" 1][HTTP::uri] } } - Joe_Pipitone
Nimbostratus
Thanks - but it still results in a redirect loop. - Brad_Parker_139
Nacreous
with the else removed it loops?
- Brad_Parker
Cirrus
Looks like you used "TCP::remote_port" in your first if. That is what caused your loop since its not being matched. Try this:
when HTTP_REQUEST { if { [TCP::local_port] eq 80 && !([string tolower [HTTP::uri]] eq "/articles/2015/09/09/something.aspx") } { HTTP::redirect https://[getfield [HTTP::host] ":" 1][HTTP::uri] } elseif { [TCP::local_port] eq 443 && [string tolower [HTTP::uri]] eq "/articles/2015/09/09/something.aspx" } { HTTP::redirect http://[getfield [HTTP::host] ":" 1][HTTP::uri] } else { HTTP::redirect https://[HTTP::host][HTTP::uri] } }- Brad_Parker
Cirrus
Also, your last else statement is not necessary and causes a loop. when HTTP_REQUEST { if { [TCP::local_port] eq 80 && !([string tolower [HTTP::uri]] eq "/articles/2015/09/09/something.aspx") } { HTTP::redirect https://[getfield [HTTP::host] ":" 1][HTTP::uri] } elseif { [TCP::local_port] eq 443 && [string tolower [HTTP::uri]] eq "/articles/2015/09/09/something.aspx" } { HTTP::redirect http://[getfield [HTTP::host] ":" 1][HTTP::uri] } } - Joe_Pipitone
Nimbostratus
Thanks - but it still results in a redirect loop. - Brad_Parker
Cirrus
with the else removed it loops?
- Stanislas_Piro2
Cumulonimbus
Hi,
this irule does the job but evaluate twice port and URL.
try this irule which evaluate clientssl profile on the VS instead of port and compare the URI once.
when HTTP_REQUEST { set is_ssl [PROFILE::exists clientssl] set is_ssl_URL [string compare -nocase [HTTP::uri] "/articles/2015/09/09/something.aspx"] if { $is_ssl && $is_ssl_URL} { HTTP::redirect http://[getfield [HTTP::host] ":" 1][HTTP::uri] } elseif { !($is_ssl) && !($is_ssl_URL)} { HTTP::redirect https://[getfield [HTTP::host] ":" 1][HTTP::uri] } } - Joe_Pipitone
Nimbostratus
Why can't we do this with a switch statement? I've tried this code, however I get a redirect loop as well.
when HTTP_REQUEST { switch -glob [string tolower [HTTP::uri]] { "/articles/2015/09/09/something.aspx" { HTTP::redirect http://[getfield [HTTP::host] ":" 1][HTTP::uri] return } default { if {([string tolower [HTTP::host]] starts_with "www.")} { HTTP::redirect "https://[string range [HTTP::host] 4 end][HTTP::uri]" return } elseif { [TCP::local_port clientside] == 80 } { HTTP::redirect https://[HTTP::host][HTTP::uri] return } } } } - Stanislas_Piro2
Cumulonimbus
With the irule I provided, I have the following result:
$ curl -i
HTTP/1.0 302 Found Location: https://xx.xx.xx.xx/articles/2015/09/09/something.aspx Server: BigIP Connection: Keep-Alive Content-Length: 0$ curl -i -k
HTTP/1.1 404 Not Found Date: Tue, 01 Sep 2015 03:33:54 GMT Server: Apache/2.4.7 (Ubuntu) Content-Length: 310 Content-Type: text/html; charset=iso-8859-1$ curl -i -k
HTTP/1.0 302 Found Location: http://xx.xx.xx.xx/articles/2015/09/09/somethingelse.aspx Server: BigIP Connection: Keep-Alive Content-Length: 0$ curl -i
HTTP/1.1 404 Not Found Date: Tue, 01 Sep 2015 03:34:25 GMT Server: Apache/2.4.7 (Ubuntu) Content-Length: 314 Content-Type: text/html; charset=iso-8859-1Isn't it the expected result?
- Stanislas_Piro2
Cumulonimbus
$ curl -i
HTTP/1.1 404 Not Found Date: Tue, 01 Sep 2015 03:34:25 GMT Server: Apache/2.4.7 (Ubuntu) Content-Length: 314 Content-Type: text/html; charset=iso-8859-1$ curl -i
HTTP/1.1 404 Not Found Date: Tue, 01 Sep 2015 04:24:50 GMT Server: Apache/2.4.7 (Ubuntu) Content-Length: 315 Content-Type: text/html; charset=iso-8859-1$ curl -i
HTTP/1.1 404 Not Found Date: Tue, 01 Sep 2015 04:25:00 GMT Server: Apache/2.4.7 (Ubuntu) Content-Length: 315 Content-Type: text/html; charset=iso-8859-1this is exactly the result you described.
- Stanislas_Piro2
Cumulonimbus
try this one, I changed order between conditions:
when HTTP_REQUEST { set is_ssl [PROFILE::exists clientssl] log local0. "SSL : $is_ssl" set is_ssl_URL [string compare -nocase [HTTP::uri] "/articles/2015/09/09/something.aspx"] log local0. "clear URL : $is_ssl_URL" if { $is_ssl && !($is_ssl_URL)} { HTTP::redirect http://[getfield [HTTP::host] ":" 1][HTTP::uri] } elseif { !($is_ssl) && $is_ssl_URL} { HTTP::redirect https://[getfield [HTTP::host] ":" 1][HTTP::uri] } }
Help guide the future of your DevCentral Community!
What tools do you use to collaborate? (1min - anonymous)Recent Discussions
Related Content
* 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
