Forum Discussion
Durga_Dash_2124
Nimbostratus
Jun 02, 2008Shared Virtual Server HTTP to HTTPS redirect
I want to build a single virtual server that will respond to requests both on port 80 and 443. I want port 80 traffic to be redirected to port 443. Also the servers on the internal pool listen on both 80 and 443 and they redirect all traffic to 443 except if the source is the Big-Ip. This we achieve by writing a server side script that looks at the HTTP header of the client request and if it has a variable 'SSLClientCipher' it assumes it is F5 and does not redirect that traffic to 443 but keeps it on port 80.
So i have the following irule in place:
-----------
rule httptossl_insertcipher {
when HTTP_REQUEST {
if { [TCP::local_port] == 80 }{
log local0. "in HTTP_REQUEST"
HTTP::respond 301 Location "https://[getfield [HTTP::host] : 1][HTTP::uri]"
}
elseif { [TCP::local_port] == 443}{
log local0. "in HTTPS_REQUEST"
HTTP::header insert SSLClientCipher [SSL::cipher name],\x20version=[SSL::cipher version],\x20bits=[SSL::cipher bits]
}
else {
log local0. "in Reject_REQUEST"
reject
}
}
}
-----------------
This is what my virtual server configuration looks like
virtual Test_CLIN {
destination 10.50.1.77:any
ip protocol tcp
translate service enable
profile http tcp wwwadirondocorg
persist cookie
pool ARCHIE_CLIN
rule httptossl_insertcipher
vlans external enable
}
----------------
I have enabled port translation on the vs to make sure it goes to port 80 on the pool.
..and this is my pool
pool ARCHIE_CLIN {
lb method member predictive
monitor all http
member 10.50.10.2:http session disable
member 10.50.10.42:http
member 10.50.10.82:http session disable
}
---
With this configuration https links work..but if i try to hit the virtual server on port 80 the virtual server closes the connection.
irule debugs don't generate any logs in /var/log/ltm when i try http but tcpdump shows..the virtual server closing out the client connection.
Not sure if this is the correct forum i.e. if this is an irule issue...
Any help is appreciated.
Thanks
Durga.
8 Replies
- Andy_Herrman_22
Nimbostratus
Do you get anything in the logs when using HTTPS links? You said the links work, but does that mean the app/page works correct, or that you're actually seeing what you expect in the logs.
I didn't think HTTP profiles could be applied to wildcard virtual servers, so it's possible the HTTP_REQUEST isn't being triggered, but I could be wrong. - Durga_Dash_2124
Nimbostratus
When I try https. The appropriate webpage from the server in the pool is displayed and also in the ltm logs i see thr irule being triggered.
But when i try http i never see the irule being triggered from the ltm logs.
Is there another way to set the above up? - Andy_Herrman_22
Nimbostratus
We do SSL termination in our application, and we have separate virtual servers configured. One specifically for port 443 that has the ssl profile applied to it, and one for port 80 that doesn't. All the rest of the configuration between the two are the same.
It's a bit more configuration, but I generally like having explicit Virtual Servers instead of generic ones. It makes separation of logic and stuff a bit cleaner. - Durga_Dash_2124
Nimbostratus
That is how we have done it always too. Separate VS for 80 and 443. With a http-to-https irule for the VS listening on port 80 and our insert Cipher irule for the VS listening on 443...and that works fine.
But i saw this irule in devcentral HttptoHttpsSingleVirtualServer
http://devcentral.f5.com/wiki/default.aspx/iRules/HttpHttpsSingleVirtualServer.html
That should work for wildcard virtual servers. I modified it by adding
HTTP::header insert SSLClientCipher [SSL::cipher name],\x20version=[SSL::cipher version],\x20bits=[SSL::cipher bits]
the above to the HTTP_request event but that gives me an error in ltm " Error: SSL hudfilter not reached or not in chain".
even without the cipher insert it doesn't seem to work for me. - hoolio
Cirrostratus
If you're trying to insert the output from an SSL-based command, you'd want to only attempt it for HTTPS connections. The SSL:: commands wouldn't be valid if the clientside connection was non-HTTPS. So add the header insert line within the 'else' block of the HTTP_REQUEST event:when HTTP_REQUEST { If redirect_http_to_https is enabled and the request was made to an HTTP port, redirect the client to the same host/URI over HTTPS if { ($::redirect_http_to_https == 1 or ([info exists redirect_http_to_https] && $redirect_http_to_https)) && \ ([info exists vip_http_port] && $vip_http_port==1)}{ HTTP::redirect https://[getfield [HTTP::host] ":" 1][HTTP::uri] if {$::debug}{log local0. "redirecting client [IP::client_addr] to https://[getfield [HTTP::host] \":\" 1][HTTP::uri]"} } else { HTTP::header insert SSLClientCipher [SSL::cipher name],\x20version=[SSL::cipher version],\x20bits=[SSL::cipher bits] ... } }
If you're already checking that the requested port is HTTPS before trying to insert the HTTP header, can you post the full rule you get the error with?
Another way to insert a space would be to wrap the header value in double quotes:
HTTP::header insert SSLClientCipher "[SSL::cipher name], version=[SSL::cipher version], bits=[SSL::cipher bits]"
Aaron - Durga_Dash_2124
Nimbostratus
Yes i had finally reached there tinkering with the rules....Coz i realised the SSLCipher will not work when it is a request over port 80 with no SSLprofile..
This was my final rule..
----------------------------------
when HTTP_REQUEST {
If redirect_http_to_https is enabled and the request was made to an HTTP port, redirect the client to the same host/URI over HTTPS
if { ($::redirect_http_to_https == 1 or ([info exists redirect_http_to_https] && $redirect_http_to_https)) && \
([info exists vip_http_port] && $vip_http_port==1)}{
HTTP::redirect https://[getfield [HTTP::host] ":" 1][HTTP::uri]
if {$::debug}{log local0. "redirecting client [IP::client_addr] to https://[getfield [HTTP::host] \":\" 1][HTTP::uri]"}
}
if { [TCP::local_port] == 443 }{
HTTP::header insert SSLClientCipher [SSL::cipher name],\x20version=[SSL::cipher version],\x20bits=[SSL::cipher bits]
}
}
--------------
I just added a check for TCP::local_port before trying to insert the SSL cipher.
Now that i have finally got it working..I have one last question..
Are there any negatives in setting up my virtual servers this way with the single irule for both http and https requests? (like more cpucycles)....instead of the traditional two virtual servers one for 80 and one for 443?
..and thanks a lot guys for the responses and help.
Durga. - hoolio
Cirrostratus
There is more overhead to run the rule than have two distinct VIPs. If you haven't already, you could remove some of the code from the iRule if you aren't using the functionality. Also, if you know there is a client SSL profile on the VIP, you could remove the 'PROFILE::exists clientssl' check.
You could use timing to get an idea of how much CPU time the iRule requires (Click here). You won't have another iRule to compare it to though. Or you could do a rough comparison by doing load testing with the iRule, checking the performance graphs and then compare that with the same load testing on two separate VIPs.
Aaron - Durga_Dash_2124
Nimbostratus
Here is my final working irule, after cleaning out all the debugging and checking since I know how my virtuals will be built.
Single wildcard virtual server on port 'Any' with ClientSSL profile set and 'http' profile set. Also with a default pool on port 80 and port translation enabled...and cookie persistence.
------------------------------
when CLIENT_ACCEPTED {
if { [TCP::local_port] == 80 }{
set disable_cmd "SSL::disable"
eval $disable_cmd
}
elseif { [TCP::local_port] != 443 }{
reject
}
}
when HTTP_REQUEST {
if { [TCP::local_port] == 80 }{
HTTP::redirect https://[getfield [HTTP::host] ":" 1][HTTP::uri]
}
if { [TCP::local_port] == 443 }{
HTTP::header insert SSLClientCipher [SSL::cipher name],\x20version=[SSL::cipher version],\x20bits=[SSL::cipher bits]
}
}
-----------------------------------
Thanks all for your help.
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
