Page MenuHomeVyOS Platform

vyos-hostsd overriding dns forward configuration
Open, HighPublicBUG

Description

Hi all,

As described on the forum I noticed my DNS forwarding configuration went missing after a certain period. After debugging I found out the configuration change appeared at the same time vyos-hostsd was performing actions as result of a dhclient lease renewal. I've tested this on a clean installation of VyOS 1.2.5 with the configuration mentioned below and was able to reproduce this.

When I reboot the router the configuration is applied as it should. After a while the DHCP client will renew the DHCP release and triggers vyos-hostsd which overwrites the PowerDNS configuration. This overwrite causes the "dns forwarding domain" entries to be removed from "forward-zones-recurse" in /etc/powerdns/recursor.conf (the service dns forwarding name-server entries will persist). In addition I noticed that the "search" and "domain" entries in /etc/resolv.conf are also overwritten by the DHCP proposal (while "search" and "domain" have been configured statically by the system domain-name configuration setting).

I would expect that dynamic services (like DHCP) will never override (or be added to) static configurations that is defined explicitly. So in case I configure a static DNS server or domain-name, I expect only that entry to be configured. When a DHCP offer comes in I'd expect only the IP to be set, but DNS settings to be ignored.

Configuration to reproduce:

set interfaces ethernet eth0 address 'dhcp'
set interfaces ethernet eth0 description 'WAN'
set interfaces ethernet eth0 duplex 'auto'
set interfaces ethernet eth0 smp-affinity 'auto'
set interfaces ethernet eth0 speed 'auto'
set service dns forwarding allow-from '10.0.0.0/8'
set service dns forwarding domain mydomain.net server '10.0.0.100'
set service dns forwarding listen-address '0.0.0.0'
set service dns forwarding name-server '80.80.80.80'
set service dns forwarding name-server '80.80.81.81'
set system domain-name 'mydomain.net'
set system host-name 'vyos'

PowerDNS configuration before DHCP renewal:

vyos@vyos:~$ cat /etc/powerdns/recursor.conf 

### Autogenerated by dns_forwarding.py ###

# Non-configurable defaults
daemon=yes
threads=1
allow-from=10.0.0.0/8
log-common-errors=yes
non-local-bind=yes
query-local-address=0.0.0.0
query-local-address6=::

# cache-size
max-cache-entries=10000

# negative TTL for NXDOMAIN
max-negative-ttl=3600

# ignore-hosts-file
export-etc-hosts=yes

# listen-on
local-address=0.0.0.0

# dnssec
dnssec=process-no-validate

# forward-zones / recursion
#
# statement is only inserted if either one forwarding domain or nameserver is configured
# if nothing is given at all, powerdns will act as a real recursor and resolve all requests by its own
#
forward-zones-recurse=mydomain.net=10.0.0.100, .=80.80.80.80;80.80.81.81

PowerDNS configuration after DHCP renewal (see missing domain.net entry in forward-zones-recurse):

vyos@vyos:~$ cat /etc/powerdns/recursor.conf 

### Autogenerated by dns_forwarding.py ###

# Non-configurable defaults
daemon=yes
threads=1
allow-from=10.0.0.0/8
log-common-errors=yes
non-local-bind=yes
query-local-address=0.0.0.0
query-local-address6=::

# cache-size
max-cache-entries=10000

# negative TTL for NXDOMAIN
max-negative-ttl=3600

# ignore-hosts-file
export-etc-hosts=yes

# listen-on
local-address=0.0.0.0

# dnssec
dnssec=process-no-validate

# forward-zones / recursion
#
# statement is only inserted if either one forwarding domain or nameserver is configured
# if nothing is given at all, powerdns will act as a real recursor and resolve all requests by its own
#
forward-zones-recurse=.=80.80.80.80;80.80.81.81

Resolv.conf before DHCP renewal:

vyos@vyos:~$ cat /etc/resolv.conf 

### Autogenerated by VyOS ###
### Do not edit, your changes will get overwritten ###

nameserver 84.116.46.22
nameserver 84.116.46.23

domain mydomain.net
search mydomain.net

Resolv.conf after DHCP renewal:

