Skip to content
CHEF-KOCH edited this page Aug 17, 2015 · 34 revisions

Index

Description

DNS primarily uses User Datagram Protocol (UDP) on port number 53 to serve the requests, TCP (Transmission Control Protocol) is only in usage if data size exceeds >512 bytes or for special tasks, some resolvers implementing an TCP for all queries option (mostly optional by default).

DNS is known as not to be secure anymore for several reasons. Like most "secure" communications protocols, it is susceptible to undetectable public-key substitution MITM-attacks an populate examples was the Apple iMessages security problem.

The main problem is the protocol insecurity by DNS and X.509. See also Certificate Transparency.

The core problems are:

  • MITM (Man-In-The-Middle)
  • DNS-based censorship circumvention
  • Domain theft's ("seizures")
  • Certificate revocation
  • DOS (Denial-Of-Service) attacks, even DNSSEC doesn't protect against this
  • Logging on exit notes
  • DNS cache poisoning
  • Other exploits that are used for e.g. phishing
  • DNS hijacking
  • ...

Blocking the DNS (port 53) isn't possible (without problems) since this is necessary on Android/Windows/Linux/Mac OS or any other OS, but we simply can use secure and proofed alternatives. - Which is more or less complicated and depending on your knowledge about how to change that. But don't worry we are here to explain all stuff in easy steps!

There are alternatives like:

  • Choosing a logging free DNS resolver e.g OpenNIC
  • DNSSEC / DNS-based Authentication of Named Entities (DANE)
  • OpenDNS (or other providers which claiming to not log/censorship anything)
  • DNSCrypt / TCPCrypt (DNSCrypt will be a part of the final CM 12.1)
  • TACK / HPKP implementations within the apps

But even with such popular alternatives there are several problems, e.g. DNSSEC suffering from miscellaneous leaks mentioned over here or here + it doesn't prevent MITM attacks.

DNS under Android

Android use a a dynamic DNS (DDNS) by default, which updates the DNS every time when the IP address changes ISP <-> wifi.

By default the Google DNS server (since 2009) is set (8.8.8.8/8.8.4.4), currently the DNS servers gets overridden after each reboot even with setprop. Googles public DNS supports DNSSEC validation since 2013 by default unless you do not want this (via opt-out), which means that this server is secured and nothing speaks against using it (except the anti-Google paranoia of course).

// IP change or reconnection (connectivity changes -> RIL via e.g. ndc resolver setifdns rmnet0 x.x.x.x y.y.y.y).

How can I gather DNS (A/AAA/...) requests?

All AOSP based ROMs coming with TCPdump as binary included, so we can just use this to show what's going on behind, there are several Tutorials and documents available to handling TCPdump. If this is to complicated for you, you can just grab AdAway (needs root) and use there own TCPDump/dnsmasq/libpcap interface to list all requests - it also provides an interface to add them to your hosts or to an separate white-/blacklist.

// Android use a kind of BIND (which includes "dig"). dig github.com | grep "Query time" // See, #37668 // Workaround, just use external apps like DNS Lookup

resolv.conf

The configuration file for DNS resolvers is /etc/resolv.conf take a look at the man page.

Allows a maximum of three nameserver lines. In order to overcome this limitation, you can use a locally caching nameserver like dnsmasq (see below). Changes made to /etc/resolv.conf take effect immediately (needs confirmation?).

dnsmasq

Dnsmasq provides services as a DNS forwarder cacher and a DHCP server. As a Domain Name Server (DNS) it can cache DNS queries to improve connection speeds to previously visited sites, and as a DHCP server dnsmasq can be used to provide internal IP addresses and routes to computers on a LAN. A list for discussion about the dnsmasq DNS and DHCP server, configuration, bugs and development can be found here.

❗ dnsmasq only allows three nameservers as a workaround we can create resolv.dnsmasq.conf and add this list into our /etc/dnsmasq.conf -> resolv-file=/etc/resolv.dnsmasq.conf

// listen-address=127.0.0.1 needs to be set for local DNS cache ... because DNSCrypt isn't an DNS Cache (so we use dnsmasq) // Empty example dnsmasq // start it via service dhcpsrv /system/bin/logwrapper /system/bin/dnsmasq -k -C /system/etc/dnsmasq.conf // Behind a firewall (like AFWall+) try: iptables -A INPUT -i $iface -p udp -s 0.0.0.0 --sport 68 -d 255.255.255.255 --dport 67 -j ACCEPT if the firewall precenting dnsmasq from working as LAN DHCP server

