For more information regarding the security incident at F5, the actions we are taking to address it, and our ongoing efforts to protect our customers, click here.

Forum Discussion

Shawn_Salyers_8's avatar
Shawn_Salyers_8
Icon for Nimbostratus rankNimbostratus
Mar 29, 2010

iRule Redirect and mask destination URL

Hello all, I am somewhat new to the F5 and have been doing a bit of searching and have come up with some similar scenarios which leads me to believe that what I am trying to accomplish is possible. What I am looking to do is a redirect from something like www.abc123.com to www.abc456.com/application/. However, I want the browser bar only to show the www.abc123.com + URI. Any help with this would be greatly appreciated.

 

 

--Shawn

15 Replies

  • Hmmm. Maybe I'm missing something. I was able to create the external file based datagroup without a problem. But I'm not clear on how to configure a server off of my network as a node in one of my pools. I am looking to do a pass-thru reverse proxy, none of the assets or content is hosted in my network.

     

     

    BTW, THANK YOU SO MUCH FOR ALL THE HELP!!!
  • hoolio's avatar
    hoolio
    Icon for Cirrostratus rankCirrostratus
    Can you hardcode the IP address(es) that the external domain resolves to? Or do you need to do a DNS lookup of the hostname? If the former, you can configure the IP address:port combinations in the pool. If the latter, you can use NAME::lookup in pre-10.1 or RESOLV::loookup in 10.1+ to resolve the hostname. For NAME::lookup, I can post an anonymized iRule example to do a look up every X seconds in the next couple of days.

     

     

    Aaron
  • Thank you so much for your help! Finally got this working through HTTP now to get the SSL side done. Again, thanks for all your help.

     

     

    --Shawn
  • jojow's avatar
    jojow
    Icon for Nimbostratus rankNimbostratus
    Hi,

     

     

    I have the same issue. I want to proxy to urls that are not in our network. And I can't make a pool, because we have to resolve the name on the fly.

     

    To give you an example so you can understand what we are trying to accomplish.

     

    We have made some google app, but want the apps to have a mycompany.com url:

     

    http://appname.mycompany.com/ -> http://appname.appspot.com/

     

    We don't want a redirect, and we should rewrite the response as well. I thought ProxyPass would work, but the trouble is that I can't make a pool of a domain name.

     

     

    - Jojo
  • hoolio's avatar
    hoolio
    Icon for Cirrostratus rankCirrostratus
    Hi Jojo,

    Which LTM version are you running? For 9.x - 10.0.x you can use NAME::lookup to resolve a hostname to an IP address. For 10.1.x and higher, you can use RESOLV::lookup

    http://devcentral.f5.com/wiki/default.aspx/iRules/NAME__lookup

    http://devcentral.f5.com/wiki/default.aspx/iRules/RESOLV__lookup

    You might want to implement logic to cache the IP address for x seconds. Here is a rough web proxy example which does this. Note, I wouldn't suggest using the proxy functionality, but hopefully it gives you an idea of how to use NAME::lookup.

    Aaron

    
     web proxy example
    
     This is a simple, incomplete example web proxy iRule.
     It only supports limited proxy functionality of converting the requested host 
        (from an absolute URI or the Host header) to an IP address and sending the request on.  
     It doesn't support CONNECT/HTTPS or most other RFC2616 requirements for a web proxy.
    
    when HTTP_REQUEST {
    
       log local0. "[IP::client_addr]:[TCP::client_port]: New HTTP [HTTP::method] request to [HTTP::host], [HTTP::uri]"
    
        Check if the URI is absolute and http://
       if {[string tolower [HTTP::uri]] starts_with "http://"}{
    
           Parse the host value from the URI
          set host [URI::host [HTTP::uri]]
          log local0. "[IP::client_addr]:[TCP::client_port]: Parsed $host from URI [HTTP::uri]"
    
       } else {
          set host [HTTP::host]
       }
    
        Check if host header has a port
       if {$host contains ":"}{
    
           Scan the host header to parse the host and port
          if {[scan $host {%[^:]:%s} host port] == 2}{
    
             log local0. "[IP::client_addr]:[TCP::client_port]: Parsed \$host:\$port: $host:$port"
    
          } else {
              Host value was host: without a port. Use the requested port.
             set port [TCP::local_port]
          }
       } else {
    
           Host header didn't have a port. Use the requested port.
          set port [TCP::local_port]
       }
        Check if the host header isn't an IP address (ie, it contains an alpha character)
       if {[string match {*[a-zA-Z]*} $host]}{
    
          log local0. "[IP::client_addr]:[TCP::client_port]: Host value not an IP: $host"
    
           Perform a DNS lookup of the hostname
          NAME::lookup $host
    
           Hold the request until name resolution completes
          HTTP::collect
    
       } elseif {[catch {IP::addr $host mask 255.255.255.255}]==0}{
    
          log local0. "[IP::client_addr]:[TCP::client_port]: Host is an IP: [HTTP::host]"
    
           Request was to a valid IP address, so use that as the destination
          node $host $port
    
       } else {
    
           Couldn't parse host header.  Could use the destination IP address as the destination?
          HTTP::respond 400 content "Invalid Host header"
          log local0. "[IP::client_addr]:[TCP::client_port]: Invalid host header: [HTTP::host]"
       }
    }
    when NAME_RESOLVED {
    
       set response [NAME::response]
    
       log local0. "[IP::client_addr]:[TCP::client_port]: Resolution response: $response (elements: [llength $response])"
    
        Check if there is a resolution answer and it's an IP address
       switch [llength $response] {
    
          0 {
              No response, or response wasn't an IP address
             log local0. "[IP::client_addr]:[TCP::client_port]: Non-existent/invalid response: $response"
     HTTP::respond 500 content "Couldn't process request"
          }
          default {
    
              Response was one or more list entries.  Use the first list element.  Check if it's an IP address.
             if {[catch "IP::addr [lindex $response 0] mask 255.255.255.255"]==0}{
    
                 Request was to a valid IP address, so use that as the destination
                if {$port != "" and [string is integer $port]}{
                   log local0. "[IP::client_addr]:[TCP::client_port]: Using destination with parsed port [lindex $response 0]:$port"
                   node [lindex $response 0] $port
                } else {
                   log local0. "[IP::client_addr]:[TCP::client_port]: Using destination with default port $response:[TCP::local_port]"
                   node [lindex $response 0] $::default_port
                }
             } else {
                 No response, or response wasn't an IP address
                log local0. "[IP::client_addr]:[TCP::client_port]: Non-existent/invalid response: $response"
        HTTP::respond 500 content "Couldn't process request"
             }
          }
       }
        Release the request
       HTTP::release
    }