vyos@vyos:~$ cat /etc/resolv.conf 

### Autogenerated by VyOS ###
### Do not edit, your changes will get overwritten ###

nameserver 84.116.46.22
nameserver 84.116.46.23

search home

Logs of behavior:

Jun 30 10:17:44 vyos dhclient: DHCPREQUEST on eth0 to 192.168.178.1 port 67
Jun 30 10:17:44 vyos dhclient: DHCPACK from 192.168.178.1
Jun 30 10:17:44 vyos vyos-hostsd[650]: Received a configuration change request
Jun 30 10:17:44 vyos vyos-hostsd[650]: Request data: {"type": "host_name", "op": "set", "data": {"domain_name": null, "search_domains": ["home"], "host_name": null}}
Jun 30 10:17:44 vyos vyos-hostsd[650]: Writing /etc/resolv.conf
Jun 30 10:17:44 vyos vyos-hostsd[650]: Writing /etc/hosts
Jun 30 10:17:44 vyos vyos-hostsd[650]: Saving state to /var/lib/vyos/hostsd.state
Jun 30 10:17:44 vyos vyos-hostsd[650]: Sent response: {'data': None}
Jun 30 10:17:44 vyos vyos-hostsd[650]: Received a configuration change request
Jun 30 10:17:44 vyos vyos-hostsd[650]: Request data: {"type": "name_servers", "tag": "dhcp-eth0", "op": "delete"}
Jun 30 10:17:44 vyos vyos-hostsd[650]: Writing /etc/resolv.conf
Jun 30 10:17:44 vyos vyos-hostsd[650]: Writing /etc/hosts
Jun 30 10:17:44 vyos vyos-hostsd[650]: Saving state to /var/lib/vyos/hostsd.state
Jun 30 10:17:44 vyos vyos-hostsd[650]: Sent response: {'data': None}
Jun 30 10:17:44 vyos vyos-hostsd[650]: Received a configuration change request
Jun 30 10:17:44 vyos vyos-hostsd[650]: Request data: {"data": ["84.116.46.23", "84.116.46.22"], "type": "name_servers", "tag": "dhcp-eth0", "op": "add"}
Jun 30 10:17:44 vyos vyos-hostsd[650]: Writing /etc/resolv.conf
Jun 30 10:17:44 vyos vyos-hostsd[650]: Writing /etc/hosts
Jun 30 10:17:44 vyos vyos-hostsd[650]: Saving state to /var/lib/vyos/hostsd.state
Jun 30 10:17:44 vyos vyos-hostsd[650]: Sent response: {'data': None}
Jun 30 10:17:45 vyos systemd[1]: Stopping PowerDNS Recursor...
Jun 30 10:17:45 vyos systemd[1]: Starting PowerDNS Recursor...
Jun 30 10:17:45 vyos pdns_recursor[3338]: PowerDNS Recursor 4.1.15 (C) 2001-2018 PowerDNS.COM BV
Jun 30 10:17:45 vyos pdns_recursor[3338]: Using 64-bits mode. Built using gcc 4.9.2 on Dec  3 2019 13:02:24 by root@613ec8350b02.
Jun 30 10:17:45 vyos pdns_recursor[3338]: PowerDNS comes with ABSOLUTELY NO WARRANTY. This is free software, and you are welcome to redistribute it according to the terms of the GPL version 2.
Jun 30 10:17:45 vyos pdns_recursor[3338]: Reading random entropy from '/dev/urandom'
Jun 30 10:17:45 vyos pdns_recursor[3338]: Enabling IPv6 transport for outgoing queries
Jun 30 10:17:45 vyos pdns_recursor[3338]: Only allowing queries from: 10.0.0.0/8
Jun 30 10:17:45 vyos pdns_recursor[3338]: Will not send queries to: 127.0.0.0/8, 10.0.0.0/8, 100.64.0.0/10, 169.254.0.0/16, 192.168.0.0/16, 172.16.0.0/12, ::1/128, fc00::/7, fe80::/10, 0.0.0.0/8, 192.0.0.0/24, 192.0.2.0/24, 198.51.100.0/24, 203.0.113.0/24, 240.0.0.0/4, ::/96, ::ffff:0:0/96, 100::/64, 2001:db8::/32, 0.0.0.0, ::
Jun 30 10:17:45 vyos pdns_recursor[3338]: Redirecting queries for zone '.' with recursion to: 80.80.80.80:53, 80.80.81.81:53
Jun 30 10:17:45 vyos pdns_recursor[3338]: Inserting forward zone 'localhost' based on hosts file
Jun 30 10:17:45 vyos pdns_recursor[3338]: Inserting reverse zone '1.0.0.127.in-addr.arpa' based on hosts file
Jun 30 10:17:45 vyos pdns_recursor[3338]: Inserting forward zone 'vyos' based on hosts file
Jun 30 10:17:45 vyos pdns_recursor[3338]: Inserting reverse zone '1.1.0.127.in-addr.arpa' based on hosts file
Jun 30 10:17:45 vyos pdns_recursor[3338]: Inserting rfc 1918 private space zones
Jun 30 10:17:45 vyos pdns_recursor[3338]: Listening for UDP queries on 0.0.0.0:53
Jun 30 10:17:45 vyos pdns_recursor[3338]: Enabled TCP data-ready filter for (slight) DoS protection
Jun 30 10:17:45 vyos pdns_recursor[3338]: Listening for TCP queries on 0.0.0.0:53
Jun 30 10:17:45 vyos pdns_recursor[3338]: Operating unthreaded
Jun 30 10:17:45 vyos systemd[1]: Started PowerDNS Recursor.
Jun 30 10:17:45 vyos pdns_recursor[3338]: Done priming cache with root hints
Jun 30 10:17:45 vyos pdns_recursor[3338]: Done priming cache with root hints
Jun 30 10:17:45 vyos pdns_recursor[3338]: Enabled 'epoll' multiplexer
Jun 30 10:17:45 vyos dhclient: bound to 192.168.178.169 -- renewal in 1675 seconds.
Jun 30 10:17:49 vyos systemd[1]: serial-getty@ttyS0.service holdoff time over, scheduling restart.
Jun 30 10:17:49 vyos systemd[1]: Stopping Serial Getty on ttyS0...
Jun 30 10:17:49 vyos systemd[1]: Starting Serial Getty on ttyS0...
Jun 30 10:17:49 vyos systemd[1]: Started Serial Getty on ttyS0.
Jun 30 10:17:49 vyos agetty[3349]: /dev/ttyS0: not a tty
Jun 30 10:17:51 vyos pdns_recursor[3338]: PowerDNS Security Update Mandatory: Upgrade now, see https://doc.powerdns.com/recursor/security-advisories/powerdns-advisory-2020-01.html https://doc.powerdns.com/recursor/security-advisories/powerdns-advisory-2020-02.html https://doc.powerdns.com/recursor/security-advisories/powerdns-adv" "isory-2020-03.html

