windows: support automatic nameserver detection for --dns option

This commit is contained in:
nom3ad 2024-05-01 20:08:15 +05:30 committed by Brian May
parent 51287dc4db
commit b826ae6b91
3 changed files with 39 additions and 12 deletions

View File

@ -3,7 +3,9 @@ import socket
import errno
import os
import threading
import subprocess
import traceback
import re
if sys.platform != "win32":
import fcntl
@ -114,18 +116,43 @@ def resolvconf_nameservers(systemd_resolved):
return nsservers
def resolvconf_random_nameserver(systemd_resolved):
def windows_nameservers():
out = subprocess.check_output(["powershell", "-NonInteractive", "-NoProfile", "-Command", "Get-DnsClientServerAddress"],
encoding="utf-8")
servers = set()
for line in out.splitlines():
if line.startswith("Loopback "):
continue
m = re.search(r'{.+}', line)
if not m:
continue
for s in m.group().strip('{}').split(','):
s = s.strip()
if s.startswith('fec0:0:0:ffff'):
continue
servers.add(s)
debug2("Found DNS servers: %s" % servers)
return [(socket.AF_INET6 if ':' in s else socket.AF_INET, s) for s in servers]
def get_random_nameserver():
"""Return a random nameserver selected from servers produced by
resolvconf_nameservers(). See documentation for
resolvconf_nameservers() for a description of the parameter.
resolvconf_nameservers()/windows_nameservers()
"""
lines = resolvconf_nameservers(systemd_resolved)
if lines:
if len(lines) > 1:
if sys.platform == "win32":
if globals().get('_nameservers') is None:
ns_list = windows_nameservers()
globals()['_nameservers'] = ns_list
else:
ns_list = globals()['_nameservers']
else:
ns_list = resolvconf_nameservers(systemd_resolved=False)
if ns_list:
if len(ns_list) > 1:
# don't import this unless we really need it
import random
random.shuffle(lines)
return lines[0]
random.shuffle(ns_list)
return ns_list[0]
else:
return (socket.AF_INET, '127.0.0.1')

View File

@ -14,7 +14,7 @@ import sshuttle.hostwatch as hostwatch
import subprocess as ssubprocess
from sshuttle.ssnet import Handler, Proxy, Mux, MuxWrapper
from sshuttle.helpers import b, log, debug1, debug2, debug3, Fatal, \
resolvconf_random_nameserver, which, get_env, SocketRWShim
get_random_nameserver, which, get_env, SocketRWShim
def _ipmatch(ipstr):
@ -199,7 +199,7 @@ class DnsProxy(Handler):
self.tries += 1
if self.to_nameserver is None:
_, peer = resolvconf_random_nameserver(False)
_, peer = get_random_nameserver()
port = 53
else:
peer = self.to_ns_peer

View File

@ -143,7 +143,7 @@ nameserver 2404:6800:4004:80c::4
@patch('sshuttle.helpers.open', create=True)
def test_resolvconf_random_nameserver(mock_open):
def test_get_random_nameserver(mock_open):
mock_open.return_value = io.StringIO(u"""
# Generated by NetworkManager
search pri
@ -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(False)
ns = sshuttle.helpers.get_random_nameserver()
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'),