TranslateProject/sources/tech/20180706 Anatomy of a Linux DNS Lookup - Part III.md
2018-08-26 12:10:18 +08:00

317 lines
12 KiB
Markdown
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

pinewall is translating
Anatomy of a Linux DNS Lookup Part III
============================================================
In [Anatomy of a Linux DNS Lookup Part I][1] I covered:
* `nsswitch`
* `/etc/hosts`
* `/etc/resolv.conf`
* `ping` vs `host` style lookups
and in [Anatomy of a Linux DNS Lookup Part II][2] I covered:
* `systemd` and its `networking` service
* `ifup` and `ifdown`
* `dhclient`
* `resolvconf`
and ended up here:
* * *
![linux-dns-2 (2)](https://zwischenzugs.files.wordpress.com/2018/06/linux-dns-2-2.png?w=525)
_A (roughly) accurate map of whats going on_
Unfortunately, thats not the end of the story. Theres still more things that can get involved. In Part III, Im going to cover NetworkManager and dnsmasq and briefly show how they play a part.
* * *
# 1) NetworkManager
As mentioned in Part II, we are now well away from POSIX standards and into Linux distribution-specific areas of DNS resolution management.
In my preferred distribution (Ubuntu), there is a service thats available and often installed for me as a dependency of some other package I install called [NetworkManager][3]. Its actually a service developed by RedHat in 2004 to help manage network interfaces for you.
What does this have to do with DNS? Install it to find out:
```
$ apt-get install -y network-manager
```
In my distribution, I get a config file.
```
$ cat /etc/NetworkManager/NetworkManager.conf
[main]
plugins=ifupdown,keyfile,ofono
dns=dnsmasq
[ifupdown]
managed=false
```
See that `dns=dnsmasq` there? That means that NetworkManager will use `dnsmasq` to manage DNS on the host.
* * *
# 2) dnsmasq
The dnsmasq program is that now-familiar thing: yet another level of indirection for `/etc/resolv.conf`.
Technically, dnsmasq can do a few things, but is primarily it acts as a DNS server that can cache requests to other DNS servers. It runs on port 53 (the standard DNS port), on all local network interfaces.
So where is `dnsmasq` running? NetworkManager is running:
```
$ ps -ef | grep NetworkManager
root     15048     1  0 16:39 ?        00:00:00 /usr/sbin/NetworkManager --no-daemon
```
But no `dnsmasq` process exists:
```
$ ps -ef | grep dnsmasq
$
```
Although its configured to be used, confusingly its not actually installed! So youre going to install it.
Before you install it though, lets check the state of `/etc/resolv.conf`.
```
$ cat /etc/resolv.conf
# Dynamic resolv.conf(5) file for glibc resolver(3) generated by resolvconf(8)
#     DO NOT EDIT THIS FILE BY HAND -- YOUR CHANGES WILL BE OVERWRITTEN
nameserver 10.0.2.2
search home
```
Its not been changed by NetworkManager.
If `dnsmasq` is installed:
```
$ apt-get install -y dnsmasq
```
Then `dnsmasq` is up and running:
```
$ ps -ef | grep dnsmasq
dnsmasq  15286     1  0 16:54 ?        00:00:00 /usr/sbin/dnsmasq -x /var/run/dnsmasq/dnsmasq.pid -u dnsmasq -r /var/run/dnsmasq/resolv.conf -7 /etc/dnsmasq.d,.dpkg-dist,.dpkg-old,.dpkg-new --local-service --trust-anchor=.,19036,8,2,49AAC11D7B6F6446702E54A1607371607A1A41855200FD2CE1CDDE32F24E8FB5
```
And `/etc/resolv.conf` has changed again!
```
root@linuxdns1:~# cat /etc/resolv.conf
# Dynamic resolv.conf(5) file for glibc resolver(3) generated by resolvconf(8)
#     DO NOT EDIT THIS FILE BY HAND -- YOUR CHANGES WILL BE OVERWRITTEN
nameserver 127.0.0.1
search home
```
And `netstat` shows `dnsmasq` is serving on all interfaces at port 53:
```
$ netstat -nlp4
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address     Foreign Address State   PID/Program name
tcp        0      0 127.0.0.1:53      0.0.0.0:*       LISTEN  15286/dnsmasq 
tcp        0      0 10.0.2.15:53      0.0.0.0:*       LISTEN  15286/dnsmasq
tcp        0      0 172.28.128.11:53  0.0.0.0:*       LISTEN  15286/dnsmasq
tcp        0      0 0.0.0.0:22        0.0.0.0:*       LISTEN  1237/sshd
udp        0      0 127.0.0.1:53      0.0.0.0:*         15286/dnsmasq
udp        0      0 10.0.2.15:53      0.0.0.0:*               15286/dnsmasq  
udp        0      0 172.28.128.11:53  0.0.0.0:*               15286/dnsmasq  
udp        0      0 0.0.0.0:68        0.0.0.0:*               10758/dhclient
udp        0      0 0.0.0.0:68        0.0.0.0:*               10530/dhclient
udp        0      0 0.0.0.0:68        0.0.0.0:*               10185/dhclient
```
* * *
# 3) Unpicking dnsmasq
Now we are in a situation where all DNS queries are going to `127.0.0.1:53` and from there what happens?
We can get a clue from looking again at the `/var/run` folder. The `resolv.conf` in `resolvconf` has been changed to point to where `dnsmasq` is being served:
```
$ cat /var/run/resolvconf/resolv.conf
# Dynamic resolv.conf(5) file for glibc resolver(3) generated by resolvconf(8)
#     DO NOT EDIT THIS FILE BY HAND -- YOUR CHANGES WILL BE OVERWRITTEN
nameserver 127.0.0.1
search home
```
while theres a new `dnsmasq` folder with its own `resolv.conf`.
```
$ cat /run/dnsmasq/resolv.conf
nameserver 10.0.2.2
```
which has the nameserver given to us by `DHCP`.
We can reason about this without looking too deeply, but what if we really want to know whats going on?
* * *
# 4) Debugging Dnsmasq
Frequently Ive found myself wondering what dnsmasqs state is. Fortunately, you can get a good amount of information out of it if you set change this line in `/etc/dnsmasq.conf`:
```
#log-queries
```
to:
```
log-queries
```
and restart `dnsmasq`
Now, if you do a simple:
```
$ ping -c1 bbc.co.uk
```
you will see something like this in `/var/log/syslog` (the `[...]` indicates that the lines start is the same as the previous one):
```
Jul  3 19:56:07 ubuntu-xenial dnsmasq[15372]: query[A] bbc.co.uk from 127.0.0.1
[...] forwarded bbc.co.uk to 10.0.2.2
[...] reply bbc.co.uk is 151.101.192.81
[...] reply bbc.co.uk is 151.101.0.81
[...] reply bbc.co.uk is 151.101.64.81
[...] reply bbc.co.uk is 151.101.128.81
[...] query[PTR] 81.192.101.151.in-addr.arpa from 127.0.0.1
[...] forwarded 81.192.101.151.in-addr.arpa to 10.0.2.2
[...] reply 151.101.192.81 is NXDOMAIN
```
which shows what `dnsmasq` received, where the query was forwarded to, and what reply was received.
If the query is returned from the cache (or, more exactly, the local time-to-live for the query has not expired), then it looks like this in the logs:
```
[...] query[A] bbc.co.uk from 127.0.0.1
[...] cached bbc.co.uk is 151.101.64.81
[...] cached bbc.co.uk is 151.101.128.81
[...] cached bbc.co.uk is 151.101.192.81
[...] cached bbc.co.uk is 151.101.0.81
[...] query[PTR] 81.64.101.151.in-addr.arpa from 127.0.0.1
```
and if you ever want to know whats in your cache, you can provoke dnsmasq into sending it to the same log file by sending the `USR1` signal to the dnsmasq process id:
```
$ kill -SIGUSR1 <(cat /run/dnsmasq/dnsmasq.pid)
```
and the output of the dump looks like this:
```
Jul  3 15:08:08 ubuntu-xenial dnsmasq[15697]: time 1530630488                                                                                                                                 
[...] cache size 150, 0/5 cache insertions re-used unexpired cache entries.                                                                           
[...] queries forwarded 2, queries answered locally 0                                                                                                 
[...] queries for authoritative zones 0                                                                                                               
[...] server 10.0.2.2#53: queries sent 2, retried or failed 0                                                                                         
[...] Host           Address        Flags      Expires                            
[...] linuxdns1      172.28.128.8   4FRI   H                                                                
[...] ip6-localhost  ::1            6FRI   H                                                                
[...] ip6-allhosts   ff02::3         6FRI   H                                                                
[...] ip6-localnet     fe00::         6FRI   H                                                                
[...] ip6-mcastprefix  ff00::         6FRI   H                                                                
[...] ip6-loopback     :               6F I   H                                                                
[...] ip6-allnodes    ff02:           6FRI   H                                                                
[...] bbc.co.uk        151.101.64.81  4F         Tue Jul  3 15:11:41 2018                                     
[...] bbc.co.uk        151.101.192.81 4F         Tue Jul  3 15:11:41 2018                                     
[...] bbc.co.uk        151.101.0.81    4F         Tue Jul  3 15:11:41 2018                                     
[...] bbc.co.uk        151.101.128.81 4F         Tue Jul  3 15:11:41 2018                                     
[...]                  151.101.64.81  4 R  NX    Tue Jul  3 15:34:17 2018                                     
[...] localhost        127.0.0.1      4FRI   H                                                                
[...] <Root>           19036   8   2  SF I                                                                    
[...] ip6-allrouters   ff02::2        6FRI   H        
```
In the above output, I believe (but dont know, and ? indicates a relatively wild guess on my part) that:
* 4 means IPv4
* 6 means IPv6
* H means address was read from an `/etc/hosts` file
* I ? Immortal DNS value? (ie no time-to-live value?)
* F ?
* R ?
* S?
* N?
* X
#### Alternatives to dnsmasq
`dnsmasq` is not the only option that can be passed to dns in NetworkManager. Theres `none` which does nothing to `/etc/resolv,conf`, `default`, which claims to update `resolv.conf`  to reflect currently active connections, and `unbound`, which communicates with the `unbound` service and `dnssec-triggerd`, which is concerned with DNS security and is not covered here.
* * *
### End of Part III
Thats the end of Part III, where we covered the NetworkManager service, and its `dns=dnsmasq` setting.
Lets briefly list some of the things weve come across so far:
* `nsswitch`
* `/etc/hosts`
* `/etc/resolv.conf`
* `/run/resolvconf/resolv.conf`
* `systemd` and its `networking` service
* `ifup` and `ifdown`
* `dhclient`
* `resolvconf`
* `NetworkManager`
* `dnsmasq`
--------------------------------------------------------------------------------
via: https://zwischenzugs.com/2018/07/06/anatomy-of-a-linux-dns-lookup-part-iii/
作者:[ZWISCHENZUGS][a]
译者:[译者ID](https://github.com/译者ID)
校对:[校对者ID](https://github.com/校对者ID)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]:https://zwischenzugs.com/
[1]:https://zwischenzugs.com/2018/06/08/anatomy-of-a-linux-dns-lookup-part-i/
[2]:https://zwischenzugs.com/2018/06/18/anatomy-of-a-linux-dns-lookup-part-ii/
[3]:https://en.wikipedia.org/wiki/NetworkManager