pforemski/dingo

Automatic selection of closest Google servers

Opened this issue · 5 comments

...just query them for dns.google.com & use the output for further queries

dupuy commented

even better would be to query publicdns.goog and validate the DNSSEC signature...

@dupuy thanks, but I believe publicdns.goog resolves to different IPs than dns.google.com; also, I don't think we have to worry about DNSSEC validation - I'd just use the same Google Public DNS HTTPS API with a default IP address

dupuy commented

Yes, you're right about the addresses being different, I realized that a moment after posting, and was in the process of editing the comment: publicdns.goog uses the anycast 8.8.8.8 etc. addresses (which don't support DNS-over-HTTPS [yet?]); publicdns-https.goog uses a fixed address; and dns.google.com uses GeoIP load-balanced addresses (which you shouldn't use for more than the TTL, to avoid defeating the load-balancing). Really, you shouldn't use any of the non-anycast addresses for more than the TTL.

You can see the difference in geographic dispersal for the two non-anycast address names with https://www.whatsmydns.net/#A/publicdns-https.goog and https://www.whatsmydns.net/#A/dns.google.com

As for the DNSSEC validation, it's quite true that the HTTPS certificate gives pretty good confidence you are not being scammed, but there have been fake Google certificates issued in the past and there will be again, so this would require the NSA to also break or fake the root DNSSEC keys, which they probably haven't done yet (as DNSSEC isn't so popular).

Preliminary implemented in c23c3ad (in gdns.go, func Gdns.Start). Marked as closed for now, will improve later.

@dupuy thanks for suggestions, but I believe independent DNSSEC validation should be a separate ticket - feel free to contribute! :)

This is what I use right now which is more reliable across corporate networks and free hotspots:

/Users/heri/work/bin/dingo.sh

#!/bin/bash
cd "$(dirname "${BASH_SOURCE[0]}")"

digresult=$(dig @208.67.222.222 -p 443 +tcp +short dns.google.com)

if [[ "$digresult" == ";;"* ]]; then
  echo "WARNING: Cannot resolve dns.google.com, using default ip in dingo..."
  exec ./dingo -gdns:auto=true "$@"
  return
fi

# Randomly chooses dns lookup result
iplist=(${digresult}) # put to array
num=${#iplist[@]} # get number of items
rand=$((RANDOM%$num)) # generate random number
iprand=${iplist[$rand]}

echo "Using dns.google.com @ ${iprand}"
exec ./dingo -gdns:server=${iprand} -gdns:auto=true "$@"

/Library/LaunchDaemons/com.github.pforemski.dingo.plist

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
	<key>Label</key>
	<string>com.github.pforemski.dingo</string>
	<key>InitGroups</key>
	<false/>
	<key>UserName</key>
	<string>nobody</string>
	<key>GroupName</key>
	<string>_mdnsresponder</string>
	<key>ProgramArguments</key>
	<array>
		<string>/Users/heri/work/bin/dingo.sh</string>
	</array>
	<key>WatchPaths</key>
	<array>
		<string>/Library/Preferences/SystemConfiguration/NetworkInterfaces.plist</string>
		<string>/Library/Preferences/SystemConfiguration/com.apple.airport.preferences.plist</string>
	</array>
	<key>RunAtLoad</key>
	<true/>
	<key>KeepAlive</key>
	<dict>
		<key>NetworkState</key>
		<true/>
	</dict>
</dict>
</plist>

It uses port 443 tcp to lookup dns.google.com on OpenDNS, before falling back to built-in mechanism in dingo. This process is repeated each time when the Wifi interface is switched between networks or SSIDs (either manually or automatically when moving to another spot).

This setup above, along with brew install dnsmasq and server=127.0.0.1#32000 in /usr/local/etc/dnsmasq.conf, has been the most reliable for me on macOS.

Caveat: A network administrator could spoof A records of both dns.google.com and www.google.com

@pforemski : Edited daemonize scripts to latest