Proxy pacfile hosting without need for Webservers using iFiles on v11

Problem this snippet solves:

The following is an iRule that allows the F5 to serve a proxy pac file to a client without the need of hosting it on a web server or the proxy itself.

Simply create the iRule and associate it to a virtual address running a specific port that has no pools.

Definition

What the heck is a pacfile? Well it's a javascript file that defines how web browsers and other user agents can automatically choose the appropriate proxy server (access method) for fetching a given URL. So you might have specific sites that go through a proxy and some sites that do not. The pac file can do this for you.

To read up more about it you can go to the following links: http://en.wikipedia.org/wiki/Proxy_auto-config http://www.craigjconsulting.com/proxypac.html

Now back to the configuration...

How to use this snippet:

Example

VIP: 192.168.1.20: 80 TCP
Domain: Proxypacfile.intranet.com --> 192.168.1.20

Just set your browser up to use the automatic configuration script:

http://proxypacfile.intranet.com/proxy.pac

You can also set to other ports

Example:

VIP: 192.168.1.21: 9090 TCP
Domain: Proxypacfile2.intranet.com --> 192.168.1.21

Just set your browser up to use the automatic configuration script:

[http://proxypacfile2.intranet.com:9090/proxy.pac] (http://proxypacfile2.intranet.com:9090/proxy.pac)

iFile Configuration:

1) Create a pacfile for example called "proxy.pac". Contained in the file could be the following logic

function FindProxyForURL(url, host) {

         if (isPlainHostName(host))
         return "DIRECT";

         if (shExpMatch(url, "http://10.*")||
         shExpMatch(url, "https://10.*")||
         shExpMatch(url, "ftp://10.*")||
         shExpMatch(url, "http://localhost*")||
         shExpMatch(url, "https://localhost*")||
         shExpMatch(url, "http://127.0.0.1*")||
         shExpMatch(url, "https://127.0.0.1*")||
         shExpMatch(url, "http://172.*")||
         shExpMatch(url, "https://172.*")||
         shExpMatch(url, "ftp://172.*"))
         return "DIRECT";

      if (dnsDomainIs(host, ".extranet.com")||
         dnsDomainIs(host, ".extranet2.com"))
         return "Proxy yourproxy.domain.com:8080";
         
         if (dnsDomainIs(host, ".intrant.com")||
         dnsDomainIs(host, ".intranet2.com"))
         return "DIRECT";
        
      return "PROXY yourproxy.domain.com:8080";
      }
   }
   

2) Now you are ready to upload the files. This is done in System > File Management--> iFile List --> Import

NOTE: Keep in mind iFiles maximum size is 4M

3) Now create a reference of the ifile. This is done by going to Local Traffic->iRules->iFile List. Fill in the information using the same name as the file itself to make this easy.

4) Now all you need is to create the irule itself

Code :

when HTTP_REQUEST {
   switch -glob [string tolower [HTTP::uri]] {
    "/proxy.pac" {
       # Retrieve the file contents, send it in a HTTP 200 response    
       HTTP::respond 200 content [ifile get proxy.pac] "Content-Type" "application/x-ns-proxy-autoconfig" "pragma" "no-cache"

    }
default {
            ## requested something else
            HTTP::respond 404 content "Oops! You've asked for something we don't have."
        }   
   }
}
Published Mar 18, 2015
Version 1.0
  • I have been doing a similar thing for years and it works well. On problem we had with the PAC file was that we made some decisions based on what the IP of the client is. Our PAC file use "var LocalIP = myIpAddress();" to get the IP but this may be unreliable. Systems that have more than one IP such as a wired and wireless or more troublesome for us were VPN connected users. Our logic would fail because sometimes the PAC file would see the Public rather than the VPN address and make the wrong decision. Our fix was to have the LTM get the address using "[IP::client_addr]" and replace the line in the PAC file using something like: when HTTP_REQUEST { Get the PAC from the iFile set response [ifile get proxy_pac] rewrite the pac file on the fly to fix problem with getting the correct IP Create a string with a command javascript command to set a var to the client IP append replacement {var LocalIP = "} [IP::client_addr] {";} Replace the command in the pac file with the new command regsub -line {var LocalIP = .*;} $response $replacement response HTTP::respond 200 content $response "Content-Type" "application/x-ns-proxy-autoconfig" }
  • how to create "a virtual address running a specific port that has no pools"?

     

  • Arie's avatar
    Arie
    Icon for Altostratus rankAltostratus

    As of v12 the iFile size limit is 32 MB (used to be 4 MB).

     

  • jk303's avatar
    jk303
    Icon for Nimbostratus rankNimbostratus

    I'd like to use the same IP/VIP to also be utilized as forward proxy on port 8080. So - user goes to to get pac file, BUT also within the pac file there will be proxy settings of .

     

    Possible? I'm hitting the 'default' event in the iRule above.

     

    Anyone has supportive iRule for forward (LTM ONLY) proxy?

     

  • Better to use the APM hosted content option, because the APM policy can check some things (ip subnet, installed software and so on) on the PC that wants the pac file but I am not a SWG expert. Also using the WPAD protocol by configuring the DHCP or DNS server, to tell the location of the PAC file could make things easy.