How can I force default DNS query to work in TCP mode? In China, the so-called GFW often contaminates DNS results like

$ dig @8.8.8.8 archive.org 

;; QUESTION SECTION:
;archive.org.           IN  A

;; ANSWER SECTION:
archive.org.        2662    IN  A   159.106.121.75


Here 159.106.121.75 is a fake IP. We have to use the TCP mode for DNS query:

$ dig @8.8.8.8 +tcp archive.org

;; QUESTION SECTION:
;archive.org.           IN  A

;; ANSWER SECTION:
archive.org.        237 IN  A   207.241.224.2


Now we get the real IP 207.241.224.2.

In System Preferences -> Network, the Advanced... button can open a tab for setting DNS. However, I can only add the IP addresses of DNS servers but cannot do anything else. So my question is: how can I force the default DNS query working in the TCP mode?

PS: I don't want to modify the /etc/hosts file to circumvent this problem as it's inconvenient. If there's any elegant method that can solve this problem, it will save me much time :) Thanks.
AFAIK it's not possible to force the mDNSResponder to use TCP instead of UDP.

I've found a workaround though. The method outlined below uses a local DNS-proxy (dnschef) forced to use TCP for outgoing DNS-requests.


Download and unzip dnschef-0.3.
Download and unzip dnslib
Download and unarchive IPy-0.76
cd to the dnslib folder: 

cd ~/Downloads/paulc-dnslib-04713cc4a9df 

install dnslib:

sudo python ./setup.py install

cd to the IPy folder: 

cd ~/Downloads/IPy-0.76 

install IPy:

sudo python ./setup.py install

Open System Preferences -> Network, replace your current DNS-server(s) (e.g. 8.8.8.8/8.8.8.4) by a local one with the IP 127.0.0.1 and apply the changes.
cd to the dnschef folder and start it:

cd ~/Downloads/dnschef-0.3 
sudo ./dnschef.py --nameservers 8.8.8.8#53#tcp



If the last command is too troublesome or ugly (well, it is ugly because you have to open Terminal.app and start the DNS-proxy), you can move the dnschef.py and .ini to another path and create a launch daemon to start the DNS-proxy while booting.

Example:


sudo mkdir /usr/local/python
sudo cp ~/Downloads/dnschef-0.3/dns* /usr/local/python/
sudo rm /usr/local/python/dnschef.exe
sudo touch /Library/LaunchDaemon/local.dnschef.plist
copy and paste the following content into the newly created file with an appropriate editor
(e.g sudo nano /Library/LaunchDaemon/local.dnschef.plist):

&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"&gt;
&lt;plist version="1.0"&gt;
&lt;dict&gt;
    &lt;key&gt;Label&lt;/key&gt;
    &lt;string&gt;local.dnschef&lt;/string&gt;
    &lt;key&gt;ProgramArguments&lt;/key&gt;
    &lt;array&gt;
        &lt;string&gt;/usr/local/python/dnschef.py&lt;/string&gt;
        &lt;string&gt;--nameservers&lt;/string&gt;
        &lt;string&gt;8.8.8.8#53#tcp&lt;/string&gt;
    &lt;/array&gt;
    &lt;key&gt;RunAtLoad&lt;/key&gt;
    &lt;true/&gt;
&lt;/dict&gt;
&lt;/plist&gt;

Load the file with sudo launchctl load -w /Library/LaunchDaemons/local.dnschef.plist

All files and folders created must be owned by root:wheel.