Skip to content

Commit 34e9bfc

Browse files
committed
Reconfigure dnspython to remove nameservers on inactive interfaces.
Closes #15; Workaround for rthalley/dnspython#1191
1 parent a746b81 commit 34e9bfc

File tree

2 files changed

+86
-0
lines changed

2 files changed

+86
-0
lines changed

monkey.py

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
import functools
2+
import logging
3+
import platform
4+
import subprocess
5+
import sys
6+
7+
import dns.resolver
8+
9+
10+
def get_active_windows_dns_servers():
11+
"""
12+
Uses PowerShell to get a set of DNS Server IPs from active IPv4 interfaces.
13+
"""
14+
return set(map(get_dns, get_interface_indexes()))
15+
16+
17+
def non_empty_lines(lines):
18+
return filter(None, (line.strip() for line in lines))
19+
20+
21+
def get_interface_indexes():
22+
# Get InterfaceIndex of active, physical, IPv4-enabled adapters
23+
ps_command_get_indexes = (
24+
"Get-NetAdapter -OperationalStatus Up -AddressFamily IPv4 -Physical | "
25+
"Select-Object -ExpandProperty InterfaceIndex"
26+
)
27+
result_indexes = subprocess.run(
28+
["powershell", "-Command", ps_command_get_indexes],
29+
capture_output=True,
30+
text=True,
31+
check=True,
32+
timeout=5,
33+
)
34+
return map(int, non_empty_lines(result_indexes.stdout).splitlines())
35+
36+
37+
def get_dns(index):
38+
"""
39+
Process the index to get DNS servers for that interface.
40+
"""
41+
index_int = int(index.strip())
42+
ps_command_get_dns = (
43+
f"Get-DnsClientServerAddress -InterfaceIndex {index_int} -AddressFamily IPv4 | "
44+
"Select-Object -ExpandProperty ServerAddresses"
45+
)
46+
result_dns = subprocess.run(
47+
["powershell", "-Command", ps_command_get_dns],
48+
capture_output=True,
49+
text=True,
50+
check=False,
51+
timeout=5, # check=False as it errors if no servers are set
52+
)
53+
# Add servers to the set (handles potential multiple servers per adapter)
54+
if result_dns.returncode != 0:
55+
return
56+
57+
return non_empty_lines(result_dns.stdout)
58+
59+
60+
def patch_dnspython_resolver_config():
61+
"""
62+
Applies the monkeypatch to dns.resolver.Resolver._config_resolver
63+
to filter nameservers based on active Windows interfaces.
64+
65+
Workaround for coherent-oss/coherent.deps#15.
66+
"""
67+
if platform.system() != "Windows":
68+
return
69+
70+
resolver = dns.resolver.get_default_resolver()
71+
72+
original_servers = resolver.nameservers
73+
74+
# Get DNS servers currently configured on *active* interfaces
75+
active_servers_set = get_active_windows_dns_servers()
76+
77+
matching_servers = active_servers_set.intersection(original_servers)
78+
79+
if not matching_servers:
80+
# Keep the original list if no active servers found
81+
return
82+
83+
resolver.nameservers = matching_servers

pypi.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,8 @@
7171
from retry_requests import retry
7272
from zipp.compat.overlay import zipfile
7373

74+
from . import monkey
75+
7476
session = retry(sessions.BaseUrlSession('https://pypi.python.org/pypi/'))
7577
session.mount('file://', FileAdapter())
7678
log = logging.getLogger(__name__)
@@ -96,6 +98,7 @@ def client(username=None):
9698
9799
Defaults to an anonymous, read-only connection if no username is supplied.
98100
"""
101+
monkey.patch_dnspython_resolver_config()
99102
username = username or os.environ.get('DB_USER') or 'anonymous'
100103
cluster = os.environ.get('DB_CLUSTER') or 'cluster0.acvlhai.mongodb.net'
101104
password = (

0 commit comments

Comments
 (0)