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

Filter by:
  • Solution
  • Technology
Answers

Please help with iRule rewrite while keeping original url for external domain

Hello everyone,

Having a tough time finding a correct answer to this. I have seen very similar answers but nothing that does quite what I am asking. I am new to iRules so be kind. I have a client with the following requirements.

  1. When connecting to abc.xyz flow is as normal.
  2. When connecting to abc.xyz/example they should be redirected to abc.external.org website while retaining the original URL that is locally hosted.

The external website is not hosted locally but is just an external resource the client has an association with. I have looked for an answer all weekend with no success other than being able to get the redirect to work properly.

What I have below is supposed to keep the original URL but it does not. It just does the redirect. Any help would be greatly appreciated.

when HTTP_REQUEST {
    if { [string tolower [HTTP::host]] equals "abc.xyz" and [string tolower [HTTP::uri]] starts with "/example" } {
    HTTP::respond 301 noserver Location "abc.external.xyz"
    }
}

I have also tried changing the HTTP::header on the HTTP_RESPONSE but that just gives me a 404 error with the following in the address bar "abc.xyz/abc.external.xyz".

I have also seen suggestions of using rewrite profiles but that doesn't seem to do what I want either and can't find any real examples of them. Again, any help would be appreciated.

Thank you!

Jonathan

0
Rate this Question
Comments on this Question
Comment made 1 month ago by JonathanW 11

Is there no one that can help with this? It would be greatly appreciated.

-1

Answers to this Question

placeholder+image
USER ACCEPTED ANSWER & F5 ACCEPTED ANSWER

Hi Jonathan,

You can try creating an FQDN node and pool containing the external website and then using an iRule to replace the HTTP host header while not modifying the URI.

Try this (substitute your own values) and let me know if it works:

create ltm node www.foo.net fqdn { name www.foo.net interval ttl }

create ltm pool POOL-www.foo.net members add { www.foo.net:80 }

when HTTP_REQUEST {
    if { [string tolower [HTTP::host]] equals "abc.net" && [string tolower [HTTP::uri]] starts_with "/example" } {
        HTTP::header replace host "www.foo.net"
        pool POOL-www.foo.net
        snat automap
    }
}
0
Comments on this Answer
Comment made 1 month ago by Michael Saleem 335

You can also achieve a similar thing using a local traffic policy rather than an irule:

create ltm policy Drafts/PROXY-EXTERNAL-WEBSITE strategy first-match rules add { abc.net { conditions add { 0 { http-host host equals values { abc.net } } 1 { http-uri path starts-with values { /example } } } actions add { 0 { http-host replace value www.foo.net } 1 { forward select pool POOL-www.foo.net snat automap } } } }

publish ltm policy Drafts/PROXY-EXTERNAL-WEBSITE

modify ltm virtual <VIRTUAL SERVER NAME> policies add { PROXY-EXTERNAL-WEBSITE }

0
Comment made 1 month ago by JonathanW 11

Hello Michael,

Your answer seems to be the most promising as after adding the config above it now keeps the original URL in the address bar but does not redirect to the external URL and gives a 404 error. I have a feeling it is a simple setting on this one. If you would like me to show any part of the config or screenshots perhaps, please let me know.

Thank you,

Jonathan

0
Comment made 1 month ago by Michael Saleem 335

Hi Jonathan,

Thanks for the feedback.

Are you using the iRule or Local Traffic Policy method?

Could you confirm the desired outcome you are after?

For example, is what I have stated below the correct rewrite that you want?

http://abc.xyz/example ==> http://abc.external.org

http://abc.xyz/example/foo ==> http://abc.external.org/foo


0
Comment made 1 month ago by JonathanW 11

Hello Michael,

Just to make sure I am reading you correctly I have your first two lines creating the node and pool below.

create ltm node www.foo.net fqdn { name www.foo.net interval ttl }

create ltm pool POOL-www.foo.net members add { www.foo.net:80 }

The first line I have "www.foo.net"; bolded, I am assuming that is the node name and the second one is the actual HTTP::host portion.

In the second line the pool name is obvious but at the end are you adding the node name?

Just need some clarification as I think now it is something simple keeping this from working.

Thank you again,

Jonathan

0
Comment made 1 month ago by Michael Saleem 335

Hi Jonathan,

You are correct.

create ltm node <DESCRIPTIVE NODE NAME> fqdn { name <ACTUAL FQDN THE F5 WILL RESOLVE> interval ttl }

create ltm pool <DESCRIPTIVE POOL NAME> members add { <DESCRIPTIVE NODE NAME>:80 }


0
Comment made 1 month ago by JonathanW 11

Hello Michael,

I missed your comment above. With your examples ealier it is the first one I am trying to achieve

http://abc.xyz/example ==> http://abc.external.org (http://abc.xyz goes to normal internal site. http://abc.xyz/example goes to external site but still looks like internal) if that makes any sense.

What it is doing with your code above is I think it is replacing the HTTP::host and uri of the original but also trying to redirect there as well, which there is no page for the /example. That should not matter though as that should trigger the rewrite/redirect.

I hope this makes sense.

Thank you,

Jonathan

0
Comment made 1 month ago by JonathanW 11

And I am using the policy since you said it should do the same thing.

0
Comment made 1 month ago by JonathanW 11

Hello Michael,

New update. I switched from using the policy to the iRule and it now goes to the external website and keeps the original URL like it should.

Only issue now is that it keeps the HTTP::uri in the redirect which it shouldn't as seen below.