DNSCrypt

DNSCrypt encrypts and authenticates DNS traffic between user and DNS resolver, the latest flashable .zip for Android is available over here. When DNSCrypt is enabled, dnscrypt-proxy accepts incoming requests on 127.0.0.1:53 to one chosen DNS resolver. Compatible resolver names are visible under /etc/dnscrypt-proxy/dnscrypt-resolvers.csv (always latest dnscrypt-resolvers.csv).

// Unbound, dnsmasq (Android default) or pdnsd are working with DNSCrypt but may needs configuration changes to work proper together

// Ensure that DNSCrypt is running
dnscrypt-proxy enable
dnscrypt-proxy disable
ps w | grep dnscrypt
// An example could be looks like this, the .zip package normally contains an init.d but this is just in case
# DNSCrypt copy & paste example config for init.d
dnscrypt-proxy \
  --resolver-name=<INSERT-YOUR-DNS-RESOLVER-NAME-HER> \
  --resolvers-list=/system/etc/dnscrypt-proxy/dnscrypt-resolvers.csv \
  --provider-key=<OPTIONAL-ONLY-NESSARY-IF YOU-ARE-NOT-USING-ONE-FROM-the-resolvers.csv-list!> \
  --provider-name=<OPTIONAL-ONLY-NESSARY-IF YOU-ARE-NOT-USING-ONE-FROM-the-resolvers.csv-list!>  \
  --resolver-address=<OPTIONAL-IF-THIS-is-different!> \
  --max-active-requests=150 \
  --ephemeral-keys \ 
  --edns-payload-size=4096 \
  --test=3600 \
  --daemonize \
  --loglevel=3

// All other command-line switches can be found on the official homepage and of course within the documents. 

How do I know if my applications are leaking DNS?

There are several ways, the most easiest way is to visit some web pages that automatically detect what is your current DNS, like:

If you Browser shows a wrong DNS according to what your own settings telling you, this usually means something is wrong or maybe compromised.

Per-Browser this must be set to get a correct behavior, because they using there own DNS internal settings:

  • On Firefox Mobile (about:config): network.dns.disablePrefetch needs to be set to true.

On the OS level:

  • Use 3rd Party Local DNS Servers/Resolvers, here.
  • Apply Windows Tweak and Registry Hacks, here - on non servers max 4 hours is enough.
  • Apply MacOS Tweaks, here.
  • Configure Firewall as Fail-safe To Prevent Leaks, here
  • Generally use secure alternatives + use a online browser check
  • Use always the latest software to ensure possible bugs and security holes are fixed tools like sumo
  • Use a secure, user/privacy friendly search engine like DuckDuck, Disconnect or Ixquick. Even better would be an decentralized search like YaCy, FAROO or any other based on P2P/...
  • Verify no external addons/software/app leaks something (speaking about external metadata and protocol headers from going in .plaintxt out!)

On Tor:

  • Read the Advanced Tor usage FAQ section, the two important ones are this and this

Sometimes these messages may be false alarms. To find out, you should run a packet sniffer on your network interface. The basic command to do this is tcpdump -pni eth0 'port domain'.

If you are using an VPN this also can "fix" the DNS problem, but sometimes even this isn't enough, especially on Android and OpenVPN, some older versions and provider still suffering from this issue, a workaround can be found over here.

