blueman
                                
                                
                                
                                    blueman copied to clipboard
                            
                            
                            
                        Blueman provides incorrect DNS info to NAP clients when using dhcpd for DHCP on Ubuntu
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
- [x] I have consulted the Troubleshooting page and done my best effort to follow.
 
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:
- Check if NetworkManager is installed, and if it is, use it to get the DNS server instead of looking in resolv.conf -or-
 - 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.
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?
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. :-)
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.
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.
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:
                                    
                                    
                                    
                                
: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?
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.
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.
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 [
         ]
      }
                                    
                                    
                                    
                                
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.