How can I force default DNS query to work in TCP mode?

Solution 1:

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):

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
    <plist version="1.0">
    <dict>
        <key>Label</key>
        <string>local.dnschef</string>
        <key>ProgramArguments</key>
        <array>
            <string>/usr/local/python/dnschef.py</string>
            <string>--nameservers</string>
            <string>8.8.8.8#53#tcp</string>
        </array>
        <key>RunAtLoad</key>
        <true/>
    </dict>
    </plist>
    
  • Load the file with sudo launchctl load -w /Library/LaunchDaemons/local.dnschef.plist

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