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.
Files changed (59) hide show
  1. dpyproxy/__init__.py +1 -0
  2. dpyproxy/__main__.py +4 -0
  3. dpyproxy-2.2.0.dist-info/METADATA +296 -0
  4. dpyproxy-2.2.0.dist-info/RECORD +59 -0
  5. dpyproxy-2.2.0.dist-info/WHEEL +4 -0
  6. dpyproxy-2.2.0.dist-info/entry_points.txt +2 -0
  7. dpyproxy-2.2.0.dist-info/licenses/LICENSE +201 -0
  8. enumerators/DnsProxyMode.py +39 -0
  9. enumerators/DnsResolvers.py +141 -0
  10. enumerators/HttpMethod.py +17 -0
  11. enumerators/Modules.py +38 -0
  12. enumerators/Port.py +11 -0
  13. enumerators/TcpProxyMode.py +17 -0
  14. enumerators/TlsVersion.py +21 -0
  15. enumerators/__init__.py +0 -0
  16. exception/DnsException.py +7 -0
  17. exception/ParserException.py +7 -0
  18. exception/__init__.py +0 -0
  19. main.py +94 -0
  20. modules/Module.py +45 -0
  21. modules/__init__.py +0 -0
  22. modules/dns/DnsModeDeterminator.py +358 -0
  23. modules/dns/DnsModule.py +113 -0
  24. modules/dns/DnsProxy.py +277 -0
  25. modules/dns/DnsResolver.py +18 -0
  26. modules/dns/__init__.py +0 -0
  27. modules/http/HttpModule.py +69 -0
  28. modules/http/HttpStrategies.py +849 -0
  29. modules/http/HttpUtils.py +94 -0
  30. modules/http/__init__.py +0 -0
  31. modules/tls/TcpProxy.py +106 -0
  32. modules/tls/TlsModule.py +173 -0
  33. modules/tls/__init__.py +0 -0
  34. network/DomainResolver.py +472 -0
  35. network/NetworkAddress.py +10 -0
  36. network/WrappedSocket.py +97 -0
  37. network/__init__.py +0 -0
  38. network/protocols/Dns.py +62 -0
  39. network/protocols/Http.py +109 -0
  40. network/protocols/Socksv4.py +70 -0
  41. network/protocols/Socksv5.py +106 -0
  42. network/protocols/Tls.py +113 -0
  43. network/protocols/__init__.py +0 -0
  44. network/tcp/Forwarder.py +203 -0
  45. network/tcp/TcpConnectionHandler.py +264 -0
  46. network/tcp/WrappedTcpSocket.py +30 -0
  47. network/tcp/__init__.py +0 -0
  48. network/udp/__init__.py +0 -0
  49. test/Sink.py +23 -0
  50. test/__init__.py +0 -0
  51. test/test_dns.py +98 -0
  52. test/test_http.py +57 -0
  53. test/test_tls.py +63 -0
  54. util/DnsAutoModeRuntimeMeasurement.py +62 -0
  55. util/DnsReachabilityCollector.py +160 -0
  56. util/DnsResolversDomainResolver.py +36 -0
  57. util/Util.py +62 -0
  58. util/__init__.py +0 -0
  59. 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
@@ -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