http://origianurl.com/external --> should go to http://externalsite.org but it's redirecting to http://externalsite.org/external which goes to the correct site but getting the external site's The requested page "/external" could not be found.

Any ideas? Very close! lol

Thank you,

Jonathan

0
Comment made 1 month ago by Michael Saleem 335

Hi Jonathan,

Thanks for confirming that you are now using the iRule.

Please try the following. (NOTE: I have added HTTP::uri "/")

This should now perform the following:

http://origianurl.com/external ==> http://externalsite.org/

when HTTP_REQUEST {
    if { [string tolower [HTTP::host]] equals "abc.net" && [string tolower [HTTP::uri]] starts_with "/example" } {
        HTTP::header replace host "www.foo.net"
        HTTP::uri "/"
        pool POOL-www.foo.net
        snat automap
    }
}

NOTE: If you need to preserve the URI like the following for example, please let me know:

http://externalsite.org/example/blah ==> http://externalsite.org/blah


0
Comment made 1 month ago by JonathanW 11

Hello Michael,

One word...Genius! Thank you so much for your help with this. I actually tried

HTTP::header replace uri "/" but that didn't work...yours did!

Thank you again good sir!

Jonathan

0
Comment made 1 month ago by JonathanW 11

Just asking, but is there a way to do the same thing in the traffic policy?

Jonathan

0
Comment made 1 month ago by Michael Saleem 335

Hi Jonathan,

You're most welcome! I am glad to hear that it's working.

Sure, this should also be possible with a local traffic policy. It's the same as the one I posted earlier; we just need to add the logic to replace the uri (with HTTP::uri)

Please try the following:

create ltm policy Drafts/PROXY-EXTERNAL-WEBSITE strategy first-match rules add { abc.net { conditions add { 0 { http-host host equals values { abc.net } } 1 { http-uri path starts-with values { /example } } } actions add { 0 { http-host replace value www.foo.net } 1 { http-uri replace value / } 2 { forward select pool POOL-www.foo.net snat automap } } } }

publish ltm policy Drafts/PROXY-EXTERNAL-WEBSITE

modify ltm virtual <VIRTUAL SERVER NAME> policies add { PROXY-EXTERNAL-WEBSITE }

0
Comment made 1 month ago by JonathanW 11

Thank you again Michael for all your help. One last issue has arisen I was hoping you could help with. The client requirements changed a bit as they now say HTTPS can be used. It makes the redirect a bit easier but even after recreating the pool/nodes for 443 instead of 80. It is now saying "www.foo.net didn't send any data" so I am wondering if it has anything to do with the SSL part?

Thank you,

Jonathan

0
Comment made 1 month ago by Michael Saleem 335

Hi Jonathan,

Yes, you are correct. So now you wish to proxy an external HTTPS site and so, you have modified the members in the pool to listen on port 443 instead port 80. However, now the connection breaks since the F5 is sending an HTTP request to the external pool members on port 443 (the pool members are expecting HTTPS requests)

To resolve this, you need to add a serverssl profile to the virtual server to make the F5 act as an SSL client so that it initiates an SSL handshake with the pool members:

modify ltm virtual <VIRTUAL NAME> profiles add { serverssl }


0
Comment made 1 month ago by JonathanW 11

Hello Michael,

Thank you so much for your help, you don't know how much I appreciate it! I only have one last question...hopefully. As it turns out, our client backend server apps are listening on different HTTP ports as there is not a server side SSL profile attached. So is there a way to rewrite to an external server over HTTPS when your own servers are only using HTTP?

The external server listens on both HTTP and HTTPS so would it be better to redirect to HTTP and then rewrite to the external server? If so, can you point me in the right direction?

Thank you,

Jonathan

0
Comment made 1 month ago by Michael Saleem 335

Hi Jonathan,

Assuming you have a virtual server listening on port 443 doing SSL offload (i.e. SSL being terminated on the virtual server and then decrypted before sending to the default pool of back-end servers on an HTTP port):

Could you try adding the serverssl profile to the virtual server and using the following modified iRule?

when CLIENT_ACCEPTED {
    set DEFAULT_POOL [LB::server pool]
}

when HTTP_REQUEST {
    if { [string tolower [HTTP::host]] equals "abc.net" && [string tolower [HTTP::uri]] starts_with "/example" } {
        HTTP::header replace host "www.foo.net"
        HTTP::uri "/"
        pool POOL-www.foo.net
        snat automap
    }
    else {
        pool $DEFAULT_POOL
        SSL::disable serverside
    }
}
0
Comment made 1 month ago by JonathanW 11

Hello Michael,

You are my f5 hero! Didn't work at first because I am DNAT'ing on my router from 8443 so testing, it had that in the URL. After changing my DNAT so there was no port xlate it started working. Awesome job!

Thanks a million!

Jonathan

0
Comment made 1 month ago by Michael Saleem 335

You're most welcome Jonathan. Good catch on the DNAT! :-D

0
placeholder+image
USER ACCEPTED ANSWER & F5 ACCEPTED ANSWER

Add the URI to the redirect:

when HTTP_REQUEST {
    if { [string tolower [HTTP::host]] equals "abc.xyz" and [string tolower [HTTP::uri]] starts with "/example" } {
    HTTP::respond 301 noserver Location "https://abc.external.xyz[HTTP::uri]"
    }
}
0
Comments on this Answer
Comment made 1 month ago by JonathanW 11

Thank you Dave for your response. It still gives me the same 404 error with both URL's in the address bar.

Jonathan

0