diff options
author | Brian May <brian@linuxpenguins.xyz> | 2020-11-04 16:55:09 +1100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-11-04 16:55:09 +1100 |
commit | 9b036fc689f857173b7a217bbc72b2d1a53f4f16 (patch) | |
tree | 152c89eb23af6afe912245e6debbee129837aaac /sshuttle/helpers.py | |
parent | 34acdd061169a03596b912cd4d20975a460fad10 (diff) | |
parent | 8461e08bc3db2170a28cab33e2af1cb08f321cb0 (diff) |
Merge pull request #552 from skuhl/systemd-resolved
Intercept DNS requests sent by systemd-resolved.
Diffstat (limited to 'sshuttle/helpers.py')
-rw-r--r-- | sshuttle/helpers.py | 65 |
1 files changed, 56 insertions, 9 deletions
diff --git a/sshuttle/helpers.py b/sshuttle/helpers.py index 185bf0c..9f51586 100644 --- a/sshuttle/helpers.py +++ b/sshuttle/helpers.py @@ -49,17 +49,64 @@ class Fatal(Exception): pass -def resolvconf_nameservers(): - lines = [] - for line in open('/etc/resolv.conf'): - words = line.lower().split() - if len(words) >= 2 and words[0] == 'nameserver': - lines.append(family_ip_tuple(words[1])) - return lines +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. -def resolvconf_random_nameserver(): - lines = resolvconf_nameservers() + 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. + # + # 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, 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: + # https://www.freedesktop.org/software/systemd/man/systemd-resolved.service.html + # + # On machines without systemd-resolved, we expect opening the + # second file will fail. + files = ['/etc/resolv.conf'] + if systemd_resolved: + files += ['/run/systemd/resolve/resolv.conf'] + + nsservers = [] + for f in files: + this_file_nsservers = [] + try: + for line in open(f): + words = line.lower().split() + if len(words) >= 2 and words[0] == 'nameserver': + this_file_nsservers.append(family_ip_tuple(words[1])) + debug2("Found DNS servers in %s: %s\n" % + (f, [n[1] for n in this_file_nsservers])) + nsservers += this_file_nsservers + except OSError as e: + debug3("Failed to read %s when looking for DNS servers: %s\n" % + (f, e.strerror)) + + return nsservers + + +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 |