Forum Discussion
brettbeggs_1177
Nimbostratus
Apr 07, 2010iRule Request - strip sub domains
I'm trying to create an iRule that can be used similar to the following mod rewrite command:
RewriteCond %{HTTP_HOST} ^.+\.(.+)\.mydomain\.com$ [NC]
RewriteRule ^(.*)$ https://%1.mydomain.com$1 [R=301,L]
What we're wanting is anything that hits https://*.sub.mydomain.com to be redirected to https://sub.mydomain.com. I guess i'm just not sure how to strip everything before sub.mydomain.com from the URL while maintaining whatever is in that first sub domain spot.
Ideally this single rule would work for any of these variants:
https://*.sub1.mydomain.com > https://sub1.mydomain.com
https://*.sub2.mydomain.com > https://sub2.mydomain.com
https://*.whatever.mydomain.com > https://whatever.mydomain.com
If it matters, the virtual server is configured with a wildcard ssl certificate *.mydomain.com so we're trying to avoid customers instinctively adding www. to the beginning of the url and getting a certificate error.
Thanks for helping!
6 Replies
- hoolio
Cirrostratus
Hi Brett,
I tried a regex, but it was about 10x less efficient than a couple of string and list operations:
Simple perf test:
% time {set host_list [split $host "."]; lindex $host_list [expr {[llength $host_list] -3}]} 1000
13 microseconds per iteration
% time {regexp -inline -nocase {(?:[^.]+\.){0,}([^.]+)\.mydomain\.com} test.mydomain.com} 1000
133 microseconds per iterationwhen HTTP_REQUEST { log local0. "[IP::client_addr]:[TCP::client_port]: [HTTP::method] request to [HTTP::host][HTTP::uri]" Split the host header value on periods into a list set host_list [split [HTTP::host] "."] log local0. "[IP::client_addr]:[TCP::client_port]: Parsed host list $host_list" Check if there were more than three fields if {[llength $host_list] > 3}{ Send a redirect with the third to last field from the requested host prepended to .mydomain.com HTTP::respond 301 Location "https://[lindex $host_list [expr {[llength $host_list] -3}]].mydomain.com" log local0. "[IP::client_addr]:[TCP::client_port]: Redirecting to\ https://[lindex $host_list [expr {[llength $host_list] -3}]].mydomain.com" } }
Aaron - brettbeggs_1177
Nimbostratus
Thanks Aaron.
I ended up having to make one little tweak, adding "https://" to the response code to get it sent over to the correct place.Send a redirect with the third to last field from the requested host prepended to .mydomain.com HTTP::respond 301 Location "https://[lindex $host_list [expr {[llength $host_list] -3}]].mydomain.com"
The problem now seems to be that the redirect isnt taking place before the request hits the virtual server. This is causing a certificate error to pop up. Once you add the exception and advance past it, the redirect works like a champ. I guess on some level that makes sense. The request has to hit the virtual server before it processes the iRule, but in doing so, causes the certificate exception.
When monitoring the logs, nothing gets logged until after you accept the certificate warning. - hoolio
Cirrostratus
Thanks for the correction on the redirect location protocol. I assumed you were using this rule on an HTTP VIP. As you found it's too late to fix this when the client is making an HTTPS request with a hostname that doesn't match the SSL cert. For HTTPS, LTM needs to decrypt the SSL before viewing the HTTP or sending an HTTP response. In order to decrypt the SSL, LTM needs to send its cert and complete an SSL handshake.
To fix this, you'd need to correct the client's request before it's made via HTTPS. So if you can add this iRule to an HTTP VIP you could prevent the insecure cert warning for the HTTPS requests. Or if clients are expected to make requests directly via HTTPS to the various hostnames, you could create separate A records to resolve the hostnames to different IP addresses.
Aaron - brettbeggs_1177
Nimbostratus
This is so frustrating...
I've decided to apply this iRule to the HTTP virtual server and wanted to add an else statement. Basically, the first part of the script should run and fix anything with more than 3 levels to the domain name. I want the else statement to kick in for everything else and simply redirect to https. Using the code below, i see the stuff show up in the log, but for the life of me, i can't get it to work. The browser just keeps saying that "The page isn't redirecting properly...Firefox has detected that the server is redirecting the request for this address in a way that will never complete".
Here's the code added...
else {
HTTP::respond 301 Location "https://[HTTP::host][HTTP::uri]"
log local0. "[IP::client_addr]:[TCP::client_port]: Redirecting to https://[HTTP::host][HTTP::uri] without parsing"
}
Any thoughts on why that keeps failing? - hoolio
Cirrostratus
What do the logs show (/var/log/ltm)? Is the HTTPS VIP redirecting some or all requests to HTTP?
Aaron - brettbeggs_1177
Nimbostratus
Ahh, yes...i was stupid and had the same irule on the http and https virtual server. I tweaked the version running on the https VS and now all is well. Thanks for all 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
