dpyproxy 2.2.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- dpyproxy/__init__.py +1 -0
- dpyproxy/__main__.py +4 -0
- dpyproxy-2.2.0.dist-info/METADATA +296 -0
- dpyproxy-2.2.0.dist-info/RECORD +59 -0
- dpyproxy-2.2.0.dist-info/WHEEL +4 -0
- dpyproxy-2.2.0.dist-info/entry_points.txt +2 -0
- dpyproxy-2.2.0.dist-info/licenses/LICENSE +201 -0
- enumerators/DnsProxyMode.py +39 -0
- enumerators/DnsResolvers.py +141 -0
- enumerators/HttpMethod.py +17 -0
- enumerators/Modules.py +38 -0
- enumerators/Port.py +11 -0
- enumerators/TcpProxyMode.py +17 -0
- enumerators/TlsVersion.py +21 -0
- enumerators/__init__.py +0 -0
- exception/DnsException.py +7 -0
- exception/ParserException.py +7 -0
- exception/__init__.py +0 -0
- main.py +94 -0
- modules/Module.py +45 -0
- modules/__init__.py +0 -0
- modules/dns/DnsModeDeterminator.py +358 -0
- modules/dns/DnsModule.py +113 -0
- modules/dns/DnsProxy.py +277 -0
- modules/dns/DnsResolver.py +18 -0
- modules/dns/__init__.py +0 -0
- modules/http/HttpModule.py +69 -0
- modules/http/HttpStrategies.py +849 -0
- modules/http/HttpUtils.py +94 -0
- modules/http/__init__.py +0 -0
- modules/tls/TcpProxy.py +106 -0
- modules/tls/TlsModule.py +173 -0
- modules/tls/__init__.py +0 -0
- network/DomainResolver.py +472 -0
- network/NetworkAddress.py +10 -0
- network/WrappedSocket.py +97 -0
- network/__init__.py +0 -0
- network/protocols/Dns.py +62 -0
- network/protocols/Http.py +109 -0
- network/protocols/Socksv4.py +70 -0
- network/protocols/Socksv5.py +106 -0
- network/protocols/Tls.py +113 -0
- network/protocols/__init__.py +0 -0
- network/tcp/Forwarder.py +203 -0
- network/tcp/TcpConnectionHandler.py +264 -0
- network/tcp/WrappedTcpSocket.py +30 -0
- network/tcp/__init__.py +0 -0
- network/udp/__init__.py +0 -0
- test/Sink.py +23 -0
- test/__init__.py +0 -0
- test/test_dns.py +98 -0
- test/test_http.py +57 -0
- test/test_tls.py +63 -0
- util/DnsAutoModeRuntimeMeasurement.py +62 -0
- util/DnsReachabilityCollector.py +160 -0
- util/DnsResolversDomainResolver.py +36 -0
- util/Util.py +62 -0
- util/__init__.py +0 -0
- util/constants.py +8 -0
|
@@ -0,0 +1,358 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
import random
|
|
3
|
+
from ipaddress import ip_address, ip_network
|
|
4
|
+
|
|
5
|
+
import dns.message
|
|
6
|
+
from dns.message import make_query
|
|
7
|
+
|
|
8
|
+
from enumerators.DnsProxyMode import DnsProxyMode
|
|
9
|
+
from enumerators.DnsResolvers import DnsResolvers
|
|
10
|
+
from modules.dns.DnsResolver import DnsResolver
|
|
11
|
+
from network.DomainResolver import DomainResolver
|
|
12
|
+
from network.NetworkAddress import NetworkAddress
|
|
13
|
+
from util.Util import parse_all_ips
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class DnsModeDeterminator:
|
|
17
|
+
"""
|
|
18
|
+
Determines functioning circumvention modes and reachable DoQ/DoH/etc. servers.
|
|
19
|
+
"""
|
|
20
|
+
|
|
21
|
+
@staticmethod
|
|
22
|
+
def parse_custom_resolvers(resolvers: list[tuple[DnsProxyMode, str, str, int, str, str]]) -> list[DnsResolver]:
|
|
23
|
+
"""
|
|
24
|
+
Parses a list of custom resolvers (tuple of ProxyMode, name, ip, port) into DnsResolver objects.
|
|
25
|
+
"""
|
|
26
|
+
_ret = []
|
|
27
|
+
for resolver in resolvers:
|
|
28
|
+
address = NetworkAddress(resolver[2], resolver[3])
|
|
29
|
+
_ret += [DnsResolver(resolver[1], address, resolver[0], resolver[4], 0, 0, resolver[5])]
|
|
30
|
+
return _ret
|
|
31
|
+
|
|
32
|
+
@staticmethod
|
|
33
|
+
def parse_default_resolvers(resolvers: list[DnsResolvers], modes: list[DnsProxyMode]) -> list[DnsResolver]:
|
|
34
|
+
"""
|
|
35
|
+
Parses a list of default resolvers into DnsResolver objects using their standard ports and names. Does that for
|
|
36
|
+
all provided proxy modes.
|
|
37
|
+
"""
|
|
38
|
+
_ret = []
|
|
39
|
+
for mode in modes:
|
|
40
|
+
# call custom resolver method with resolvers default values
|
|
41
|
+
_ret += DnsModeDeterminator.parse_custom_resolvers(
|
|
42
|
+
list(
|
|
43
|
+
map(
|
|
44
|
+
lambda resolver: (
|
|
45
|
+
mode,
|
|
46
|
+
str(resolver.name),
|
|
47
|
+
str(resolver.value),
|
|
48
|
+
mode.default_port(),
|
|
49
|
+
str(resolver.hostname),
|
|
50
|
+
str(resolver.path),
|
|
51
|
+
),
|
|
52
|
+
resolvers,
|
|
53
|
+
)
|
|
54
|
+
)
|
|
55
|
+
)
|
|
56
|
+
return _ret
|
|
57
|
+
|
|
58
|
+
@staticmethod
|
|
59
|
+
def generate_resolvers(restrict_advertised: bool = True) -> list[DnsResolver]:
|
|
60
|
+
"""
|
|
61
|
+
Generates a list of DnsResolver objects based on the statically defined addresses below.
|
|
62
|
+
"""
|
|
63
|
+
_res = []
|
|
64
|
+
|
|
65
|
+
if restrict_advertised:
|
|
66
|
+
# append RESOLVERS_SUPPORT_ALL
|
|
67
|
+
_res += DnsModeDeterminator.parse_default_resolvers(
|
|
68
|
+
DnsModeDeterminator.RESOLVERS_SUPPORT_ALL, [mode for mode in DnsProxyMode if mode != DnsProxyMode.AUTO]
|
|
69
|
+
)
|
|
70
|
+
|
|
71
|
+
# append RESOLVERS_SUPPORT_ALL_ENCRYPTED
|
|
72
|
+
_res += DnsModeDeterminator.parse_default_resolvers(
|
|
73
|
+
DnsModeDeterminator.RESOLVERS_SUPPORT_ALL_ENCRYPTED,
|
|
74
|
+
[DnsProxyMode.DOT, DnsProxyMode.DOH, DnsProxyMode.DOH3, DnsProxyMode.DOQ],
|
|
75
|
+
)
|
|
76
|
+
|
|
77
|
+
# append RESOLVERS_SUPPORT_ALL_EXCEPT_DOQ
|
|
78
|
+
_res += DnsModeDeterminator.parse_default_resolvers(
|
|
79
|
+
DnsModeDeterminator.RESOLVERS_SUPPORT_ALL_EXCEPT_DOQ,
|
|
80
|
+
[mode for mode in DnsProxyMode if mode != DnsProxyMode.DOQ and mode != DnsProxyMode.AUTO],
|
|
81
|
+
)
|
|
82
|
+
|
|
83
|
+
# append RESOLVERS_SUPPORT_ALL_EXCEPT_DOH3_DOQ
|
|
84
|
+
_res += DnsModeDeterminator.parse_default_resolvers(
|
|
85
|
+
DnsModeDeterminator.RESOLVERS_SUPPORT_ALL_EXCEPT_DOH3_DOQ,
|
|
86
|
+
[
|
|
87
|
+
mode
|
|
88
|
+
for mode in DnsProxyMode
|
|
89
|
+
if mode != DnsProxyMode.DOQ and mode != DnsProxyMode.AUTO and mode != DnsProxyMode.DOH3
|
|
90
|
+
],
|
|
91
|
+
)
|
|
92
|
+
|
|
93
|
+
# append RESOLVERS_SUPPORT_UDP_TCP_DOT
|
|
94
|
+
_res += DnsModeDeterminator.parse_default_resolvers(
|
|
95
|
+
DnsModeDeterminator.RESOLVERS_SUPPORT_UDP_TCP_DOT,
|
|
96
|
+
[
|
|
97
|
+
DnsProxyMode.UDP,
|
|
98
|
+
DnsProxyMode.LAST_RESPONSE,
|
|
99
|
+
DnsProxyMode.TCP,
|
|
100
|
+
DnsProxyMode.TCP_FRAG,
|
|
101
|
+
DnsProxyMode.DOT,
|
|
102
|
+
],
|
|
103
|
+
)
|
|
104
|
+
|
|
105
|
+
# append RESOLVERS_SUPPORT_UDP_TCP_DOH
|
|
106
|
+
_res += DnsModeDeterminator.parse_default_resolvers(
|
|
107
|
+
DnsModeDeterminator.RESOLVERS_SUPPORT_UDP_TCP_DOH,
|
|
108
|
+
[
|
|
109
|
+
DnsProxyMode.UDP,
|
|
110
|
+
DnsProxyMode.LAST_RESPONSE,
|
|
111
|
+
DnsProxyMode.TCP,
|
|
112
|
+
DnsProxyMode.TCP_FRAG,
|
|
113
|
+
DnsProxyMode.DOH,
|
|
114
|
+
],
|
|
115
|
+
)
|
|
116
|
+
|
|
117
|
+
# append RESOLVERS_SUPPORT_ENCRYPTED_EXCEPT_DOQ
|
|
118
|
+
_res += DnsModeDeterminator.parse_default_resolvers(
|
|
119
|
+
DnsModeDeterminator.RESOLVERS_SUPPORT_ENCRYPTED_EXCEPT_DOH3_DOQ, [DnsProxyMode.DOT, DnsProxyMode.DOH]
|
|
120
|
+
)
|
|
121
|
+
|
|
122
|
+
# append RESOLVERS_SUPPORT_ONLY_UNENCRYPTED
|
|
123
|
+
_res += DnsModeDeterminator.parse_default_resolvers(
|
|
124
|
+
DnsModeDeterminator.RESOLVERS_SUPPORT_ONLY_UNENCRYPTED,
|
|
125
|
+
[DnsProxyMode.UDP, DnsProxyMode.TCP, DnsProxyMode.TCP_FRAG, DnsProxyMode.LAST_RESPONSE],
|
|
126
|
+
)
|
|
127
|
+
else:
|
|
128
|
+
_res += DnsModeDeterminator.parse_default_resolvers(
|
|
129
|
+
[x for x in DnsResolvers], [mode for mode in DnsProxyMode if mode != DnsProxyMode.AUTO]
|
|
130
|
+
)
|
|
131
|
+
return _res
|
|
132
|
+
|
|
133
|
+
# resolvers that support UDP/TPC/DoT/DoH/DoH3/DoQ
|
|
134
|
+
RESOLVERS_SUPPORT_ALL: list[DnsResolvers] = [
|
|
135
|
+
DnsResolvers.ADGUARD_1,
|
|
136
|
+
DnsResolvers.ADGUARD_2,
|
|
137
|
+
DnsResolvers.ADGUARD_UNFILTERED_1,
|
|
138
|
+
DnsResolvers.ADGUARD_UNFILTERED_2,
|
|
139
|
+
DnsResolvers.ADGUARD_FAMILY_1,
|
|
140
|
+
DnsResolvers.ADGUARD_FAMILY_2,
|
|
141
|
+
]
|
|
142
|
+
|
|
143
|
+
# resolver that support DoQ/DoH3/DoH/DoT
|
|
144
|
+
RESOLVERS_SUPPORT_ALL_ENCRYPTED: list[DnsResolvers] = [DnsResolvers.NEXTDNS_1, DnsResolvers.NEXTDNS_2]
|
|
145
|
+
|
|
146
|
+
# resolvers that support UDP/TCP/DoT/DoH/DoH3 but no DoQ
|
|
147
|
+
RESOLVERS_SUPPORT_ALL_EXCEPT_DOQ: list[DnsResolvers] = [
|
|
148
|
+
DnsResolvers.CLOUDFLARE_1,
|
|
149
|
+
DnsResolvers.CLOUDFLARE_2,
|
|
150
|
+
DnsResolvers.CLOUDFLARE_SECURITY_1,
|
|
151
|
+
DnsResolvers.CLOUDFLARE_SECURITY_2,
|
|
152
|
+
DnsResolvers.CLOUDFLARE_FAMILY_1,
|
|
153
|
+
DnsResolvers.CLOUDFLARE_FAMILY_2,
|
|
154
|
+
DnsResolvers.GOOGLE_1,
|
|
155
|
+
DnsResolvers.GOOGLE_2,
|
|
156
|
+
]
|
|
157
|
+
|
|
158
|
+
# resolvers that support UDP/TCP/DoT/DoH but no DOH3 and DoQ
|
|
159
|
+
RESOLVERS_SUPPORT_ALL_EXCEPT_DOH3_DOQ: list[DnsResolvers] = [
|
|
160
|
+
DnsResolvers.CLEAN_BROWSING_FAMILY_1,
|
|
161
|
+
DnsResolvers.CLEAN_BROWSING_FAMILY_2,
|
|
162
|
+
DnsResolvers.CLEAN_BROWSING_ADULT_1,
|
|
163
|
+
DnsResolvers.CLEAN_BROWSING_SECURITY_1,
|
|
164
|
+
DnsResolvers.CLEAN_BROWSING_SECURITY_2,
|
|
165
|
+
DnsResolvers.CISCO_1,
|
|
166
|
+
DnsResolvers.CISCO_2,
|
|
167
|
+
DnsResolvers.CISCO_FAMILY_1,
|
|
168
|
+
DnsResolvers.CISCO_FAMILY_2,
|
|
169
|
+
DnsResolvers.CISCO_SANDBOX_1,
|
|
170
|
+
DnsResolvers.CISCO_SANDBOX_2,
|
|
171
|
+
DnsResolvers.QUAD_9_1,
|
|
172
|
+
DnsResolvers.QUAD_9_2,
|
|
173
|
+
DnsResolvers.QUAD_9_EDNS_1,
|
|
174
|
+
DnsResolvers.QUAD_9_EDNS_2,
|
|
175
|
+
DnsResolvers.QUAD_9_UNSECURED_1,
|
|
176
|
+
DnsResolvers.QUAD_9_UNSECURED_2,
|
|
177
|
+
DnsResolvers.YANDEX_1,
|
|
178
|
+
DnsResolvers.YANDEX_2,
|
|
179
|
+
DnsResolvers.YANDEX_SAFE_1,
|
|
180
|
+
DnsResolvers.YANDEX_SAFE_2,
|
|
181
|
+
DnsResolvers.YANDEX_FAMILY_1,
|
|
182
|
+
DnsResolvers.YANDEX_FAMILY_2,
|
|
183
|
+
]
|
|
184
|
+
|
|
185
|
+
# resolvers that support UDP/TCP/DoT
|
|
186
|
+
RESOLVERS_SUPPORT_UDP_TCP_DOT: list[DnsResolvers] = [DnsResolvers.CLEAN_BROWSING_ADULT_2]
|
|
187
|
+
|
|
188
|
+
# resolvers that support UDP/TCP/DoH
|
|
189
|
+
RESOLVERS_SUPPORT_UDP_TCP_DOH: list[DnsResolvers] = [DnsResolvers.CISCO_CHROMIUM]
|
|
190
|
+
|
|
191
|
+
# resolvers that support DoT/DoH
|
|
192
|
+
RESOLVERS_SUPPORT_ENCRYPTED_EXCEPT_DOH3_DOQ: list[DnsResolvers] = [
|
|
193
|
+
DnsResolvers.WIKIMEDIA,
|
|
194
|
+
DnsResolvers.MULLVAD,
|
|
195
|
+
DnsResolvers.MULLVAD_ADBLOCK,
|
|
196
|
+
DnsResolvers.MULLVAD_BASE,
|
|
197
|
+
DnsResolvers.MULLVAD_EXTENDED,
|
|
198
|
+
DnsResolvers.MULLVAD_FAMILY,
|
|
199
|
+
DnsResolvers.MULLVAD_ALL,
|
|
200
|
+
]
|
|
201
|
+
|
|
202
|
+
# resolvers that support UDP/TCP
|
|
203
|
+
RESOLVERS_SUPPORT_ONLY_UNENCRYPTED: list[DnsResolvers] = [DnsResolvers.G_CORE_1, DnsResolvers.G_CORE_2]
|
|
204
|
+
|
|
205
|
+
CUSTOM_RESOLVERS: list[DnsResolver] = parse_custom_resolvers(
|
|
206
|
+
[
|
|
207
|
+
#########################################################
|
|
208
|
+
# #
|
|
209
|
+
# #
|
|
210
|
+
# Add custom DNS servers here #
|
|
211
|
+
# #
|
|
212
|
+
# #
|
|
213
|
+
#########################################################
|
|
214
|
+
# each server need the supported proxy mode, a name, the IP address, and a port
|
|
215
|
+
# e.g. a DoT server under 127.0.0.1:1234
|
|
216
|
+
# (DnsProxyMode.DOT, "My Server", "127.0.0.1", 1234),
|
|
217
|
+
]
|
|
218
|
+
)
|
|
219
|
+
|
|
220
|
+
def __init__(
|
|
221
|
+
self,
|
|
222
|
+
timeout: int,
|
|
223
|
+
censored_domain: str,
|
|
224
|
+
compare_ip_ranges: list[str],
|
|
225
|
+
block_page_ips: bool = False,
|
|
226
|
+
restrict_advertised: bool = True,
|
|
227
|
+
):
|
|
228
|
+
"""
|
|
229
|
+
:param timeout: timeout for DNS requests
|
|
230
|
+
:param censored_domain: censored domain
|
|
231
|
+
:param compare_ip_ranges: ip ranges to compare against
|
|
232
|
+
:param block_page_ips: whether the ip ranges are block pages ips (avoid) or not (match)
|
|
233
|
+
:param restrict_advertised: whether to restrict resolver to what they actually support
|
|
234
|
+
in one of these ranges to be deemed correct
|
|
235
|
+
"""
|
|
236
|
+
|
|
237
|
+
self.timeout = timeout
|
|
238
|
+
self.censored_domain = censored_domain
|
|
239
|
+
self.block_page_ips = block_page_ips
|
|
240
|
+
|
|
241
|
+
self.compare_ip_ranges = []
|
|
242
|
+
for ip_range in compare_ip_ranges:
|
|
243
|
+
try:
|
|
244
|
+
self.compare_ip_ranges.append(ip_network(ip_range))
|
|
245
|
+
except:
|
|
246
|
+
logging.error(f"Could not parse {ip_range} as a valid ip range!")
|
|
247
|
+
raise
|
|
248
|
+
self.censored_request = make_query(censored_domain, "A")
|
|
249
|
+
self.resolvers: list[DnsResolver] = DnsModeDeterminator.generate_resolvers(restrict_advertised)
|
|
250
|
+
|
|
251
|
+
def generate_working_resolver(
|
|
252
|
+
self, mode: DnsProxyMode = None, min_retries: int = 1, max_retries: int = 1, add_sni: bool = True
|
|
253
|
+
):
|
|
254
|
+
"""
|
|
255
|
+
Generator that yields all working DnsResolvers.
|
|
256
|
+
:param mode: Restricts resolver generation to the specified mode.
|
|
257
|
+
:param min_retries: Number of minimum retries to determine success.
|
|
258
|
+
:param max_retries: Number of maximum retries to determine success.
|
|
259
|
+
:param add_sni: Whether to include an SNI extension.
|
|
260
|
+
"""
|
|
261
|
+
all_modes = [
|
|
262
|
+
DnsProxyMode.DOT,
|
|
263
|
+
DnsProxyMode.DOH,
|
|
264
|
+
DnsProxyMode.DOH3,
|
|
265
|
+
DnsProxyMode.DOQ,
|
|
266
|
+
DnsProxyMode.UDP,
|
|
267
|
+
DnsProxyMode.TCP,
|
|
268
|
+
DnsProxyMode.TCP_FRAG,
|
|
269
|
+
DnsProxyMode.LAST_RESPONSE,
|
|
270
|
+
]
|
|
271
|
+
|
|
272
|
+
# Restrict to the given mode or use all
|
|
273
|
+
modes_to_test = [mode] if mode is not None else all_modes
|
|
274
|
+
|
|
275
|
+
# Generate all (mode, resolver) combinations
|
|
276
|
+
resolver_mode_pairs = [
|
|
277
|
+
(_mode, resolver) for _mode in modes_to_test for resolver in self.resolvers if resolver.mode == _mode
|
|
278
|
+
]
|
|
279
|
+
|
|
280
|
+
# Shuffle to ensure full random order across modes and resolvers
|
|
281
|
+
random.shuffle(resolver_mode_pairs)
|
|
282
|
+
|
|
283
|
+
for _mode, resolver in resolver_mode_pairs:
|
|
284
|
+
validate_ip = (
|
|
285
|
+
not add_sni
|
|
286
|
+
if _mode in [DnsProxyMode.DOT, DnsProxyMode.DOH, DnsProxyMode.DOH3, DnsProxyMode.DOQ]
|
|
287
|
+
else True
|
|
288
|
+
)
|
|
289
|
+
yield from self.try_resolver(
|
|
290
|
+
resolver,
|
|
291
|
+
mode=_mode,
|
|
292
|
+
validate_ip=validate_ip,
|
|
293
|
+
min_retries=min_retries,
|
|
294
|
+
max_retries=max_retries,
|
|
295
|
+
add_sni=add_sni,
|
|
296
|
+
)
|
|
297
|
+
|
|
298
|
+
def try_resolver(
|
|
299
|
+
self, resolver, mode: DnsProxyMode, validate_ip: bool, min_retries: int, max_retries: int, add_sni: bool
|
|
300
|
+
):
|
|
301
|
+
"""
|
|
302
|
+
Generator function that determines all reachable DNS resolvers for the specified mode. If validate_ip is True,
|
|
303
|
+
the DNS resolver must respond with a pre-defined IP address.
|
|
304
|
+
"""
|
|
305
|
+
logging.debug(f"Trying to resolve {resolver.name} for mode {mode}")
|
|
306
|
+
success = False
|
|
307
|
+
|
|
308
|
+
for i in range(max_retries):
|
|
309
|
+
resolver.tries += 1
|
|
310
|
+
try:
|
|
311
|
+
answer = DomainResolver.resolve_static(
|
|
312
|
+
mode=mode,
|
|
313
|
+
message=self.censored_request,
|
|
314
|
+
resolver=resolver.address,
|
|
315
|
+
timeout=self.timeout,
|
|
316
|
+
hostname=resolver.hostname,
|
|
317
|
+
add_sni=add_sni,
|
|
318
|
+
path=resolver.path,
|
|
319
|
+
)
|
|
320
|
+
except Exception as e:
|
|
321
|
+
logging.debug(f"Could not resolve to {resolver.name} for mode {mode} with exception {e}")
|
|
322
|
+
else:
|
|
323
|
+
if validate_ip:
|
|
324
|
+
if self.assert_correct_ip(answer):
|
|
325
|
+
logging.debug(f"Successfully resolved to {resolver.name} for mode {mode}")
|
|
326
|
+
resolver.successes += 1
|
|
327
|
+
if i + 1 >= min_retries and resolver.successes / (i + 1) >= 2 / 3:
|
|
328
|
+
success = True
|
|
329
|
+
break
|
|
330
|
+
else:
|
|
331
|
+
logging.debug(f"Incorrect IP from {resolver.name} in mode {mode}")
|
|
332
|
+
else:
|
|
333
|
+
logging.debug(f"Successfully resolved to {resolver.name} for mode {mode}")
|
|
334
|
+
resolver.successes += 1
|
|
335
|
+
if i + 1 >= min_retries and resolver.successes / (i + 1) >= 2 / 3:
|
|
336
|
+
success = True
|
|
337
|
+
break
|
|
338
|
+
if success:
|
|
339
|
+
yield resolver
|
|
340
|
+
|
|
341
|
+
def assert_correct_ip(self, answer: dns.message.Message) -> bool:
|
|
342
|
+
"""
|
|
343
|
+
Determines whether the given DNS response contains the given IP in its answer section.
|
|
344
|
+
:param answer: The DNS response to check.
|
|
345
|
+
"""
|
|
346
|
+
# extract requires record type and class
|
|
347
|
+
|
|
348
|
+
resolved_ips = parse_all_ips(answer)
|
|
349
|
+
for ip in resolved_ips:
|
|
350
|
+
# check if IP lies in range
|
|
351
|
+
for ip_range in self.compare_ip_ranges:
|
|
352
|
+
if ip_address(ip) in ip_range:
|
|
353
|
+
return not self.block_page_ips
|
|
354
|
+
|
|
355
|
+
logging.debug(
|
|
356
|
+
f"None of the resolved IP addresses {resolved_ips} in specified IP ranges {self.compare_ip_ranges}."
|
|
357
|
+
)
|
|
358
|
+
return self.block_page_ips
|
modules/dns/DnsModule.py
ADDED
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
from argparse import ArgumentParser, Namespace
|
|
2
|
+
|
|
3
|
+
from enumerators.DnsProxyMode import DnsProxyMode
|
|
4
|
+
from modules.dns.DnsProxy import DnsProxy
|
|
5
|
+
from modules.Module import Module
|
|
6
|
+
from network.NetworkAddress import NetworkAddress
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class DnsModule(Module):
|
|
10
|
+
"""
|
|
11
|
+
Implements circumvention methods for DNS censorship.
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
def __init__(self, parser: ArgumentParser):
|
|
15
|
+
super().__init__(parser)
|
|
16
|
+
self.proxy: DnsProxy | None = None
|
|
17
|
+
self.server_address: NetworkAddress | None = None
|
|
18
|
+
|
|
19
|
+
@staticmethod
|
|
20
|
+
def register_parameters(parser: ArgumentParser):
|
|
21
|
+
dns_module = parser.add_argument_group("DNS Module")
|
|
22
|
+
|
|
23
|
+
dns_module.add_argument(
|
|
24
|
+
"--dns_mode",
|
|
25
|
+
type=DnsProxyMode,
|
|
26
|
+
default=DnsProxyMode.AUTO,
|
|
27
|
+
help="Mode that the DNS proxy operates in. Default AUTO. If not set to AUTO, still attempts to "
|
|
28
|
+
"automatically determine a resolver for the configured mode. To pre-define the used DNS mode and server "
|
|
29
|
+
"set this flag and the dns_resolver_host and optionally the dns_resolver_port flags.",
|
|
30
|
+
)
|
|
31
|
+
|
|
32
|
+
dns_module.add_argument(
|
|
33
|
+
"--dns_timeout",
|
|
34
|
+
type=int,
|
|
35
|
+
default=3,
|
|
36
|
+
help=f"Connection timeout in seconds. For the {DnsProxyMode.LAST_RESPONSE} mode this timeout will "
|
|
37
|
+
"always be reached. Set this timeout and the timeout of calling application accordingly.",
|
|
38
|
+
)
|
|
39
|
+
|
|
40
|
+
dns_module.add_argument("--dns_host", type=str, default="127.0.0.1", help="Address the proxy server runs on")
|
|
41
|
+
|
|
42
|
+
dns_module.add_argument("--dns_port", type=int, default=5533, help="Port the proxy server runs on")
|
|
43
|
+
|
|
44
|
+
dns_module.add_argument(
|
|
45
|
+
"--dns_resolver_host",
|
|
46
|
+
type=str,
|
|
47
|
+
default=None,
|
|
48
|
+
help="DNS resolver IP. If set, must correspond to the selected dns_mode.",
|
|
49
|
+
)
|
|
50
|
+
|
|
51
|
+
dns_module.add_argument(
|
|
52
|
+
"--dns_resolver_port",
|
|
53
|
+
type=str,
|
|
54
|
+
default=None,
|
|
55
|
+
help="DNS resolver port. If set, must correspond to the selected dns_mode. If unset, port is chosen "
|
|
56
|
+
"based on the chosen or determined mode's standard port",
|
|
57
|
+
)
|
|
58
|
+
|
|
59
|
+
dns_module.add_argument(
|
|
60
|
+
"--dns_censored_domain",
|
|
61
|
+
type=str,
|
|
62
|
+
default="www.google.dj",
|
|
63
|
+
help="A domain name censored in your location. Used to determine working circumventions methods. "
|
|
64
|
+
"Specify together with --dns_censored_domain_ip",
|
|
65
|
+
)
|
|
66
|
+
|
|
67
|
+
dns_module.add_argument(
|
|
68
|
+
"--dns_compare_ip_ranges",
|
|
69
|
+
type=str,
|
|
70
|
+
default="8.8.4.0/24,8.8.8.0/24,8.34.208.0/20,8.35.192.0/20,23.236.48.0/20,23.251.128.0/19,34.0.0.0/15,34.2.0.0/16,34.3.0.0/23,34.3.3.0/24,34.3.4.0/24,34.3.8.0/21,34.3.16.0/20,34.3.32.0/19,34.3.64.0/18,34.4.0.0/14,34.8.0.0/13,34.16.0.0/12,34.32.0.0/11,34.64.0.0/10,34.128.0.0/10,35.184.0.0/13,35.192.0.0/14,35.196.0.0/15,35.198.0.0/16,35.199.0.0/17,35.199.128.0/18,35.200.0.0/13,35.208.0.0/12,35.224.0.0/12,35.240.0.0/13,57.140.192.0/18,64.15.112.0/20,64.233.160.0/19,66.22.228.0/23,66.102.0.0/20,66.249.64.0/19,70.32.128.0/19,72.14.192.0/18,74.114.24.0/21,74.125.0.0/16,104.154.0.0/15,104.196.0.0/14,104.237.160.0/19,107.167.160.0/19,107.178.192.0/18,108.59.80.0/20,108.170.192.0/18,108.177.0.0/17,130.211.0.0/16,136.22.160.0/20,136.22.176.0/21,136.22.184.0/23,136.22.186.0/24,136.124.0.0/15,142.250.0.0/15,146.148.0.0/17,152.65.208.0/22,152.65.214.0/23,152.65.218.0/23,152.65.222.0/23,152.65.224.0/19,162.120.128.0/17,162.216.148.0/22,162.222.176.0/21,172.110.32.0/21,172.217.0.0/16,172.253.0.0/16,173.194.0.0/16,173.255.112.0/20,192.104.160.0/23,192.158.28.0/22,192.178.0.0/15,193.186.4.0/24,199.36.154.0/23,199.36.156.0/24,199.192.112.0/22,199.223.232.0/21,207.223.160.0/20,208.65.152.0/22,208.68.108.0/22,208.81.188.0/22,208.117.224.0/19,209.85.128.0/17,216.58.192.0/19,216.73.80.0/20,216.239.32.0/19,216.252.220.0/22",
|
|
71
|
+
help="A list of IP ranges the resolved IP of the censored domain lies in. The censored domain is "
|
|
72
|
+
"specifiable in --dns_censored_domain.",
|
|
73
|
+
)
|
|
74
|
+
|
|
75
|
+
dns_module.add_argument(
|
|
76
|
+
"--dns_block_page_ips",
|
|
77
|
+
default=False,
|
|
78
|
+
help="Whether the given IP ranges to compare are block page IPs or not. Default is False.",
|
|
79
|
+
)
|
|
80
|
+
|
|
81
|
+
dns_module.add_argument(
|
|
82
|
+
"--dns_add_sni",
|
|
83
|
+
default=True,
|
|
84
|
+
help="Whether or not to include the SNI for encrypted DNS modes. Defaults to True.",
|
|
85
|
+
)
|
|
86
|
+
|
|
87
|
+
dns_module.add_argument(
|
|
88
|
+
"--dns_skip_working_file",
|
|
89
|
+
default=False,
|
|
90
|
+
help="Whether taking the stored working resolver from a file should be skipped. Defaults to False.",
|
|
91
|
+
)
|
|
92
|
+
|
|
93
|
+
def extract_parameters(self, args: Namespace):
|
|
94
|
+
self.server_address = NetworkAddress(args.dns_host, args.dns_port)
|
|
95
|
+
resolver_address = NetworkAddress(args.dns_resolver_host, args.dns_port)
|
|
96
|
+
|
|
97
|
+
self.proxy = DnsProxy(
|
|
98
|
+
proxy_mode=args.dns_mode,
|
|
99
|
+
address=self.server_address,
|
|
100
|
+
timeout=args.dns_timeout,
|
|
101
|
+
dns_resolver_address=resolver_address,
|
|
102
|
+
censored_domain=args.dns_censored_domain,
|
|
103
|
+
compare_ip_ranges=[x for x in args.dns_compare_ip_ranges.split(",")],
|
|
104
|
+
block_page_ips=args.dns_block_page_ips,
|
|
105
|
+
add_sni=args.dns_add_sni,
|
|
106
|
+
skip_working_file=args.dns_skip_working_file,
|
|
107
|
+
)
|
|
108
|
+
|
|
109
|
+
def start(self):
|
|
110
|
+
self.proxy.start()
|
|
111
|
+
|
|
112
|
+
def stop(self):
|
|
113
|
+
self.proxy.continue_processing = False
|