title: PF, load balanced gateways, and Squid
body: <p>So I have a FreeBSD router running PF and Squid, and it has three network interfaces: two connected to upstream providers (<code>em0</code> and <code>em1</code> respectively), and one for LAN (<code>re0</code>) that we serve. There is some load balancing configured with PF. Basically, it routes all traffic to ports <code>1-1024</code> through one interface (<code>em0</code>) and everything else through the other (<code>em1</code>).</p>
  
  <p>Now, I have a Squid proxy also running on the box that transparently redirects any HTTP request from LAN to port <code>3128</code> in <code>127.0.0.1</code>. Since Squid redirects this request to HTTP outside, it should follow the load balancing rule through <code>em0</code>, no? The problem is, when we tested it out (by browsing from a computer in the LAN to <a href="http://whatismyip.com" rel="nofollow noreferrer">http://whatismyip.com</a>, it reports the external IP of the <code>em1</code> interface! When we turn Squid off, the external IP of <code>em0</code> is reported, as expected.</p>
  
  <p>How do I make Squid behave with the load balancing rule that we have set up?</p>
  
  <p>Here's the related settings in <code>/etc/pf.conf</code> that I have:</p>
  
  <pre><code>ext_if1="em1"   # DSL
  ext_if2="em0"   # T1
  int_if="re0"
  
  ext_gw1="x.x.x.1"
  ext_gw2="y.y.y.1"
  
  int_addr="10.0.0.1"
  int_net="10.0.0.0/16"
  
  dsl_ports = "1024:65535"
  t1_ports = "1:1023"
  
  ...
  
  squid=3128
  rdr on $int_if inet proto tcp from $int_net \
          to any port 80 -&gt; 127.0.0.1 port $squid
  pass in quick on $int_if route-to lo0 inet proto tcp \
          from $int_net to 127.0.0.1 port $squid keep state
  
  ...
  
  # load balancing
  pass in on $int_if route-to ($ext_if1 $ext_gw1) \
          proto tcp from $int_net to any port $dsl_ports keep state
  pass in on $int_if route-to ($ext_if1 $ext_gw1) \
          proto udp from $int_net to any port $dsl_ports
  
  pass in on $int_if route-to ($ext_if2 $ext_gw2) \
          proto tcp from $int_net to any port $t1_ports keep state
  pass in on $int_if route-to ($ext_if2 $ext_gw2) \
          proto udp from $int_net to any port $t1_ports
  
  pass out on $ext_if1 route-to ($ext_if2 $ext_gw2) from $ext_if2 to any
  pass out on $ext_if2 route-to ($ext_if1 $ext_gw1) from $ext_if1 to any
  </code></pre>
  
  <p>I have tried appending the following rule, but it did nothing:</p>
  
  <pre><code>pass in on $int_if route-to ($ext_if2 $ext_gw2) \
          proto tcp from 127.0.0.1 to any port $t1_ports keep state
  </code></pre>
  
  <p>Thanks!</p>