summaryrefslogtreecommitdiffstats
path: root/sshuttle/helpers.py
diff options
context:
space:
mode:
authorBrian May <brian@linuxpenguins.xyz>2020-11-04 16:55:09 +1100
committerGitHub <noreply@github.com>2020-11-04 16:55:09 +1100
commit9b036fc689f857173b7a217bbc72b2d1a53f4f16 (patch)
tree152c89eb23af6afe912245e6debbee129837aaac /sshuttle/helpers.py
parent34acdd061169a03596b912cd4d20975a460fad10 (diff)
parent8461e08bc3db2170a28cab33e2af1cb08f321cb0 (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.py65
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