NetworkManager & dnsmasq - ignore auto DNS settings

I'm running Arch Linux with NetworkManager and dnsmasq set up. It all seems to work fine, except that I try to use the new CloudFlare 1.1.1.1 DNS, but the resolver keeps using the DNS that is advertised by my router. The nameservers seem to be added, including my router's IP, see below:

Apr 04 20:02:56 tdewolff dnsmasq[22337]: setting upstream servers from DBus
Apr 04 20:02:56 tdewolff dnsmasq[22337]: using nameserver 2606:4700:4700::1001#53
Apr 04 20:02:56 tdewolff dnsmasq[22337]: using nameserver 2606:4700:4700::1111#53
Apr 04 20:02:56 tdewolff dnsmasq[22337]: using nameserver 1.0.0.1#53
Apr 04 20:02:56 tdewolff dnsmasq[22337]: using nameserver 1.1.1.1#53
Apr 04 20:02:56 tdewolff dnsmasq[22337]: using nameserver 192.168.1.254#53(via wlp4s0)
Apr 04 20:02:56 tdewolff dnsmasq[22337]: using nameserver fe80::1%wlp4s0#53
Apr 04 20:02:56 tdewolff dnsmasq[22337]: cleared cache

Using nmcli dev show consistently shows:

IP4.DNS[1]:                             192.168.1.254
IP6.DNS[1]:                             fe80::1

but I want to use the CloudFlare DNSs regardless of the local network (and not have to change the connection settings for every network). How can I change the order of DNS look-up, or disable the router's resolver? I've tried adding strict-order to /etc/NetworkManager/dnsmasq.d/local but to no avail.


I'm not using dnsmasq, but I had a similar issue. The solution for me was:

  • Put the DNS servers you want in /etc/resolv.conf (ref)

    # IPv4 nameservers: 
    nameserver 1.1.1.1
    nameserver 1.0.0.1
    # IPv6 nameservers:
    nameserver 2606:4700:4700::1111
    nameserver 2606:4700:4700::1001
    
  • Tell NetworkManager not to modify your /etc/resolv.conf by writing in your /etc/NetworkManager/NetworkManager.conf (ref)

    [main]
    dns=none
    

Probably restart NetworkManager etc. afterward. If you do nmcli dev show it shows the DNS server reported by the router:

IP4.DNS[1]:                             192.168.50.1

But if you use nslookup (from bind-tools in Arch), it looks like 1.1.1.1 is actually used for the query:

» nslookup google.com
Server:     1.1.1.1
Address:    1.1.1.1#53

Non-authoritative answer:
Name:   google.com
Address: 172.217.9.238
Name:   google.com
Address: 2607:f8b0:4006:801::200e

UPDATE: config with dnsmasq

I tried out a config with dnsmasq. NetworkManager has a dnsmasq plugin that you can use by putting into /etc/NetworkManager/NetworkManager.conf the following:

[main]
dns=dnsmasq

This will start dnsmasq with NetworkManager and put 127.0.0.1 into /etc/resolv.conf (ref). However, I did not do it this way because then dnsmasq isn't managed by systemctl and you don't automatically end up with logging in journalctl (maybe there is some way around this).

Instead, I used the following config (ref):

  • /etc/NetworkManager/NetworkManager.conf:

    [main]
    dns=none
    
  • /etc/resolv.conf:

    nameserver 127.0.0.1
    
  • /etc/resolv.dnsmasq.conf:

     # IPv4 nameservers: 
     nameserver 1.0.0.1
     # IPv6 nameservers:
     nameserver 2606:4700:4700::1111
     nameserver 2606:4700:4700::1001
    
  • /etc/dnsmasq.conf:

     resolv-file=/etc/resolv.dnsmasq.conf
     log-queries
    

Restart NetworkManager and dnsmasq. Now, verify your local nameservers didn't get overwritten:

» cat /etc/resolv.conf
nameserver 127.0.0.1

We can also question NetworkManager:

» cat /run/NetworkManager/resolv.conf 
# Generated by NetworkManager
nameserver 192.168.50.1

» nmcli dev show
...
IP4.DNS[1]:                             192.168.50.1

But those entries are seemingly just indicating what the router has reported, not necessarily what will actually be used for a query, because if we do drill google.com, we see that 127.0.0.1 was in fact used:

;; Query time: 0 msec
;; SERVER: 127.0.0.1
;; WHEN: Fri Apr 20 11:32:59 2018
;; MSG SIZE  rcvd: 44

Also, if you put log-queries into /etc/dnsmasq.conf as shown above, you see in journalctl after running drill stackoverflow.com twice:

dnsmasq[27679]: query[A] stackoverflow.com from 127.0.0.1
dnsmasq[27679]: forwarded stackoverflow.com to 1.0.0.1
dnsmasq[27679]: reply stackoverflow.com is 151.101.1.69
dnsmasq[27679]: reply stackoverflow.com is 151.101.65.69
dnsmasq[27679]: reply stackoverflow.com is 151.101.129.69
dnsmasq[27679]: reply stackoverflow.com is 151.101.193.69
dnsmasq[27679]: query[A] stackoverflow.com from 127.0.0.1
dnsmasq[27679]: cached stackoverflow.com is 151.101.193.69
dnsmasq[27679]: cached stackoverflow.com is 151.101.129.69
dnsmasq[27679]: cached stackoverflow.com is 151.101.65.69
dnsmasq[27679]: cached stackoverflow.com is 151.101.1.69

The first time it asked 1.0.0.1, the second time it found the result in the cache. You can remove log-queries from dnsmasq.conf if satisfied.


A slightly better way, in that it simplifies NetworkManager management, is to use a symlink for /etc/resolv.conf. This is the default in my distro (Fedora), which you can check in your disto by looking at the dns option in man 5 NetworkManager.conf.

Define cloudflare as the authoritative DNS by first creating a file (I used /usr/local/etc/resolv.cloudflare.conf) containing the cloudflare DNS's:

# IPv4 nameservers: 
nameserver 1.1.1.1
nameserver 1.0.0.1
# IPv6 nameservers:
nameserver 2606:4700:4700::1111
nameserver 2606:4700:4700::1001

Then symlink to that file, removing the existing file.

sudo rm /etc/resolv.conf sudo ln -s /usr/local/etc/resolv.cloudflare.conf /etc/resolv.conf

At this point, you can verify that the nameserver is doing the right thing by

$ dig google.com

; <<>> DiG 9.11.2-P1-RedHat-9.11.2-1.P1.fc26 <<>> google.com
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 41906
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 1536
;; QUESTION SECTION:
;google.com.            IN  A

;; ANSWER SECTION:
google.com.     185 IN  A   172.217.9.238

;; Query time: 10 msec
;; SERVER: 1.1.1.1#53(1.1.1.1)
;; WHEN: Thu Apr 12 18:00:37 EDT 2018
;; MSG SIZE  rcvd: 55

Note: If your distro's NetworkManager has a different default for the dns= variable, then update it to include the following.

[main]
dns=symlink

Then, NetworkManager will not update resolve.conf if you make /etc/resolve.conf a symlink,