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,160 @@
1
+ # Determines and outputs the reachability of all DNS servers and circumvention methods's
2
+ # specified in DnsModeDeterminator.py
3
+ import logging
4
+ import os
5
+
6
+ # hack to add parent to pythonpath
7
+ import sys
8
+ import time
9
+
10
+ sys.path.append(os.path.join(os.path.dirname(__file__), ".."))
11
+
12
+ from modules.dns.DnsModeDeterminator import DnsModeDeterminator
13
+
14
+ TIMEOUT = 5
15
+ CENSORED_DOMAIN = "www.google.dj"
16
+ MIN_RETRIES = 3
17
+ MAX_RETRIES = 20
18
+ ADD_SNI = True
19
+ RESTRICT_ADVERTISED = True
20
+ BLOCK_PAGE_IPS = False
21
+
22
+ # wikipedia ranges https://wikitech.wikimedia.org/wiki/IP_and_AS_allocations
23
+ WIKIMEDIA_RANGES = [
24
+ "185.15.56.0/22",
25
+ "91.198.174.0/24",
26
+ "195.200.68.0/24",
27
+ "193.46.90.0/24",
28
+ "198.35.26.0/23",
29
+ "208.80.152.0/22",
30
+ "103.102.166.0/24",
31
+ ]
32
+
33
+ # https://www.gstatic.com/ipranges/goog.json
34
+ GOOGLE_RANGES = [
35
+ "8.8.4.0/24",
36
+ "8.8.8.0/24",
37
+ "8.34.208.0/20",
38
+ "8.35.192.0/20",
39
+ "23.236.48.0/20",
40
+ "23.251.128.0/19",
41
+ "34.0.0.0/15",
42
+ "34.2.0.0/16",
43
+ "34.3.0.0/23",
44
+ "34.3.3.0/24",
45
+ "34.3.4.0/24",
46
+ "34.3.8.0/21",
47
+ "34.3.16.0/20",
48
+ "34.3.32.0/19",
49
+ "34.3.64.0/18",
50
+ "34.4.0.0/14",
51
+ "34.8.0.0/13",
52
+ "34.16.0.0/12",
53
+ "34.32.0.0/11",
54
+ "34.64.0.0/10",
55
+ "34.128.0.0/10",
56
+ "35.184.0.0/13",
57
+ "35.192.0.0/14",
58
+ "35.196.0.0/15",
59
+ "35.198.0.0/16",
60
+ "35.199.0.0/17",
61
+ "35.199.128.0/18",
62
+ "35.200.0.0/13",
63
+ "35.208.0.0/12",
64
+ "35.224.0.0/12",
65
+ "35.240.0.0/13",
66
+ "57.140.192.0/18",
67
+ "64.15.112.0/20",
68
+ "64.233.160.0/19",
69
+ "66.22.228.0/23",
70
+ "66.102.0.0/20",
71
+ "66.249.64.0/19",
72
+ "70.32.128.0/19",
73
+ "72.14.192.0/18",
74
+ "74.114.24.0/21",
75
+ "74.125.0.0/16",
76
+ "104.154.0.0/15",
77
+ "104.196.0.0/14",
78
+ "104.237.160.0/19",
79
+ "107.167.160.0/19",
80
+ "107.178.192.0/18",
81
+ "108.59.80.0/20",
82
+ "108.170.192.0/18",
83
+ "108.177.0.0/17",
84
+ "130.211.0.0/16",
85
+ "136.22.160.0/20",
86
+ "136.22.176.0/21",
87
+ "136.22.184.0/23",
88
+ "136.22.186.0/24",
89
+ "136.124.0.0/15",
90
+ "142.250.0.0/15",
91
+ "146.148.0.0/17",
92
+ "152.65.208.0/22",
93
+ "152.65.214.0/23",
94
+ "152.65.218.0/23",
95
+ "152.65.222.0/23",
96
+ "152.65.224.0/19",
97
+ "162.120.128.0/17",
98
+ "162.216.148.0/22",
99
+ "162.222.176.0/21",
100
+ "172.110.32.0/21",
101
+ "172.217.0.0/16",
102
+ "172.253.0.0/16",
103
+ "173.194.0.0/16",
104
+ "173.255.112.0/20",
105
+ "192.104.160.0/23",
106
+ "192.158.28.0/22",
107
+ "192.178.0.0/15",
108
+ "193.186.4.0/24",
109
+ "199.36.154.0/23",
110
+ "199.36.156.0/24",
111
+ "199.192.112.0/22",
112
+ "199.223.232.0/21",
113
+ "207.223.160.0/20",
114
+ "208.65.152.0/22",
115
+ "208.68.108.0/22",
116
+ "208.81.188.0/22",
117
+ "208.117.224.0/19",
118
+ "209.85.128.0/17",
119
+ "216.58.192.0/19",
120
+ "216.73.80.0/20",
121
+ "216.239.32.0/19",
122
+ "216.252.220.0/22",
123
+ ]
124
+
125
+ IRAN_BLOCK_PAGES = ["10.10.34.34", "10.10.34.35", "10.10.34.36"]
126
+
127
+
128
+ def main():
129
+ print(",".join(GOOGLE_RANGES))
130
+ return
131
+ logging.basicConfig(stream=sys.stderr, level=logging.DEBUG)
132
+
133
+ _det = DnsModeDeterminator(
134
+ timeout=TIMEOUT,
135
+ censored_domain=CENSORED_DOMAIN,
136
+ compare_ip_ranges=GOOGLE_RANGES,
137
+ block_page_ips=BLOCK_PAGE_IPS,
138
+ restrict_advertised=RESTRICT_ADVERTISED,
139
+ )
140
+
141
+ print("Generating working resolvers... might take a while!")
142
+ _time = time.time()
143
+
144
+ for resolver in [
145
+ x for x in _det.generate_working_resolver(min_retries=MIN_RETRIES, max_retries=MAX_RETRIES, add_sni=ADD_SNI)
146
+ ]:
147
+ print(resolver)
148
+
149
+ print(f"Time taken: {format_time(time.time() - _time)}")
150
+
151
+
152
+ def format_time(unix_timestamp: float) -> str:
153
+ """
154
+ Formats unix timestamp to hh:mm:ss format
155
+ """
156
+ return time.strftime("%H:%M:%S", time.gmtime(unix_timestamp))
157
+
158
+
159
+ if __name__ == "__main__":
160
+ main()
@@ -0,0 +1,36 @@
1
+ import os
2
+
3
+ # hack to add parent to pythonpath
4
+ import sys
5
+
6
+ from dns.message import make_query
7
+
8
+ sys.path.append(os.path.join(os.path.dirname(__file__), ".."))
9
+
10
+ from enumerators.DnsProxyMode import DnsProxyMode
11
+ from enumerators.DnsResolvers import DnsResolvers
12
+ from network.DomainResolver import DomainResolver
13
+ from network.NetworkAddress import NetworkAddress
14
+ from util.Util import parse_all_ips
15
+
16
+ TIMEOUT = 5
17
+
18
+
19
+ def main():
20
+ local_address = NetworkAddress("127.0.0.53", 53)
21
+ local_resolver = DomainResolver(DnsProxyMode.UDP, local_address, TIMEOUT, "")
22
+ for resolver in DnsResolvers:
23
+ if resolver.hostname == "":
24
+ continue # No need to test Gcore
25
+
26
+ message = make_query(resolver.hostname, "A")
27
+ try:
28
+ answer = local_resolver.resolve_udp_static(message, resolver=local_address, timeout=TIMEOUT)
29
+ resolved_ips = parse_all_ips(answer)
30
+ if resolver.value not in resolved_ips:
31
+ print(f"Ip mismatch between {resolver} and {resolved_ips}")
32
+ except Exception as e:
33
+ print(f"Could not determine IP of {resolver} due to {e}")
34
+
35
+
36
+ main()
util/Util.py ADDED
@@ -0,0 +1,62 @@
1
+ import logging
2
+ import socket
3
+
4
+ import dns
5
+ from dns.rdatatype import RdataType
6
+
7
+
8
+ def is_valid_ipv4_address(ip_address: str) -> bool:
9
+ """
10
+ Returns whether the given string is a valid ipv4 address.
11
+ :param ip_address: String to check for ipv4 validity
12
+ :return: Whether the given string is a valid ip address
13
+ """
14
+ try:
15
+ socket.inet_aton(ip_address)
16
+ return True
17
+ except socket.error:
18
+ return False
19
+
20
+
21
+ def parse_all_ips(answer: dns.message.Message) -> list[str]:
22
+ resolved_ips = []
23
+ _name = ""
24
+ _rdclass = ""
25
+ _rdtype = ""
26
+
27
+ try:
28
+ _name = answer.question[0].name
29
+ _rdclass = answer.question[0].rdclass
30
+ _rdtype = answer.question[0].rdtype
31
+
32
+ for record in answer.find_rrset(answer.answer, _name, _rdclass, _rdtype):
33
+ try:
34
+ ip = record.address
35
+ resolved_ips += [ip]
36
+ except Exception as e:
37
+ logging.error(f"Could not extract IP from DNS response with exception {e}:\n{record}")
38
+ continue
39
+ except Exception as e:
40
+ if answer is not None:
41
+ try:
42
+ # Try CNAME backup
43
+ cname = answer.find_rrset(answer.answer, _name, _rdclass, RdataType.CNAME)
44
+ _name = str(cname[0])
45
+
46
+ for record in answer.find_rrset(answer.answer, _name, _rdclass, _rdtype):
47
+ try:
48
+ ip = record.address
49
+ resolved_ips += [ip]
50
+ except Exception as e:
51
+ logging.error(f"Could not extract IP from DNS response with exception {e}:\n{record}")
52
+ continue
53
+ except Exception as e:
54
+ logging.error(
55
+ f"Could not extract IP from DNS response with exception {e}:\n{_name}, {_rdclass}, {_rdtype}; "
56
+ f"{answer.answer}"
57
+ )
58
+ else:
59
+ logging.error(
60
+ f"Could not extract IP from DNS response with exception {e}:\n{_name}, {_rdclass}, {_rdtype}; None"
61
+ )
62
+ return resolved_ips
util/__init__.py ADDED
File without changes
util/constants.py ADDED
@@ -0,0 +1,8 @@
1
+ TLS_1_0_HEADER = b"\x16\x03\x01"
2
+ TLS_1_1_HEADER = b"\x16\x03\x02"
3
+ TLS_1_2_HEADER = b"\x16\x03\x03"
4
+
5
+ SOCKSv4_HEADER = b"\x04"
6
+ SOCKSv5_HEADER = b"\x05"
7
+
8
+ STANDARD_SOCKET_RECEIVE_SIZE = 4096