blueman icon indicating copy to clipboard operation
blueman copied to clipboard

Blueman provides incorrect DNS info to NAP clients when using dhcpd for DHCP on Ubuntu

Open justdave opened this issue 4 years ago • 10 comments

blueman: 2.1.3-2ubuntu1.1 BlueZ: 5.55-0ubuntu1.1 Distribution: Ubuntu 20.10/groovy Desktop environment: whatever the default is on Ubuntu - I can't find an About box anywhere to tell me what it is

I originally filed this at https://bugs.launchpad.net/ubuntu/+source/blueman/+bug/1845824 almost two years ago, but they've never patched it and never saw fit to upstream the bug report apparently.

Symptom: When configuring blueman to offer a Bluetooth Network Access Point and instructing it to use dhcpd for the DHCP server, it feeds 127.0.0.53 to the clients as the DNS server. This does not work because 127.0.0.0/8 is only accessible from localhost, and the clients route that address to themselves.

The code which generates the DHCP config is in /usr/lib/python3/dist-packages/blueman/main/NetConf.py and the offending code can be found in the get_dns_servers function at line 31 (as of the version listed above)

It pulls the DNS server out of /etc/resolv.conf. On modern Ubuntu systems, Ubuntu has a DNS cache server installed, which binds to 127.0.0.53, so that's what it puts in /etc/resolv.conf. This is not the real DNS server of course, and it's not reachable from NAP clients.

Two options seem to be available to fix this:

  1. Check if NetworkManager is installed, and if it is, use it to get the DNS server instead of looking in resolv.conf -or-
  2. Add a configuration option for the DNS server to feed to clients.

The following bash snippet will grab the default route's primary DNS server from NetworkManager: systemd-resolve --status $( netstat -r | grep default | head -1 | awk '{ print $8 }' ) | grep 'DNS Server:' | sed -e 's/.*DNS Server: \(\S\+\).*/\1/'

I suspect there's a better API for it from python, but I haven't researched it.

justdave avatar May 31 '21 17:05 justdave

That's not NetworkManager. NetworkManager creates a perfectly fine /etc/resolv.conf for me. 127.0.0.53 is systemd-resolved. It symlinks /lib/systemd/resolv.conf with that static configuration pointing at its internal resolver.

Could you check #1553?

cschramm avatar Jun 04 '21 07:06 cschramm

I'm not much of an expert on the topic, but at least I got you pointed in the right direction. :-)

I just rebuilt the Ubuntu package with version 2.2.1 and this patch applied on top of it, and I'm now running that and it seems to work. :-)

justdave avatar Jun 06 '21 20:06 justdave

I take that back, it only worked the first time. On subsequent restarts, it fails with an error that the dhcpd.conf file has an unexpected semicolon. The line cited is blueman's domain-name-server option line, which has no servers listed. :-( I'm not sure why it worked the first time, maybe had something in memory since I didn't restart the whole server after reinstalling before I tried it.

justdave avatar Jun 23 '21 17:06 justdave

Restarts of ... your system? I could imagine that blueman is asking too early before DNS servers are known. We probably have to listen to changes of the DNS property instead of just reading it.

cschramm avatar Jun 24 '21 10:06 cschramm

I could imagine that blueman is asking too early before DNS servers are known. We probably have to listen to changes of the DNS property instead of just reading it.

Ah, yes, that would make sense.... except just restarting the nap service in blueman throws an error with the existing patch:

Screen Shot 2021-07-06 at 1 08 23 PM

justdave avatar Jul 06 '21 17:07 justdave

:thinking: You do see IPv4 nameservers with systemd-resolve --status? What does

dbus-send --print-reply --system --dest=org.freedesktop.resolve1 /org/freedesktop/resolve1 org.freedesktop.DBus.Properties.Get string:org.freedesktop.resolve1.Manager string:DNS

give you?

cschramm avatar Jul 06 '21 20:07 cschramm

systemd-resolve --status shows nameservers on links 2 and 7 but not in global. 2 is eth0, 7 is a bridge interface that includes eth0 and the tap interface from the openvpn server. Both have "+DefaultRoute" in the Protocols section, all the rest of them have "-DefaultRoute"

dave@mini:~$ dbus-send --print-reply --system --dest=org.freedesktop.resolve1 /org/freedesktop/resolve1 org.freedesktop.DBus.Properties.Get string:org.freedesktop.resolve1.Manager string:DNS
method return time=1625637029.437874 sender=:1.2 -> destination=:1.93 serial=284 reply_serial=2
   variant       array [
         struct {
            int32 7
            int32 2
            array of bytes [
               c0 a8 34 fe
            ]
         }
         struct {
            int32 2
            int32 2
            array of bytes [
               c0 a8 34 fe
            ]
         }
         struct {
            int32 2
            int32 10
            array of bytes [
               fd 7a fe 7f 6a 03 00 52 00 00 00 00 00 00 00 fe
            ]
         }
      ]

looks like the code is specifically looking for interface==0 and those are only 2 and 7...

I checked another machine that doesn't have the funky openvpn setup on it, and it also only has dns servers listed on link 2.

justdave avatar Jul 07 '21 06:07 justdave

Not sure how that API is meant to be used then. We can go through all links to find the default one(s). What about

dbus-send --print-reply --system --dest=org.freedesktop.resolve1 /org/freedesktop/resolve1 org.freedesktop.DBus.Properties.Get string:org.freedesktop.resolve1.Manager string:CurrentDNSServer

? Would be only one but as long as we watch the property that should be fine, I guess.

cschramm avatar Jul 07 '21 07:07 cschramm

dave@mini:~$ dbus-send --print-reply --system --dest=org.freedesktop.resolve1 /org/freedesktop/resolve1 org.freedesktop.DBus.Properties.Get string:org.freedesktop.resolve1.Manager string:CurrentDNSServer
method return time=1625886702.538100 sender=:1.2 -> destination=:1.257 serial=20721 reply_serial=2
   variant       struct {
         int32 0
         int32 0
         array [
         ]
      }

justdave avatar Jul 10 '21 03:07 justdave

Alright, I dug into the systemd-resolve documentation and found that it uses global and link-specific DNS servers where the links have the DefaultRoute flag alike, so that's what we want to collect. New try in #1553.

cschramm avatar Jul 10 '21 08:07 cschramm