Linux – force LAN hosts to go through proxy

debianfirewalliptableslinuxPROXY

I have an IPTables firewall on a Debian server, with a bunch of hosts behind it with masquerading. In the upstream network I don't have direct access to the internet, and I need to go through a proxy server to get to web sites.

I want the hosts behind my firewall to automatically go through the proxy server without each host needing to set up proxy on their own (mostly because I want to be able to change the proxy address in a single point, because I have different proxies for different network scenarios).

Is there a way to have IPTables force all outgoing traffic on port 80 and 443 to go through the proxy? If not, can I use some other readily available software to get the behavior I need?

Best Answer

There are at least two ways of doing this:

  1. Proxy auto-configuration URL via DHCP
  2. Transparent proxy redirection with iptables

The first option uses WPAD mechanism:

In your DHCP server config, you must include option 252 (e.g. for dhcpd):

option local-proxy-config code 252 = text;
...
subnet 192.168.0.0 netmask 255.255.255.0 {
  range 192.168.0.20 192.168.0.30;
  ...
  option local-proxy-config "http://your_http_server/proxy.pac";
}

Your proxy.pac is just a bit of JS which tells the browser what to proxy (e.g.):

function FindProxyForURL(url, host) {
    var proxy = "PROXY your_proxy_server:3128; DIRECT";
    var direct = "DIRECT";

    // no proxy for local hosts without domain:
    if(isPlainHostName(host)) return direct;

    // proxy everything else:
    return proxy;
}

The second option is to use iptables to redirect http traffic transparently (e.g.):

iptables -t nat -A PREROUTING -i eth0 -s ! your_proxy_server -p tcp --dport 80 -j DNAT --to your_proxy_server:3128
iptables -t nat -A POSTROUTING -o eth0 -s local-network -d your_proxy_server -j SNAT --to iptables-box
iptables -A FORWARD -s local-network -d your_proxy_server -i eth0 -o eth0 -p tcp --dport 3128 -j ACCEPT