Transparent DNS proxy

We would like to optimise our DNS traffic. For that to work we need a transparent DNS proxy, as we cannot force the end-users to use our DNS server. There are quite a few articles to be found on setting up a transparent Squid proxy. And there is also mention of setting up a transparent DNS proxy using unbound on Linux. Reading those articles this seems to be rather straightforward.

I’ve spent quite a bit of time to set this up on FreeBSD as there were a few bugs to iron out. Those bugfixes have been submitted and accepted (isn’t Open Source Software great?).

  1. First of we need to compile unbound ourselves, at least SVN revision 3678, or use release 1.5.9 when released, as it contains fixes for using IP_BINDANY/IPV6_BINDANY (the BSD equivalent for IP_TRANSPARENT).
  2. Next we need to setup an appropriate unbound configuration. You will need to run the DNS server as user root for it to be able to use IP_BINDANY on FreeBSD. You will also need to bind to all interfaces in automatic mode for it to pick up the forwarded traffic1. Third, you need to enable the ip-transparent option.
    username: root
    interface-automatic: yes
    ip-transparent: yes
  3. Start your unbound server.
  4. Then configure ipfw to forward DNS traffic to unbound:
    /sbin/ipfw add count tag 4 ip4 from any to any
    /sbin/ipfw add count tag 6 ip6 from any to any
    
    /sbin/ipfw add fwd 127.0.0.1,53 udp from any to any 53 tagged 4 in recv $LANIFACE
    /sbin/ipfw add fwd 127.0.0.1,53 tcp from any to any 53 tagged 4 in recv $LANIFACE
    /sbin/ipfw add fwd ::1,53 udp from any to any 53 tagged 6 in recv $LANIFACE
    /sbin/ipfw add fwd ::1,53 tcp from any to any 53 tagged 6 in recv $LANIFACE

    The tagging is needed to separate the traffic between the two protocols. It could be done with skipto as well.

  5. Reload the firewall rules, and presto you should see DNS traffic on $LANIFACE being redirected to unbound. Please note that ipfw forward rules do not work on bridged traffic as bridged traffic is filtered at the ethernet level, and protocol and port numbers are not known yet. You will need to setup a router for this to work unfortunately.
  6. On 10.3 and before you will need to patch your kernel for IPV6_BINDANY to work. Otherwise unbound will fail in sendmsg() on UDP on IPv6. This is fixed in CURRENT in revision 296984.

Leave a Reply

Your email address will not be published. Required fields are marked *