Details

Difficulty level
Normal (likely a few hours)
Version
1.2.5
Why the issue appeared?
Will be filled on close
Is it a breaking change?
Behavior change

Event Timeline

This is already fixed in 1.3

Ok, nice. And how about 1.2? Is it possible to fix this with the 1.2.6 release?

Possible by backporting https://github.com/vyos/vyos-1x/pull/452 and https://github.com/vyos/vyatta-cfg-system/pull/125 though I think some code using Config would need to be modified - add .exists calls before each .return_value(s) - 1.3's vyos.config doesn't require them, 1.2's I think does.

Still present in the 1.2.6-S1 release. Makes vyos unusable in environment with DHCP WAN IPs and using the DNS forwarder for specific domains. Those domain forwarders are lost every time the ISP renews the public IP.

Note this occurs even with "set system disable-dhcp-nameservers" in the config, where a DHCP renewal should not affect the DNS system at all.

One work around is to lock the file for editing:

chattr +i /etc/powerdns/recursor.conf

But then you lose the entire DNS forwarding config on next reboot. Currently forcing me to use 1.3 rolling :(.

c-po triaged this task as High priority.Jan 18 2021, 7:46 PM
c-po edited projects, added VyOS 1.2 Crux (VyOS 1.2.7); removed VyOS 1.2 Crux.