Had to work on one of these for a client, and decided that while there’s a whole host of documentation out there, there aren’t a lot of good working examples of how to use the proxy auto config functions properly in a complex file.
Since I spent the better part of 8 hours getting something that works properly in the environment (including site blocking to a custom server), I figured I’d share it with the users of this series of tubes in the hope it helps someone.
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // // NAME: proxy.pac // // Original: http://www.cluberti.com/blog // Last Update: 14th May 2010 // // Comment: Proxy.pac example file for use as an auto configuration script // template. // // NOTE: Provided as-is - usage of this source assumes that you are at the // very least familiar with the javascript language being used and // the tools used to create and debug this file. // // In other words, if you break it, you get to keep the pieces. // // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // javascript:alert ("Using PAC file"); // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Start of the PAC file - function FindProxyForUrl: function FindProxyForURL(url, host) { // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Set proxy values as strings to use during return // NOTE that if a rule directs the browser to return proxy_block, in this example // the browser should attempt to visit http://internalserver:80, and will display // the default web site at that location. var proxy_primary = "PROXY proxy.primary.internal.domain.com:80"; var proxy_secondary = "PROXY proxy.secondary.internal.domain.com:80"; var proxy_testing = "PROXY proxy.testing.internal.domain.com:80"; var proxy_block = "PROXY internalserver:80"; //<- useful for blocking sites var proxy_no = "DIRECT"; // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Some proxies may have issues with mixed-case URLs, so change host variable to // all lower case, and resolve the host IP to reduce DNS lookups later: host = host.toLowerCase(); var resolved_IP = dnsResolve(host); // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Master blocked sites list // NOTE: Add all sies you wish to redirect to proxy_block here: // if destination is .someblockeddomain.com, return proxy_block: if (dnsDomainIs(host, ".someblockeddomain.com")) { return proxy_block; } // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // If URL has no dots in host name, send traffic direct. if (isPlainHostName(host)) { return proxy_no; } // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Master proxy bypass list // NOTE: Add all other proxy bypass entries into this section: // If destination is to an RFC 1918 IP, return direct: if (isInNet(resolved_IP, "10.0.0.0", "255.0.0.0") || isInNet(resolved_IP, "172.16.0.0", "255.240.0.0") || isInNet(resolved_IP, "192.168.0.0", "255.255.0.0") || isInNet(resolved_IP, "127.0.0.0", "255.255.255.0")) { return proxy_no; } // If request matches certain hosts in our IP range, return direct: if (isInNet(resolved_IP, "11.11.11.11", "255.0.0.0") || isInNet(resolved_IP, "11.11.11.12", "255.0.0.0")) { return proxy_no; } If request begins with "xww", return direct: if (shExpMatch(host, "xww.*")) { return proxy_no; } // If request matches for *.internal.ourdomain.com/.net/.org, return direct: if (shExpMatch(host, "*.internal.ourdomain.com") || shExpMatch(host, "*.internal.ourdomain.net") || shExpMatch(host, "*.internal.ourdomain.org")) { return proxy_no; } // If request resolves to .external/.testing.ourdomain.com, return direct: if (dnsDomainIs(host, ".external.ourdomain.com") || dnsDomainIs(host, ".testing.ourdomain.com")) { return proxy_no; } // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Hosts/domains to proxy // NOTE: Add all hosts/domains that should go through the proxy into this section: // If request is for *.ourdomain.com and we've gotten this far, further // parsing is required: if (shExpMatch(host, "*.ourdomain.com")) { // If request is for .us.ourdomain.com, use primary proxy: if (dnsDomainIs(host, ".us.ourdomain.com")) { return proxy_primary; } // If request is for .world.ourdomain.com, use secondary proxy: if (dnsDomainIs(host, ".world.ourdomain.com")) { return proxy_secondary; } } // If browsing to *.microsoft.com, further parsing is required: if (shExpMatch(host, "*.microsoft.com")) { // If request is specifically for www.microsoft.com, try the secondary // proxy first: if (localHostOrDomainIs(host, "www.microsoft.com")) { return proxy_secondary + "; " + proxy_primary ; } // Otherwise, try the primary proxy first to other microsoft sites: if (dnsDomainIs(host, ".microsoft.com")) { return proxy_primary + "; " + proxy_secondary ; } } // If browsing to *.someotherdomain.com, further parsing is required: if (shExpMatch(host, "*.someotherdomain.com")) { // 172.16.0.0/255.255.0.0 IP address block -- try primary proxy first: if (isInNet(myIpAddress(), "172.16.0.0", "255.255.0.0")) { return proxy_primary + "; " + proxy_secondary ; } // 172.31.0.0/255.255.0.0 IP address block -- try secondary proxy first: if (isInNet(myIpAddress(), "172.31.0.0", "255.255.0.0")) { return proxy_secondary + "; " + proxy_primary ; } } // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Advanced proxying based on computer IP Address via the myIpAddress() function // NOTE: Add all IP Address ranges you wish to proxy for in this section: // If the computer's IP address is in the 172.16.0.0/255.255.0.0 range, use // the the primary proxy Monday through Friday: if (isInNet(myIpAddress(), "172.16.0.0", "255.255.0.0")) { if (weekdayRange("MON", "FRI")) { return proxy_primary; } // If this check is done on Saturday or Sunday, this will fall through and // parsing will continue. } // If the computer's IP address is in the 172.31.0.0/255.255.0.0 range, use // the secondary proxy from January to June, and September to December: if (isInNet(myIpAddress(), "172.31.0.0", "255.255.0.0")) { if (dateRange("JAN", "JUN")) { return proxy_secondary; } if (dateRange("SEP", "DEC")) { return proxy_secondary; } // If this check is done in July or August, this will fall through and parsing // will continue. } // If the computer's IP address is in the 192.168.0.0/255.255.0.0 range, use // the testing proxy from 8AM to 6PM local time: if (isInNet(myIpAddress(), "192.168.0.0", "255.255.0.0")) { if (timeRange(8, 18)) { return proxy_testing; } // If this check is done before 8AM or after 6PM, this will fall through and // parsing will continue. } // If the computer's IP address is in the 10.0.0.0/255.0.0.0 range, use the // testing proxy: if (isInNet(myIpAddress(), "10.0.0.0", "255.0.0.0")) { return proxy_testing; } // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Default return direct rule // If the request matches no other parsing rules, return direct: else // javascript:alert ("PAC finished parsing for: " + host + "\nFrom IP: " + myIpAddress() + "\nReturning: " + proxy_no); return proxy_no; }