Another possible problem is that you ISP mitm and manipulate the DNS traffic (mostly due censorship or to spoof)! There are only a few methods to bypass this:

  • Use TOR + setup it (simply use the setup wizard if you don't know how)
  • Use a SSH tunnel
  • Choose an VPN which doesn't censorship
  • Use JonDo (the proxy) [but browser is also good]
  • Use DNSCrypt or httpsdnsd (HTTPSDNS daemon is already running if you use JonDo)
  • For general implementation info about DNS Transport over TCP take a look at here

There are also several tips, tricks and guides directly with a lot of examples over the official Tor Wiki page, see here & here. Remember that the given tricks on this pages are optimized for TOR/I2P, so you may need to adjust some example configuration given from there.

DNS problems

An easy method to look at opened or closed threads is to search via is:issue is:open dns / is:issue is:closed dns which shows the important threads (if the topic/thread content was correct labaled), alternative just click on the follow links (or copy/paste the issue number in the search e.g. https://github.com/ukanth/afwall/issues/.

Already reported DNS related topics:

Important: Please always use the search function here on AFWall's/AOSP issue tracker to search already known existent problems to avoid duplicate threads.

Resolver commands

Android 4.0.4

http://androidxref.com/4.0.4/xref/system/netd/CommandListener.cpp#778

  • ndc resolver setdefaultif <iface>
  • ndc resolver setifdns <iface> <dns1> <dns2> ...
  • ndc resolver flushdefaultif
  • ndc resolver flushif <iface>

Android 4.1.1

http://androidxref.com/4.1.1/xref/system/netd/CommandListener.cpp#803

  • ndc resolver setdefaultif <iface>
  • ndc resolver setifdns <iface> <dns1> <dns2> ...
  • ndc resolver flushdefaultif
  • ndc resolver flushif <iface>

Android 4.2_r1

http://androidxref.com/4.2_r1/xref/system/netd/CommandListener.cpp#873

  • ndc resolver setdefaultif <iface>
  • ndc resolver setifdns <iface> <dns1> <dns2> ...
  • ndc resolver flushdefaultif
  • ndc resolver flushif <iface>

Android 4.3_r2.1

http://androidxref.com/4.3_r2.1/xref/system/netd/CommandListener.cpp#770

  • ndc resolver setdefaultif <iface>
  • ndc resolver setifdns <iface> <domains> <dns1> <dns2> ...
  • ndc resolver flushdefaultif
  • ndc resolver flushif <iface>
  • ndc resolver setifaceforpid <iface> <pid>
  • ndc resolver clearifaceforpid <pid>

Android 4.4_r1

http://androidxref.com/4.4_r1/xref/system/netd/CommandListener.cpp#941

  • ndc resolver setdefaultif <iface>
  • ndc resolver setifdns <iface> <domains> <dns1> <dns2> ...
  • ndc resolver flushdefaultif
  • ndc resolver flushif <iface>
  • ndc resolver setifaceforpid <iface> <pid>
  • ndc resolver clearifaceforpid <pid>
  • ndc resolver setifaceforuid <iface> <l> <h>
  • ndc resolver clearifaceforuid <l> <h>
  • ndc resolver clearifacemapping

Android 4.4.2_r1

http://androidxref.com/4.4.2_r1/xref/system/netd/CommandListener.cpp#942

  • ndc resolver setdefaultif <iface>
  • ndc resolver setifdns <iface> <domains> <dns1> <dns2> ...
  • ndc resolver flushdefaultif
  • ndc resolver flushif <iface>
  • ndc resolver setifaceforpid <iface> <pid>
  • ndc resolver clearifaceforpid <pid>
  • ndc resolver setifaceforuidrange <iface> <l> <h>
  • ndc resolver clearifaceforuidrange <l> <h>
  • ndc resolver clearifacemapping

Android 4.4.3_r1.1

http://androidxref.com/4.4.3_r1.1/xref/system/netd/CommandListener.cpp#940

  • ndc resolver setdefaultif <iface>
  • ndc resolver setifdns <iface> <domains> <dns1> <dns2> ...
  • ndc resolver flushdefaultif
  • ndc resolver flushif <iface>
  • ndc resolver setifaceforpid <iface> <pid>
  • ndc resolver clearifaceforpid <pid>
  • ndc resolver setifaceforuidrange <iface> <l> <h>
  • ndc resolver clearifaceforuidrange <if> <l> <h>
  • ndc resolver clearifacemapping

Android 4.4.4_r1

http://androidxref.com/4.4.4_r1/xref/system/netd/CommandListener.cpp#940

  • ndc resolver setdefaultif <iface>
  • ndc resolver setifdns <iface> <domains> <dns1> <dns2> ...
  • ndc resolver flushdefaultif
  • ndc resolver flushif <iface>
  • ndc resolver setifaceforpid <iface> <pid>
  • ndc resolver clearifaceforpid <pid>
  • ndc resolver setifaceforuid <iface> <l> <h>
  • ndc resolver clearifaceforuid <if> <l> <h>
  • ndc resolver clearifacemapping

Android 5.0.0_r2

http://androidxref.com/5.0.0_r2/xref/system/netd/server/CommandListener.cpp#776

  • ndc resolver setnetdns <netId> <domains> <dns1> <dns2> ...
  • ndc resolver flushnet <netId>

Android 5.1.0_r1

http://androidxref.com/5.1.0_r1/xref/system/netd/server/CommandListener.cpp#791

  • ndc resolver setnetdns <netId> <domains> <dns1> <dns2> ...
  • ndc resolver clearnetdns <netId>
  • ndc resolver flushnet <netId>

Master tree (latest versions 08.07.2015 checked)

  • ndc resolver setnetdns <netId> <domains> <dns1> <dns2> ...
  • ndc resolver clearnetdns <netId>
  • ndc resolver flushnet <netId>

Changing the default DNS

On Android < 4.3 we can use the command getprop | grep dns to know all the DNS properties being used. This command requires BusyBox!

'rmnet0’ is the interface name for the 3G connection. net.rmnet0.dns1 and net.rmnet0.dns2 are the properties to be changed to point to OpenDNS server (the settings are still present in CM/AOSP code). Since, these properties are changed after the connection is established, net.dns1 and net.dns2 also have to be changed. Execute these commands as root user: setprop net.rmnet0.dns1 208.67.222.222. setprop net.rmnet0.dns2 208.67.220.220. setprop net.dns1 208.67.222.222. setprop net.dns2 208.67.220.220.

Remember, the settings will be applicable only for the current session! You will have to repeat it when you are re-connecting to the network.

Android system chooses the DNS servers using the script located at /system/etc/dhcpcd/dhcpcd-hooks/20-dns.conf

20-dns.conf

To change the DNS servers, use the command: 'setprop property name'

setprop net.dns1=208.67.222.222
setprop net.dns2=208.67.220.220
setprop net.eth0.dns1=208.67.222.222
setprop net.eth0.dns2=208.67.220.220 
setprop net.rmnet0.dns1=208.67.222.222
setprop net.rmnet0.dns2=208.67.220.220
setprop dhcp.tiwlan0.dns1=208.67.222.222
setprop dhcp.tiwlan0.dns2=208.67.220.220
setprop net.ppp0.dns1=208.67.222.222
setprop net.ppp0.dns2=208.67.220.220
setprop net.pdpbr1.dns1=208.67.222.222
setprop net.pdpbr1.dns2=208.67.220.220

Or via init.d script (won't reapply after connectivity change):

#!/system/bin/sh
setprop net.dns1 208.67.222.222
setprop net.dns2 208.67.220.220

# Optional
setprop dhcp.tiwlan0.dns1 208.67.222.222
setprop dhcp.tiwlan0.dns2 208.67.220.220
setprop net.ppp0.dns1 208.67.222.222
setprop net.ppp0.dns2 208.67.220.220
setprop net.rmnet0.dns1 208.67.222.222
setprop net.rmnet0.dns2 208.67.220.220
setprop net.pdpbr1.dns1 208.67.222.222
setprop net.pdpbr1.dns2 208.67.220.220

To check against it (on e.g. wlan) we use: tcpdump -ns0 -i wlan0 'port 53'

DNS check tool is a secure proof if DNS is working or not, alternative you can use nslookup via command line. Please remember that there are some problems generally with the DNS security protocol, there are several known attacks, like DOS, Cache poisoning, ghost domain names & others. For more information take a look over here

If there is no setprop you can write the values before the unset_dns_props() begins. Here is an example 20-dns.conf file. You can get the dns information by using the getprop | grep dns command but this will only work for Android <4.3 devices.

The getprop or setprop method does not work on Android versions >4.4+ anymore. Those values, when changed, get simply ignored by the netd daemon. It's necessary to communicate directly to the daemon via the /dev/socket/netd socket. In Android it's now present a tool called ndc which does exactly this job.

On 4.3 or 4.4 KitKat (#su):

ndc resolver setifdns eth0 "" 208.67.222.222 208.67.220.220 192.168.1.1
ndc resolver setdefaultif eth0

Or via AFWall+ custom script:

$IPTABLES -t nat -D OUTPUT -p tcp --dport 53 -j DNAT --to-destination 208.67.222.222:53 || true
$IPTABLES -t nat -D OUTPUT -p udp --dport 53 -j DNAT --to-destination 208.67.222.222:53 || true

Or via init.d:

#!/system/bin/sh
# File without file extension

IP6TABLES=/system/bin/ip6tables
IPTABLES=/system/bin/iptables

# Maybe need to change $IPTABLES to iptables (if there are troubles applying them)
$IPTABLES -t nat -A OUTPUT -p tcp --dport 53 -j DNAT --to-destination 208.67.222.222:53
$IPTABLES -t nat -A OUTPUT -p udp --dport 53 -j DNAT --to-destination 208.67.222.222:53

If you still like external apps, you should take a look at Override DNS [tested, working on 4.4.4/5.x] which does more or less the same. That may solve some problems on Android 4.4/Lollipop/M but there is no guarantee, some ROMs may handle it different.

Commands to check if DNS is working

The following may are necessary to indicate if all is working (dhcp/nameserver/dnsmasq,...), may needs to be changed for your interfaces you want to check: cellular, tethered, ...

  • Grep the current DNS resolver/settings, reads them via: adb shell getprop | grep dns
  • The actual DNS servers used are the ones listed in the output of: adb shell dumpsys connectivity or adb shell dumpsys connectivity | grep DnsAddresses
  • Via nslookup nslookup google.com
  • See the current dhcp info cat /system/etc/dhcpcd/dhcpcd.conf
  • List the tethered dns configuration adb logcat | egrep '(TetherController|dnsmasq)'
  • Check routing via ip ru + ip route ls
  • On Bluetooth tethering ip addr show bt-pan (optional)
  • TCPDump check state and export them: tcpdump -ni any -s0 -U -w /sdcard/icmp4.pcap icmp4 or adb shell /data/tcpdump -ni wlan0 "icmp6 or port 67 or port 68"

Browser

The normal mobile browser (even stock yes) working out-of-the-box without need any manual adjustment to work with the default DNS.

But some browsers are hard-coding them (so that it isn't possible to override this) and on some systems it may needs configurations changes to get theme proper working e.g. if you changed the DNS system widely.

Working without any manual adjustments:

  • Dolphin
  • Naked Browser
  • Firefox (supports DANE via addon)
  • TOR (Orweb), see this article deprecated
  • ....

Needs changes in the settings:

  • Chrome -> Clean DNS cache .... (doesn't support DANE (official), addon is available)
  • Firefox -> for Tor/Orbot .... (disable internal via network.dnsCacheExpiration;0)
  • ...

Apps to change the default DNS

The following apps are success tested on all systems to work:

  • OverrideDNS (paid)
  • ... add more, remember they must work on all systems (even 5.1.1/M)

Useful links

Todo:

  • I won't explain router side configuration, just use OpenWRT or any other mod (documented very well)
  • Complete the missing parts
  • Android 5.x doesn't support WPAD,....
  • Link all DNS related stuff in this thread (e.g. from the FAQ)
  • Add several workarounds since newer systems ignoring the etc/resolver.conf or dhcpcd/dhcpcd-hooks/20-dns.conf files, explained with given links
  • Add AFWall+ workarounds via custom scripts or separate tips
  • Possible explain why Android 4.4.+/5+ wants to call the RIL with RIL_REQUEST_SETUP_DATA_CALL
  • Explain the broken MTU (saw this on so many roms) and list this bug (see ConnectivityService.cpp), since Android 5.1.x always seems to use 1500 regardless of what value has dhcp daemon set in option 26 (call interface_mtu).
  • How can I gather DNS (A/AAA/...) requests? -> must be re-written
  • Add example output how it should looks like, really? (low-prio)
  • Add traceroute, whois, and dig commands to work with (low-prio)
  • On Android 5.x DNS problems try to disable IPv6, since Android 5.0.1/5.x doesn't like DHCPv6
  • Is there a decentralized search for Android as app available (similar to yacy)? Mail me if there is one. (low-prio) + add them in the article
  • Android auto config compatibility (not yet), e.g. test network fails
  • DNSCrypt, dnsmasq & resolv.conf should be mentioned + example configuration should be given (I need confirmation if that works or not)