đ Proxy Auto-Configuration (PAC)
â Wikipedia
The âSmartâ Routing Script
While static system proxies are simple (everything goes to one IP), they lack nuance. In a real-world network, you donât want to send traffic to your internal printer or a local dev server through a remote Rama proxy. You need a way to say: âProxy the internet, but stay direct for the office.â
This is exactly what a PAC file does. It is a single JavaScript file containing a function called FindProxyForURL(url, host). Every time your browser wants to load a resource, it runs this function to get instructions.
The client passes two arguments to this function:
- url: The full destination URL (e.g.,
https://example.com:8443/foo/bar?baz=1). - host: The host component extracted from the URL (e.g.,
example.com).
The function returns a string instructing the client on how to proceed:
DIRECT: Connect to the destination server directly, bypassing the proxy.PROXY host:port: Connect via the specified HTTP proxy.
Note
While some clients support
SOCKS,HTTPS, orSOCKS5directives,PROXYandDIRECTare the most universally compatible across all platforms and browsers.Unless you really need to and know for sure it is supported it is best to only use the
PROXYandDIRECTdirectives.
You can return multiple options separated by a semicolon (;). The client will attempt them in order.
Script Example
The power of PAC lies in its simplicity. It provides a set of helper functions that allow you to make decisions based on the destination.
function FindProxyForURL(url, host) {
// 1. Stay direct for local hostnames
if (isPlainHostName(host) || dnsDomainIs(host, ".local")) {
return "DIRECT";
}
// 2. Stay direct for the internal corporate network
if (isInNet(dnsResolve(host), "10.0.0.0", "255.0.0.0")) {
return "DIRECT";
}
// 3. Send everything else to our Rama proxy
// If the proxy is down, the browser will try to go DIRECT as a backup
return "PROXY proxy.rama.internal:8080; DIRECT";
}
Key PAC Functions:
isPlainHostName(host): True if there are no dots in the hostname (e.g.,http://intranet).dnsDomainIs(host, ".com"): Allows for domain-specific routing.isInNet(ip, pattern, mask): Allows for IP-range based routing.shExpMatch(str, shellExpression): Pattern matching for URLs using shell-style wildcards.
Distribution: How Browsers Find the File
A PAC file isnât much use if the client doesnât know where it is. There are two primary ways to distribute a PAC script:
- Manual URL: You enter the address (e.g.,
http://config.rama.internal/proxy.pac) into the System Proxy settings. - WPAD (Web Proxy Auto-Discovery): This is the âzero-configâ method. The browser uses DNS or DHCP to look for a server named
wpad. It then tries to downloadhttp://wpad/wpad.dat. While convenient, WPAD has significant security risks (like DNS poisoning), which is why many modern environments prefer manual URLs or MDM-pushed configs.
Learn more about WPAD at https://en.wikipedia.org/wiki/Web_Proxy_Auto-Discovery_Protocol.
System proxy settings is the more common way to use PAC.
The Limitations of PAC
As flexible as PAC files are, they share the same weakness as all System Proxies: Application Compliance.
A PAC file is a suggestion, not a law. Furthermore, because PAC relies on JavaScript, many non-browser applications (like low-level CLI tools or embedded devices) donât have a JavaScript engine to run the script. For those âblindâ applications, the PAC settings are essentially invisible.
Rama Support
TOOD⌠in progress
More Resources
- MDN: Proxy Auto-Configuration: Excellent documentation on built-in helper functions (like
shExpMatch). Note: These functions can be slow; Safechain often uses optimized custom logic instead. - Cloudflare: PAC Best Practices: Modern performance tips.
- Microsoft: WinHTTP IPv6 Extensions: Information on
FindProxyForURLEx, used specifically by Win32 applications for IPv6 support (useful only if you need to take advantage of builtin Ipv6 utilities and only supported for windows applications running the Win32 stack).