Automatic HTTP Proxy

This will be a 2 part post. Part 1 is setting up Squid, Nginx, DNS, and the PAC file.

Part 2 will cover redirecting requests for ports 21/80/443 to the proxy for any applications that either don’t support proxy config parameters, or that wish to misbehave.

This is all done with FreeBSD, Squid, BIND, Nginx. You could substitute other equiv. applications/OS with the same success.


  1. Create PAC file that defines proxy configuration
  2. Configuring nginx to host the pac file
  3. DNS for auto-configuration of proxy
  4. Configuring squid as a proxy
  5. Configuring the client’s browser for proxy config
  6. Ensure traffic is getting proxied properly

Proxy Auto-Configuration

Proxy Auto-Configuration is a specialized JavaScript function that the browser will call as part of determining how requests are handled.

My PAC file looks like this:

 1	function FindProxyForURL(url, host) {
 2		if (
 3			isInNet(myIpAddress(), "", "") ||
 4			isInNet(myIpAddress(), "", "") ||
 5			isInNet(myIpAddress(), "", "") ||
 6			isInNet(myIpAddress(), "", "") ||
 7			isInNet(myIpAddress(), "", "") ||
 8			shExpMatch(shExpMatch, "2607:f8b0:400e:c04::8d") ||
 9			shExpMatch(shExpMatch, "fc00:101:ca7:*")) {
10			return "DIRECT";
11		} else {
12			if (shExpMatch(url, "http:*"))
13				return "PROXY" ;
14			if (shExpMatch(url, "https:*"))
15				return "PROXY" ;
16			if (shExpMatch(url, "ftp:*"))
17				return "PROXY" ;
18			return "DIRECT";
19		}
20	}

The top defines a list of IP ranges (I’ve included both IPv4 and IPv6) that should be excluded from the proxy. You should edit this as appropriate. The bottom portion defines 3 different types of URL we want to proxy, and where to direct each one. These can be all hosted on the same system, or on different systems. When you’re done editing this, save it as ‘proxy.pac’.

Configuring Nginx

Install the pkg (or the port). Edit /usr/local/etc/nginx/mime.types Add the following lines under ’types {'

1	application/x-ns-proxy-autoconfig .pac
2	application/x-ns-proxy-autoconfig .dat

Ensure you don’t have additional entries for these types anywhere else in the file. If its the default file (you haven’t made changes to it), these types were not in, as of the date of this post.

By default (on FreeBSD), nginx defaults to looking for content in /usr/local/www/nginx/. Place your ‘proxy.pac’ file here. Make a sym link to it as ‘wpad.dat’.

1cd /usr/local/www/nginx/
2ln -s proxy.pac wpad.dat

Edit /etc/rc.conf and enable nginx:


Start nginx: ‘service nginx start’ You should be able to retrieve the file with ‘http://proxy.server/proxy.pac


Create A (and AAAA records if you use IPv6) record for wpad.domain.tld This needs to point to the same place as proxy.server used above.


The changes to the default configuration were limited to 3 lines:

1acl localnet src
2http_port 3128
3https_port 3130 transparent cert=/usr/local/etc/squid/proxy.cmhome.cert key=/usr/local/etc/squid/proxy.cmhome.key

Testing the proxy


1tail -F /var/log/squid/access.log /var/log/nginx-access.log

You should see entries like:

1192.168.11.11 - - [18/Jul/2014:22:50:38 +0000] "GET /wpad.dat HTTP/1.1" 200 921 "-" " CFNetwork/673.3 Darwin/13.3.0 (x86_64) (MacPro3%2C1)" 1405627253.231 1177 fc00:101:ca7:11::11 TCP_MISS/200 671 GET - HIER_DIRECT/ text/html

Client Configuration

Here are some screenshots for setting the system wide proxy on a mac, as well as the proxy settings for firefox.