Forum Discussion

Nikolay_Matveev's avatar
Nikolay_Matveev
Icon for Nimbostratus rankNimbostratus
Feb 12, 2015

select a pool based on source IP and then amend headers based on selected pool

Hi,

Could you advise how I can achieve the following goal, please?

I have two web servers - external (3rd party - server1.external.com) and internal (server2.internal.com). I need to present these two servers to internal users as appname.internal.com but make load balancing decision based on source IP of internal users.

I have now worked out how I can trick the remote server (substituting Host and Location headers in requests and responses accordingly) but I am struggling to combine this with pool selection based on IP.

Should it be something like this?

when CLIENT_ACCEPTED {
        
}

when HTTP_REQUEST {
    if  {
       the header replacement below works fine    
      HTTP::header replace host "server1.external.com" 
      }
     else {
      HTTP::header replace host "server2.internal.com" 
     }
}

when HTTP_RESPONSE {
     Rewrite the Location header for redirects
    if { [HTTP::header exists Location] }{ 
            HTTP::header replace Location [string map {"https://server1.external.com" "https://appname.internal.com"} [HTTP::header Location]] 
    }
}

8 Replies

  • Will something like this work for your node selection?

    when CLIENT_ACCEPTED {
        if { [IP::addr [IP::client_addr] equals 10.0.0.0/8] } {
            node server2.internal.com
        }
        else {
            node server1.external.com
        }
    }
    
  • Yes, perhaps there are two options here - one is to have two pools with one server in each OR have a single pool with two servers in it... not sure what would the recommended option be. My thinking was that two pools would be a more universal solution (as then I could add servers to each of the pools) but I do not know how to reference pool name.

     

    The code below does not seem to be working

     

    when CLIENT_ACCEPTED {
        if { [IP::addr [IP::client_addr] equals 10.0.0.0/8] } {
            pool POOL_FOR_EXTERNAL_SERVERS
        }
        else {
            pool POOL_FOR_INTERNAL_SERVERS
        }
    }
    when HTTP_REQUEST {
        if { [LB::server pool] eq "POOL_FOR_EXTERNAL_SERVERS" } {
            <....handling headers for the external servers..>
        } else {
            <.. handling headers for the internal servers ..>
        }
    }

    What am I doing wrong here?

     

    • Brad_Parker's avatar
      Brad_Parker
      Icon for Cirrus rankCirrus
      doing it with pools would make it scale-able if you needed to add servers and the syntax is correct you have here. What's not working exactly, the pool selection? Try adding some logging to see what's happening. Throw something like 'log local0. "External(or Internal) Pool [IP::client_addr]" ' to you if/else statements and see what gets logged.
  • the IF statement in HTTP_REQUEST handling does not seem to work...

     

    Where would that log entry appear? System - Logs - Local Traffic? (cannot find where it's saving the log to... nothing is appearing in the external syslog :()

     

  • Ignore me - found now! By looks of it the pool name is prefixed by "/Common/". Silly mistake :) I will correct and get back with an update.

     

  • Ok, all good now except one thing - the internal server is HTTP only on the server side, and the VS has SSL profiles both on the client side and on the server side. Now when I select the internal pool I get "Page not available" in the browser. I assume this is because LTM is trying to negotiate SSL to the port 80 of the server that allows only HTTP.

    How do I correctly disable SSL profile and under what event? Currently I am trying as follows (does not seem to be working):

    when CLIENT_ACCEPTED {
        if { [IP::addr [IP::client_addr] equals 192.168.1.0/24] } {
            pool "/Common/POOL_SERVICEDESK_EXT_HTTPS_443"
            log local0. "SERVICEDESK Client accepted, pool [LB::server pool]"
        }
        else {
            pool "/Common/POOL_SERVICEDESK_INT_HTTP_80"
            log local0. "SERVICEDESK Client accepted, pool [LB::server pool]"
             disable SSL here?
            SSL::disable serverside
        }
    }
    
    when HTTP_REQUEST {
     if { [LB::server pool] eq "/Common/POOL_FOR_EXTERNAL_SERVERS" }{
            
             Working with headers for External server
            
            log local0. "SERVICEDESK Request Received. Active app - External"
            HTTP::header replace host "server1.external.com" 
            if {[HTTP::uri] equals {/}} {HTTP::uri {/support/home}}
            } else {
            
             Working with headers for Supportworks
            
            log local0. "SERVICEDESK Request Received. Active app - Internal"
            HTTP::header replace host "server2.internal.com"
             or shall I disable it here?
            SSL::disable serverside
     }
    }
    
    when HTTP_RESPONSE {
         Rewrite the Location header for redirects
        if { [HTTP::header exists Location] }{ 
            HTTP::header replace Location [string map {"https://server1.external.com" "https://app.internal.com"} [HTTP::header Location]] 
            HTTP::header replace Location [string map {"http://server2.internal.com" "https://app.internal.com"} [HTTP::header Location]]
       }
    }
    
    • Brad_Parker's avatar
      Brad_Parker
      Icon for Cirrus rankCirrus
      I personally like to set a variable like $serverSSL 0/1 in the HTTP_REQUEST then put SSL::disable in the SERVER_CONNECTED event with an if $serverSSL == 1
    • Brad_Parker's avatar
      Brad_Parker
      Icon for Cirrus rankCirrus
      Also, make sure you have port translation checked on the VS.