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,141 @@
|
|
|
1
|
+
from enum import Enum
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class DnsResolvers(Enum):
|
|
5
|
+
"""
|
|
6
|
+
Ip addresses of public DNS resolvers.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
# Initial list https://en.wikipedia.org/wiki/Public_recursive_name_server
|
|
10
|
+
|
|
11
|
+
# Adguard https://adguard-dns.io/en/public-dns.html
|
|
12
|
+
ADGUARD_1 = ("94.140.14.14", "dns.adguard-dns.com", "/dns-query")
|
|
13
|
+
ADGUARD_2 = ("94.140.15.15", "dns.adguard-dns.com", "/dns-query")
|
|
14
|
+
ADGUARD_FAMILY_1 = ("94.140.14.15", "family.adguard-dns.com", "/dns-query")
|
|
15
|
+
ADGUARD_FAMILY_2 = ("94.140.15.16", "family.adguard-dns.com", "/dns-query")
|
|
16
|
+
ADGUARD_UNFILTERED_1 = ("94.140.14.140", "unfiltered.adguard-dns.com", "/dns-query")
|
|
17
|
+
ADGUARD_UNFILTERED_2 = ("94.140.14.141", "unfiltered.adguard-dns.com", "/dns-query")
|
|
18
|
+
|
|
19
|
+
# CleanBrowsing https://cleanbrowsing.org/filters
|
|
20
|
+
CLEAN_BROWSING_FAMILY_1 = ("185.228.168.168", "family-filter-dns.cleanbrowsing.org", "/doh/family-filter/")
|
|
21
|
+
CLEAN_BROWSING_FAMILY_2 = ("185.228.169.168", "family-filter-dns.cleanbrowsing.org", "/doh/family-filter/")
|
|
22
|
+
CLEAN_BROWSING_ADULT_1 = ("185.228.168.10", "adult-filter-dns.cleanbrowsing.org", "/doh/adult-filter/")
|
|
23
|
+
CLEAN_BROWSING_ADULT_2 = ("185.228.169.11", "adult-filter-dns.cleanbrowsing.org", "/doh/adult-filter/")
|
|
24
|
+
CLEAN_BROWSING_SECURITY_1 = ("185.228.168.9", "security-filter-dns.cleanbrowsing.org", "/doh/security-filter/")
|
|
25
|
+
CLEAN_BROWSING_SECURITY_2 = ("185.228.169.9", "security-filter-dns.cleanbrowsing.org", "/doh/security-filter/")
|
|
26
|
+
|
|
27
|
+
# Cloudflare https://developers.cloudflare.com/1.1.1.1/ip-addresses/
|
|
28
|
+
CLOUDFLARE_1 = ("1.1.1.1", "one.one.one.one", "/dns-query")
|
|
29
|
+
CLOUDFLARE_2 = ("1.0.0.1", "1dot1dot1dot1.cloudflare-dns.com", "/dns-query")
|
|
30
|
+
CLOUDFLARE_SECURITY_1 = ("1.1.1.2", "security.cloudflare-dns.com", "/dns-query")
|
|
31
|
+
CLOUDFLARE_SECURITY_2 = ("1.0.0.2", "security.cloudflare-dns.com", "/dns-query")
|
|
32
|
+
CLOUDFLARE_FAMILY_1 = ("1.1.1.3", "family.cloudflare-dns.com", "/dns-query")
|
|
33
|
+
CLOUDFLARE_FAMILY_2 = ("1.0.0.3", "family.cloudflare-dns.com", "/dns-query")
|
|
34
|
+
CLOUDFLARE_MOZILLA_1 = ("162.159.61.4", "mozilla.cloudflare-dns.com", "/dns-query")
|
|
35
|
+
CLOUDFLARE_MOZILLA_2 = ("172.64.41.4", "mozilla.cloudflare-dns.com", "/dns-query")
|
|
36
|
+
CLOUDFLARE_CHROMIUM_1 = ("172.64.41.3", "chrome.cloudflare-dns.com", "/dns-query")
|
|
37
|
+
CLOUDFLARE_CHROMIUM_2 = ("162.159.61.3", "chrome.cloudflare-dns.com", "/dns-query")
|
|
38
|
+
|
|
39
|
+
# https://developers.google.com/speed/public-dns
|
|
40
|
+
GOOGLE_1 = ("8.8.8.8", "dns.google", "/dns-query")
|
|
41
|
+
GOOGLE_2 = ("8.8.4.4", "dns.google", "/dns-query")
|
|
42
|
+
|
|
43
|
+
# Gcore https://gcore.com/public-dns
|
|
44
|
+
G_CORE_1 = ("95.85.95.85", "", "/dns-query")
|
|
45
|
+
G_CORE_2 = ("2.56.220.2", "", "/dns-query")
|
|
46
|
+
|
|
47
|
+
# Mullvad https://mullvad.net/en/help/dns-over-https-and-dns-over-tls
|
|
48
|
+
MULLVAD = ("194.242.2.2", "dns.mullvad.net", "/dns-query")
|
|
49
|
+
MULLVAD_ADBLOCK = ("194.242.2.3", "adblock.dns.mullvad.net", "/dns-query")
|
|
50
|
+
MULLVAD_BASE = ("194.242.2.4", "base.dns.mullvad.net", "/dns-query")
|
|
51
|
+
MULLVAD_EXTENDED = ("194.242.2.5", "extended.dns.mullvad.net", "/dns-query")
|
|
52
|
+
MULLVAD_FAMILY = ("194.242.2.6", "family.dns.mullvad.net", "/dns-query")
|
|
53
|
+
MULLVAD_ALL = ("194.242.2.9", "all.dns.mullvad.net", "/dns-query")
|
|
54
|
+
|
|
55
|
+
# Cisco https://umbrella.cisco.com/blog/enhancing-support-dns-encryption-with-dns-over-https
|
|
56
|
+
CISCO_1 = ("208.67.222.222", "dns.opendns.com", "/dns-query")
|
|
57
|
+
CISCO_2 = ("208.67.220.220", "dns.umbrella.com", "/dns-query")
|
|
58
|
+
CISCO_FAMILY_1 = ("208.67.222.123", "familyshield.opendns.com", "/dns-query")
|
|
59
|
+
CISCO_FAMILY_2 = ("208.67.220.123", "familyshield.opendns.com", "/dns-query")
|
|
60
|
+
CISCO_SANDBOX_1 = ("208.67.222.2", "sandbox.opendns.com", "/dns-query")
|
|
61
|
+
CISCO_SANDBOX_2 = ("208.67.220.2", "sandbox.opendns.com", "/dns-query")
|
|
62
|
+
CISCO_CHROMIUM = ("146.112.41.2", "doh.opendns.com", "/dns-query")
|
|
63
|
+
|
|
64
|
+
# Quad 9 https://www.quad9.net/support/faq/
|
|
65
|
+
QUAD_9_1 = ("9.9.9.9", "dns.quad9.net", "/dns-query")
|
|
66
|
+
QUAD_9_2 = ("149.112.112.112", "dns.quad9.net", "/dns-query")
|
|
67
|
+
QUAD_9_EDNS_1 = ("9.9.9.11", "dns11.quad9.net", "/dns-query")
|
|
68
|
+
QUAD_9_EDNS_2 = ("149.112.112.11", "dns11.quad9.net", "/dns-query")
|
|
69
|
+
QUAD_9_UNSECURED_1 = ("9.9.9.10", "dns10.quad9.net", "/dns-query")
|
|
70
|
+
QUAD_9_UNSECURED_2 = ("149.112.112.10", "dns10.quad9.net", "/dns-query")
|
|
71
|
+
|
|
72
|
+
# wikimedia https://meta.wikimedia.org/wiki/Wikimedia_DNS
|
|
73
|
+
WIKIMEDIA = ("185.71.138.138", "wikimedia-dns.org", "/dns-query")
|
|
74
|
+
|
|
75
|
+
# Yandex https://dns.yandex.com/
|
|
76
|
+
YANDEX_1 = ("77.88.8.8", "common.dot.dns.yandex.net", "/dns-query")
|
|
77
|
+
YANDEX_2 = ("77.88.8.1", "common.dot.dns.yandex.net", "/dns-query")
|
|
78
|
+
YANDEX_SAFE_1 = ("77.88.8.88", "safe.dot.dns.yandex.net", "/dns-query")
|
|
79
|
+
YANDEX_SAFE_2 = ("77.88.8.2", "safe.dot.dns.yandex.net", "/dns-query")
|
|
80
|
+
YANDEX_FAMILY_1 = ("77.88.8.7", "family.dot.dns.yandex.net", "/dns-query")
|
|
81
|
+
YANDEX_FAMILY_2 = ("77.88.8.3", "family.dot.dns.yandex.net", "/dns-query")
|
|
82
|
+
|
|
83
|
+
# NextDNS https://nextdns.io/ Firefox and Chromium use both
|
|
84
|
+
NEXTDNS_1 = ("194.45.101.249", "dns.nextdns.io", "/dns-query")
|
|
85
|
+
NEXTDNS_2 = ("217.146.22.163", "dns.nextdns.io", "/dns-query")
|
|
86
|
+
|
|
87
|
+
def __new__(cls, ip, hostname, path):
|
|
88
|
+
obj = object.__new__(cls)
|
|
89
|
+
obj._value_ = ip # The actual enum value is the IP address
|
|
90
|
+
obj.hostname = hostname # Store hostname
|
|
91
|
+
obj.path = path # Store path
|
|
92
|
+
return obj
|
|
93
|
+
|
|
94
|
+
def __str__(self):
|
|
95
|
+
return f"{self.name} ({self.value}): {self.hostname}"
|
|
96
|
+
|
|
97
|
+
def is_default(self):
|
|
98
|
+
"""
|
|
99
|
+
Returns true if we consider the DNS server to be default. DpyProxy favors "default" DNS resolvers in its AUTO
|
|
100
|
+
selection mode.
|
|
101
|
+
"""
|
|
102
|
+
return self in [
|
|
103
|
+
DnsResolvers.ADGUARD_UNFILTERED_1,
|
|
104
|
+
DnsResolvers.ADGUARD_UNFILTERED_2,
|
|
105
|
+
DnsResolvers.CLOUDFLARE_1,
|
|
106
|
+
DnsResolvers.CLOUDFLARE_2,
|
|
107
|
+
DnsResolvers.GOOGLE_1,
|
|
108
|
+
DnsResolvers.GOOGLE_2,
|
|
109
|
+
DnsResolvers.G_CORE_1,
|
|
110
|
+
DnsResolvers.G_CORE_2,
|
|
111
|
+
DnsResolvers.MULLVAD,
|
|
112
|
+
DnsResolvers.CISCO_1,
|
|
113
|
+
DnsResolvers.CISCO_2,
|
|
114
|
+
DnsResolvers.QUAD_9_UNSECURED_1,
|
|
115
|
+
DnsResolvers.QUAD_9_UNSECURED_2,
|
|
116
|
+
DnsResolvers.YANDEX_1,
|
|
117
|
+
DnsResolvers.YANDEX_2,
|
|
118
|
+
DnsResolvers.NEXTDNS_1,
|
|
119
|
+
DnsResolvers.NEXTDNS_2,
|
|
120
|
+
DnsResolvers.CISCO_CHROMIUM,
|
|
121
|
+
]
|
|
122
|
+
|
|
123
|
+
def is_family(self):
|
|
124
|
+
"""
|
|
125
|
+
Returns true if the resolver filters content it considers adult. DpyProxy favors resolvers that do not apply
|
|
126
|
+
family filters in its AUTO selection mode.
|
|
127
|
+
"""
|
|
128
|
+
return self in [
|
|
129
|
+
DnsResolvers.ADGUARD_FAMILY_1,
|
|
130
|
+
DnsResolvers.ADGUARD_FAMILY_2,
|
|
131
|
+
DnsResolvers.CLEAN_BROWSING_FAMILY_1,
|
|
132
|
+
DnsResolvers.CLEAN_BROWSING_FAMILY_1,
|
|
133
|
+
DnsResolvers.CLOUDFLARE_FAMILY_1,
|
|
134
|
+
DnsResolvers.CLOUDFLARE_FAMILY_2,
|
|
135
|
+
DnsResolvers.MULLVAD_FAMILY,
|
|
136
|
+
DnsResolvers.MULLVAD_ALL,
|
|
137
|
+
DnsResolvers.CISCO_FAMILY_1,
|
|
138
|
+
DnsResolvers.CISCO_FAMILY_2,
|
|
139
|
+
DnsResolvers.YANDEX_FAMILY_1,
|
|
140
|
+
DnsResolvers.YANDEX_FAMILY_2,
|
|
141
|
+
]
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
from enum import Enum
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class HttpMethod(Enum):
|
|
5
|
+
GET = "GET"
|
|
6
|
+
HEAD = "HEAD"
|
|
7
|
+
OPTIONS = "OPTIONS"
|
|
8
|
+
TRACE = "TRACE"
|
|
9
|
+
PUT = "PUT"
|
|
10
|
+
POST = "POST"
|
|
11
|
+
DELETE = "DELETE"
|
|
12
|
+
PATCH = "PATCH"
|
|
13
|
+
CONNECT = "CONNECT"
|
|
14
|
+
|
|
15
|
+
@staticmethod
|
|
16
|
+
def all():
|
|
17
|
+
return [e.value for e in HttpMethod]
|
enumerators/Modules.py
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
from argparse import ArgumentParser
|
|
2
|
+
from enum import Enum
|
|
3
|
+
|
|
4
|
+
from modules.dns.DnsModule import DnsModule
|
|
5
|
+
from modules.http.HttpModule import HttpModule
|
|
6
|
+
from modules.tls.TlsModule import TlsModule
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class Modules(Enum):
|
|
10
|
+
"""
|
|
11
|
+
All optional modules the proxy supports
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
TLS = "TLS"
|
|
15
|
+
DNS = "DNS"
|
|
16
|
+
HTTP = "HTTP"
|
|
17
|
+
|
|
18
|
+
def create_module(self, parser: ArgumentParser):
|
|
19
|
+
"""
|
|
20
|
+
Created a new Module object based the enumerator type.
|
|
21
|
+
"""
|
|
22
|
+
if self == Modules.TLS:
|
|
23
|
+
return TlsModule(parser)
|
|
24
|
+
elif self == Modules.DNS:
|
|
25
|
+
return DnsModule(parser)
|
|
26
|
+
elif self == Modules.HTTP:
|
|
27
|
+
return HttpModule(parser)
|
|
28
|
+
|
|
29
|
+
def get_class(self):
|
|
30
|
+
"""
|
|
31
|
+
Returns the class of the module.
|
|
32
|
+
"""
|
|
33
|
+
if self == Modules.TLS:
|
|
34
|
+
return TlsModule
|
|
35
|
+
elif self == Modules.DNS:
|
|
36
|
+
return DnsModule
|
|
37
|
+
elif self == Modules.HTTP:
|
|
38
|
+
return HttpModule
|
enumerators/Port.py
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
from enum import Enum
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class TcpProxyMode(Enum):
|
|
5
|
+
"""
|
|
6
|
+
Modes the proxy can operate in
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
HTTP = "HTTP"
|
|
10
|
+
HTTPS = "HTTPS"
|
|
11
|
+
SNI = "SNI"
|
|
12
|
+
SOCKSv4 = "SOCKSv4"
|
|
13
|
+
SOCKSv4a = "SOCKSv4a"
|
|
14
|
+
SOCKSv5 = "SOCKSv5"
|
|
15
|
+
|
|
16
|
+
def __str__(self):
|
|
17
|
+
return self.name
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
from enum import Enum
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class TlsVersion(Enum):
|
|
5
|
+
"""
|
|
6
|
+
Various TLS versions that can be used to overwrite the TLS version in the TLS record.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
DEFAULT = "XXXX"
|
|
10
|
+
TLS10 = "0301"
|
|
11
|
+
TLS11 = "0302"
|
|
12
|
+
TLS12 = "0303"
|
|
13
|
+
TLS13_DRAFT_28 = "7F1C"
|
|
14
|
+
TLS13 = "0304"
|
|
15
|
+
SSL3 = "0300"
|
|
16
|
+
SSL2 = "0302"
|
|
17
|
+
INVALID_SMALLER = "0000"
|
|
18
|
+
INVALID_BIGGER = "2020"
|
|
19
|
+
|
|
20
|
+
def __str__(self):
|
|
21
|
+
return f"{self.name}: {self.value}"
|
enumerators/__init__.py
ADDED
|
File without changes
|
exception/__init__.py
ADDED
|
File without changes
|
main.py
ADDED
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
|
|
3
|
+
import argparse
|
|
4
|
+
import logging
|
|
5
|
+
import sys
|
|
6
|
+
import threading
|
|
7
|
+
import time
|
|
8
|
+
from argparse import ArgumentParser
|
|
9
|
+
|
|
10
|
+
from enumerators.Modules import Modules
|
|
11
|
+
from modules.dns.DnsModule import DnsModule
|
|
12
|
+
from modules.Module import Module
|
|
13
|
+
from modules.tls.TlsModule import TlsModule
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def extract_activated_modules(parser: ArgumentParser) -> list[Module]:
|
|
17
|
+
|
|
18
|
+
def list_of_modules(arg):
|
|
19
|
+
if arg is None or len(arg) == 0:
|
|
20
|
+
return []
|
|
21
|
+
return list(map(lambda x: Modules.__getitem__(x), arg.split(",")))
|
|
22
|
+
|
|
23
|
+
general = parser.add_argument_group("Standard options")
|
|
24
|
+
|
|
25
|
+
general.add_argument("-h", "--help", action="help", help="Show this help message and exit")
|
|
26
|
+
|
|
27
|
+
general.add_argument("--debug", default=False, action=argparse.BooleanOptionalAction, help="Turns on debugging")
|
|
28
|
+
|
|
29
|
+
general.add_argument(
|
|
30
|
+
"--disabled_modules",
|
|
31
|
+
type=list_of_modules,
|
|
32
|
+
# choices=Modules,
|
|
33
|
+
default=[Modules.HTTP],
|
|
34
|
+
help="List of proxy modules to disable. By default, only the HTTP module is disabled.",
|
|
35
|
+
)
|
|
36
|
+
|
|
37
|
+
# only parse arguments of basic module to determine used modules
|
|
38
|
+
args = parser.parse_known_args()[0]
|
|
39
|
+
|
|
40
|
+
# change logging
|
|
41
|
+
if args.debug:
|
|
42
|
+
logging.basicConfig(stream=sys.stderr, level=logging.DEBUG)
|
|
43
|
+
else:
|
|
44
|
+
logging.basicConfig(stream=sys.stderr, level=logging.INFO)
|
|
45
|
+
|
|
46
|
+
# crate and set enabled modules
|
|
47
|
+
return list(map(lambda x: x.create_module(parser), [x for x in Modules if x not in args.disabled_modules]))
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
def main():
|
|
51
|
+
"""
|
|
52
|
+
Starts the proxy with all enabled modules.
|
|
53
|
+
"""
|
|
54
|
+
# initialize argumentParser
|
|
55
|
+
parser = argparse.ArgumentParser(
|
|
56
|
+
description="Proxy for circumventing DPI-based censorship.", usage="%(prog)s [options]", add_help=False
|
|
57
|
+
)
|
|
58
|
+
|
|
59
|
+
# parse options of other modules
|
|
60
|
+
for otherModule in Modules:
|
|
61
|
+
otherModule.get_class().register_parameters(parser)
|
|
62
|
+
|
|
63
|
+
activated_modules = extract_activated_modules(parser)
|
|
64
|
+
|
|
65
|
+
parsed_args = parser.parse_args()
|
|
66
|
+
|
|
67
|
+
for otherModule in activated_modules:
|
|
68
|
+
otherModule.extract_parameters(parsed_args)
|
|
69
|
+
|
|
70
|
+
# if tls module and DNS module are running provide dns server to tls module
|
|
71
|
+
dns_module = next((mod for mod in activated_modules if isinstance(mod, DnsModule)), None)
|
|
72
|
+
tls_module = next((mod for mod in activated_modules if isinstance(mod, TlsModule)), None)
|
|
73
|
+
|
|
74
|
+
if dns_module and tls_module:
|
|
75
|
+
logging.info("DNS Module and TLS module found. Setting DNS server for TLS Module")
|
|
76
|
+
tls_module.set_dns_server(dns_module.server_address)
|
|
77
|
+
tls_module.extract_parameters(parsed_args)
|
|
78
|
+
|
|
79
|
+
# start modules
|
|
80
|
+
for otherModule in activated_modules:
|
|
81
|
+
threading.Thread(target=otherModule.start).start()
|
|
82
|
+
|
|
83
|
+
try:
|
|
84
|
+
while True:
|
|
85
|
+
time.sleep(1000)
|
|
86
|
+
except KeyboardInterrupt:
|
|
87
|
+
logging.info("Received Keyboard Interrupt. Cancelling modules and exiting!")
|
|
88
|
+
for otherModule in activated_modules:
|
|
89
|
+
otherModule.stop()
|
|
90
|
+
sys.exit(0)
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
if __name__ == "__main__":
|
|
94
|
+
main()
|
modules/Module.py
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
from abc import ABC, abstractmethod
|
|
2
|
+
from argparse import ArgumentParser, Namespace
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class Module(ABC):
|
|
6
|
+
"""
|
|
7
|
+
Abstract class for a module. A module abstracts certain proxy functionality such as TLS alterations or DNS
|
|
8
|
+
alterations.
|
|
9
|
+
They can be started and stopped independently.
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
def __init__(self, parser: ArgumentParser):
|
|
13
|
+
self.parser = parser
|
|
14
|
+
|
|
15
|
+
@staticmethod
|
|
16
|
+
@abstractmethod
|
|
17
|
+
def register_parameters(parser: ArgumentParser):
|
|
18
|
+
"""
|
|
19
|
+
Registers the module's CLI parameters.
|
|
20
|
+
"""
|
|
21
|
+
pass
|
|
22
|
+
|
|
23
|
+
@abstractmethod
|
|
24
|
+
def extract_parameters(self, arguments: Namespace):
|
|
25
|
+
"""
|
|
26
|
+
Extracts the module's registered CLI parameters from ArgumentParser's output.
|
|
27
|
+
"""
|
|
28
|
+
|
|
29
|
+
@abstractmethod
|
|
30
|
+
def start(
|
|
31
|
+
self,
|
|
32
|
+
):
|
|
33
|
+
"""
|
|
34
|
+
Starts the module. Without calling this function the module should not do anything. Should only be called after
|
|
35
|
+
registering and extracting the module's CLI parameters.
|
|
36
|
+
"""
|
|
37
|
+
pass
|
|
38
|
+
|
|
39
|
+
@abstractmethod
|
|
40
|
+
def stop(self):
|
|
41
|
+
"""
|
|
42
|
+
Stops the module from accepting any future connections. Running connections are continued.
|
|
43
|
+
Does nothing if the module has not been started before.
|
|
44
|
+
"""
|
|
45
|
+
pass
|
modules/__init__.py
ADDED
|
File without changes
|