diff --git a/sshuttle/client.py b/sshuttle/client.py index da23b7d..ab28d0b 100644 --- a/sshuttle/client.py +++ b/sshuttle/client.py @@ -589,7 +589,7 @@ def main(listenip_v6, listenip_v4, # redirect packets outgoing to this server to the remote host # instead. if dns: - nslist += resolvconf_nameservers() + nslist += resolvconf_nameservers(True) if to_nameserver is not None: to_nameserver = "%s@%s" % tuple(to_nameserver[1:]) else: diff --git a/sshuttle/helpers.py b/sshuttle/helpers.py index 5d61b43..0cd97df 100644 --- a/sshuttle/helpers.py +++ b/sshuttle/helpers.py @@ -48,10 +48,18 @@ class Fatal(Exception): pass -def resolvconf_nameservers(): - """Retrieves a list of tuples (address type, address as a string) that - the current system uses to resolve hostnames from /etc/resolv.conf - and possibly other files. +def resolvconf_nameservers(systemd_resolved): + """Retrieves a list of tuples (address type, address as a string) of + the DNS servers used by the system to resolve hostnames. + + If parameter is False, DNS servers are retrieved from only + /etc/resolv.conf. This behavior makes sense for the sshuttle + server. + + If parameter is True, we retrieve information from both + /etc/resolv.conf and /run/systemd/resolve/resolv.conf (if it + exists). This behavior makes sense for the sshuttle client. + """ # Historically, we just needed to read /etc/resolv.conf. @@ -59,10 +67,10 @@ def resolvconf_nameservers(): # If systemd-resolved is active, /etc/resolv.conf will point to # localhost and the actual DNS servers that systemd-resolved uses # are stored in /run/systemd/resolve/resolv.conf. For programs - # that use the localhost DNS server, only reading /etc/resolv.conf - # is sufficient. However, resolved provides other ways of - # resolving hostnames (such as via dbus) that may not route - # requests through localhost. So, we retrieve a list of DNS + # that use the localhost DNS server, having sshuttle read + # /etc/resolv.conf is sufficient. However, resolved provides other + # ways of resolving hostnames (such as via dbus) that may not + # route requests through localhost. So, we retrieve a list of DNS # servers that resolved uses so we can intercept those as well. # # For more information about systemd-resolved, see: @@ -70,7 +78,9 @@ def resolvconf_nameservers(): # # On machines without systemd-resolved, we expect opening the # second file will fail. - files = ['/etc/resolv.conf', '/run/systemd/resolve/resolv.conf'] + files = ['/etc/resolv.conf'] + if systemd_resolved: + files += ['/run/systemd/resolve/resolv.conf'] nsservers = [] for f in files: @@ -90,8 +100,12 @@ def resolvconf_nameservers(): return nsservers -def resolvconf_random_nameserver(): - lines = resolvconf_nameservers() +def resolvconf_random_nameserver(systemd_resolved): + """Return a random nameserver selected from servers produced by + resolvconf_nameservers(). See documentation for + resolvconf_nameservers() for a description of the parameter. + """ + lines = resolvconf_nameservers(systemd_resolved) if lines: if len(lines) > 1: # don't import this unless we really need it diff --git a/sshuttle/server.py b/sshuttle/server.py index 8e15866..67409a7 100644 --- a/sshuttle/server.py +++ b/sshuttle/server.py @@ -205,7 +205,7 @@ class DnsProxy(Handler): self.tries += 1 if self.to_nameserver is None: - _, peer = resolvconf_random_nameserver() + _, peer = resolvconf_random_nameserver(False) port = 53 else: peer = self.to_ns_peer diff --git a/tests/client/test_helpers.py b/tests/client/test_helpers.py index 3ed588f..732f38a 100644 --- a/tests/client/test_helpers.py +++ b/tests/client/test_helpers.py @@ -131,7 +131,7 @@ nameserver 2404:6800:4004:80c::3 nameserver 2404:6800:4004:80c::4 """) - ns = sshuttle.helpers.resolvconf_nameservers() + ns = sshuttle.helpers.resolvconf_nameservers(False) assert ns == [ (AF_INET, u'192.168.1.1'), (AF_INET, u'192.168.2.1'), (AF_INET, u'192.168.3.1'), (AF_INET, u'192.168.4.1'), @@ -156,7 +156,7 @@ nameserver 2404:6800:4004:80c::2 nameserver 2404:6800:4004:80c::3 nameserver 2404:6800:4004:80c::4 """) - ns = sshuttle.helpers.resolvconf_random_nameserver() + ns = sshuttle.helpers.resolvconf_random_nameserver(False) assert ns in [ (AF_INET, u'192.168.1.1'), (AF_INET, u'192.168.2.1'), (AF_INET, u'192.168.3.1'), (AF_INET, u'192.168.4.1'),