How to make Firefox use TCP for DNS

I want to use TCP for DNS, to bypass my ISP's slow and broken DNS servers. I'm not using (and don't want to use) a proxy.

Note: I want to use DNS over TCP because if I use it over udp, no matter what server I set, I get answers from my ISP's DNS.

Notice that I will fiercely downvote whoever suggests:

  • programs to do TCP over DNS,
  • the setting in about:config to make DNS go over the proxy too: I'm not using a proxy,
  • use another DNS: I've already set up Google as my DNS, but I get intercepted.

Example of what I mean by saying intercept:

$ dig @8.8.8.8 thepiratebay.se

; <<>> DiG 9.8.1 <<>> @8.8.8.8 thepiratebay.se
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 24385
;; flags: qr aa rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0

;; QUESTION SECTION:
;thepiratebay.se.               IN      A

;; ANSWER SECTION:
thepiratebay.se.        28800   IN      A       83.224.65.41

;; Query time: 50 msec
;; SERVER: 8.8.8.8#53(8.8.8.8)
;; WHEN: Sun Sep 16 22:51:06 2012
;; MSG SIZE  rcvd: 49

$ dig +tcp @8.8.8.8 thepiratebay.se

; <<>> DiG 9.8.1 <<>> +tcp @8.8.8.8 thepiratebay.se
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 15131
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0

;; QUESTION SECTION:
;thepiratebay.se.               IN      A

;; ANSWER SECTION:
thepiratebay.se.        436     IN      A       194.71.107.15

;; Query time: 61 msec
;; SERVER: 8.8.8.8#53(8.8.8.8)
;; WHEN: Sun Sep 16 22:51:10 2012
;; MSG SIZE  rcvd: 49

If it matters, I'm using Firefox 14 on Gentoo Linux.


Solution 1:

If you are using glibc you can use the undocumented use-vc option (see resolv/res_init.c in the glib source code) which forces the libc resolver to always use TCP.

Either set it globally in resolv.conf:

options use-vc nameserver 1.2.3.4

Or pass the option in the environment:

RES_OPTIONS=use-vc firefox

It will not work if the application implemented its own support for DNS without using the libc res_init/res_query/… functions. It's working with Firefox (probably as long as you are not using the "remote DNS" option in the SOCKS proxy settings).

Solution 2:

Install Unbound, and just change "tcp-upstream: no" to "yes" in the unbound.conf config file.

# upstream connections use TCP only (and no UDP), "yes" or "no"
# useful for tunneling scenarios, default no.
# tcp-upstream: no

And in order to resolver everything through an upstream resolver, add something like:

forward-zone:
    name: "."
    forward-addr: 213.154.224.3

You can also use dnssec-trigger, a convenient user interface for Unbound, that configures it to tunnel everything through an SSL connection.

Solution 3:

One way to get round the ISP issue is to run your own, local, DNS server. This isn't especially difficult on Linux.

There is a previous, related question that covers some of the relevant points: What to do when an ISP intercepts NXDOMAIN requests? And another article here.

DNSsec (WikiPedia) should remove this problem in the long term. Also DNSCrypt from OpenDNS fixes the issue but only for Mac and Windows workstations.

There are a number of good articles on setting up your own DNS:

  • Ubuntu
  • Redhat
  • Debian

Solution 4:

make Firefox use TCP for DNS?

You can't

Firefox doesn't make that decision, it just calls an operating system API like gethostbyname()

The operating system resolver hands that off to a DNS server.

You might think you could set up your own internal DNS server and configure that to only use TCP.

Here's a relevant post from someone who probably knows more about DNS than anyone else.

08-11-2008 03:20 AM

Re: Is it possible to force BIND to use TCP exclusively?

"Joe Baptista" writes:

Are there any configuration changes that can be made to BIND to force it to use TCP exclusively and never use UDP? Possible?

no.

--
Paul Vixie

Probably anyway

In theory you can find, write or modify a DNS forwarder that does what you want.

In theory you may be able to find or write a Firefox plugin that intercepts and replaces any calls to gethostbyname() with custom DNS client code - I've no idea if the Firefox plugin architecture makes this possible but it might be worth a look.