Forum Discussion
mart_58302
Nimbostratus
Sep 23, 2008Destination based redirect irule, a'la cache.pac implementing?
Hello.
We are using F5 for proxy servers gateway, and everything works fine, but due routings in proxy's if the clients destination is local network, the proxy's can't connect to local network, so in web browsers are using cache.pac where is defined, that if destination is local network, traffic goes directly, not via F5. Example:
function FindProxyForURL(url, host) {
if(shExpMatch(host, "*[^0123456789.]*") == false)
if( isInNet(host, "127.0.0.0", "255.0.0.0")
|| isInNet(host, "172.17.0.0", "255.255.0.0")
|| isInNet(host, "172.18.0.0", "255.255.0.0")
)
return "DIRECT";
else
return "PROXY proxygateway.internal:8080; DIRECT";
)
But clients who can't read/use the cache.pac can't connect local network at all, so is it possible on the F5 with irule do same thing as with cache.pac, that if destination is local network F5 redirects all this traffic to the network directly and without any NAT/SNAT?
35 Replies
- mart_58302
Nimbostratus
Posted By nmenant on 10/01/2008 3:06 AM
Hi,
With your configuration here is what is happening:
If client connects on port 80 then it will try to connect on port 80 on your pool since you specified "any" for the port on the vs and on each pool member.
If you want to receive all http connections on port 8080 on your pool then you should change the port information from any to 8080
Hmm, but then I loose all other connections to proxy, as proxy is listening also on a lot other ports and http is only listening on 8080.
Seems, either I define for every proxy service a diffent VIP or I can't use this rule? - hoolio
Cirrostratus
If the browser has a proxy configured, the destination address for any request is going to be the proxy server IP address. You'd need to look at the HTTP host header in the request to determine the actual HTTP server the request is being made to. If you configure a VIP on the port that the client is making the request to the proxy server, you add an HTTP profile to the VIP, check the Host header value and then make a decision on how to handle the traffic.
If you configure the pool for a port of 'any' then LTM won't translate the destination port from what the client requested when sending requests to the pool. If the client request worked without LTM, then the connection through LTM's VIP should work okay.
If you configure a new 0.0.0.0:8080 VIP with an HTTP profile and the rule which inspects the Host header, does it work? If not, what do you see on the client and the LTM log file?
Aaron - mart_58302
Nimbostratus
If the browser has a proxy configured, the destination address for any request is going to be the proxy server IP address. You'd need to look at the HTTP host header in the request to determine the actual HTTP server the request is being made to. If you configure a VIP on the port that the client is making the request to the proxy server, you add an HTTP profile to the VIP, check the Host header value and then make a decision on how to handle the traffic.
If you configure the pool for a port of 'any' then LTM won't translate the destination port from what the client requested when sending requests to the pool. If the client request worked without LTM, then the connection through LTM's VIP should work okay.
If you configure a new 0.0.0.0:8080 VIP with an HTTP profile and the rule which inspects the Host header, does it work? If not, what do you see on the client and the LTM log file?
Ok, made new VIP 0.0.0.0:8080, with http profile and activated rulewhen HTTP_REQUEST { if {[scan [HTTP::host] {%[0-9:]}] eq [HTTP::host]}{ if {[matchclass [getfield [HTTP::host] ":" 1] eq ::private_net]}{ log local0. "matched local addresses" forward } } log local0. "didn't match local addresses" pool live-proxy-pool }
And if dst ip is external, traffic goes to the proxy, but if dst ip is internal, then nothing happends, in logs I can see:
Oct 1 16:32:48 tmm tmm[1712]: Rule http_bypass_proxy_debug : didn't match local addresse - hoolio
Cirrostratus
You need to add a 'return' after the forward command to prevent the rest of the rule from running for requests with a local IP in the host header. Can test with this version and some additional logging?when HTTP_REQUEST { log local0. "[IP::client_addr]:[TCP::client_port]: [IP::local_addr]:[TCP::local_port] [HTTP::host][HTTP::uri]" if {[scan [HTTP::host] { % [ 0 - 9 : ] }] eq [HTTP::host]}{ log local0. "[IP::client_addr]:[TCP::client_port]: Host header was numeric" if {[matchclass [getfield [HTTP::host] ":" 1] eq ::private_net]}{ log local0. "[IP::client_addr]:[TCP::client_port]: Host was an internal IP. Forwarding and exiting rule event" forward return } } log local0. "[IP::client_addr]:[TCP::client_port]: Host header wasn't numeric and a local IP address. Using proxy pool." pool live-proxy-pool }
Make sure to remove all of the spaces in the scan command: { % [ 0 - 9 : ] }
Aaron - mart_58302
Nimbostratus
You need to add a 'return' after the forward command to prevent the rest of the rule from running for requests with a local IP in the host header. Can test with this version and some additional logging?
Sorry, there was return, I just by mistake didn't paste it here. With Your rule I can access external ip -s, but not local ones:
External:
Oct 2 14:30:37 tmm tmm[1712]: Rule http_proxy_bypass_debug : 172.18.15.13:1660: 192.168.121.125:8080 www.neti.eehttp://www.neti.ee/
Oct 2 14:30:37 tmm tmm[1712]: Rule http_proxy_bypass_debug : 172.18.15.13:1660: Host header wasn't numeric and a local IP address. Using proxy pool.
Oct 2 14:30:38 tmm tmm[1712]: Rule http_proxy_bypass_debug : 172.18.15.13:1662: 192.168.121.125:8080 www.neti.eehttp://www.neti.ee/style/colors.css
Local:
Oct 2 14:32:59 tmm tmm[1712]: Rule http_proxy_bypass_debug : 172.18.15.13:1688: 192.168.121.125:8080 list.internalhttp://list.internal/favicon.ico
Oct 2 14:32:59 tmm tmm[1712]: Rule http_proxy_bypass_debug : 172.18.15.13:1688: Host header wasn't numeric and a local IP address. Using proxy pool. - hoolio
Cirrostratus
Sorry for the confusion... if you want to pass some requests on to a proxy but have the rule act as an HTTP proxy for local addresses, you'd need to rewrite the host header and change the destination IP address to that of the host header. Is all traffic through the VIP which is destined for a local address HTTP to port 80? If so, it might be feasible to do this. If some of the requests might be HTTPS it would be more complicated. Can you describe the scenario for local requests? I might have time in the next few days to write up a more involved example.
Else, if you wanted to configure a proxy server for local addresses, you could just send the requests to that proxy server, as you are for the remote requests. Maybe this would defeat your aim though?
Aaron - hoolio
Cirrostratus
I didn't have period character listed in the scan command, so the IP address check would have always failed. Here is an alpha rule example which checks the host header for IP addresses. If the requested host is an IP or IP:port, where the IP is an internal IP, the rule sends the request to the requested IP (or IP:port). All other requests are send to the proxy pool. I wasn't sure what a server would do with the Proxy-Connection header, so I removed it. I tested this with a few requests, but not thoroughly. It doesn't support SSL to the server. I'd have to do a bit more testing to try to support that.
Aaronwhen HTTP_REQUEST { Check if host header value only contains numerals, '.' or ':' The format is {%[CHARS]}, where CHARS can be a character ranges or single characters. The literal hyphern character '-' needs to be listed first or last in the character set if {[scan [HTTP::host] { % [ 0 - 9 . : ] }] eq [HTTP::host]}{ log local0. "[IP::client_addr]:[TCP::client_port]: Matched header: [HTTP::host]" Split the host header value on the : if it exists. set ip [getfield [HTTP::host] ":" 1] set port [getfield [HTTP::host] ":" 2] log local0. "[IP::client_addr]:[TCP::client_port]: \$ip: $ip, \$port: $port" Check if the IP is an internal IP address (matches the stock private_net datagroup). Running matchclass against the parsed IP address verifies the parsed IP address is valid so we don't need additional checks. if {[matchclass $ip eq $::private_net] or 1}{ log local0. "[IP::client_addr]:[TCP::client_port]: Match class test, sending request to $ip:$port" Request is to a local IP address, so use the host value and the port if it's included as the destination. 'string is integer' returns true for a null length variable, so check that the string length is greater than 1 and that the string is an integer if {[info exists port] and [string length $port] and [string is integer $port]}{ node $ip $port } else { node $ip 80 } Remove the Proxy-Connection header. HTTP::header remove "Proxy-Connection" Stop processing this event in this rule. return } } pool proxy_pool log local0. "[IP::client_addr]:[TCP::client_port]: Didn't match header: [HTTP::host], or IP was not internal" }
Make sure to remove the spaces in the scan parameter:
{ % [ 0 - 9 . : ] } - mart_58302
Nimbostratus
I didn't have period character listed in the scan command, so the IP address check would have always failed. Here is an alpha rule example which checks the host header for IP addresses. If the requested host is an IP or IP:port, where the IP is an internal IP, the rule sends the request to the requested IP (or IP:port). All other requests are send to the proxy pool. I wasn't sure what a server would do with the Proxy-Connection header, so I removed it. I tested this with a few requests, but not thoroughly. It doesn't support SSL to the server. I'd have to do a bit more testing to try to support that.
I was sick, so I will test Your rule today, but seems it's impossible to to the trick with one global proxy gateway, as there are no profile defined and all traffic, (http/https/socks/ftp/streaming etc) goes true it? - hoolio
Cirrostratus
If that's the case, I think it would take an incredibly complicated iRule. Do you have an option to configure a proxy for LAN requests and send the requests to local addresses to that server, rather than trying to support all those protocols using an iRule on the LTM?
Aaron - mart_58302
Nimbostratus
If that's the case, I think it would take an incredibly complicated iRule. Do you have an option to configure a proxy for LAN requests and send the requests to local addresses to that server, rather than trying to support all those protocols using an iRule on the LTM?
Well, I do it with cache.pac for web browsers, but the main problems are all others clients, which can not read or understood cache.pac. So that's why I had idea do some magic in LTM.
But seems making this workable is impossible, still big thanks for You for helping me.
Help guide the future of your DevCentral Community!
What tools do you use to collaborate? (1min - anonymous)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