atomicshop 2.20.8__py3-none-any.whl → 2.21.1__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.
Potentially problematic release.
This version of atomicshop might be problematic. Click here for more details.
- atomicshop/__init__.py +1 -1
- atomicshop/mitm/config_static.py +27 -20
- atomicshop/mitm/connection_thread_worker.py +136 -164
- atomicshop/mitm/engines/__parent/responder___parent.py +43 -43
- atomicshop/mitm/engines/__reference_general/responder___reference_general.py +43 -43
- atomicshop/mitm/engines/create_module_template.py +11 -5
- atomicshop/mitm/engines/create_module_template_main_example.py +13 -0
- atomicshop/mitm/import_config.py +174 -22
- atomicshop/mitm/initialize_engines.py +49 -68
- atomicshop/mitm/mitm_main.py +118 -152
- atomicshop/wrappers/socketw/dns_server.py +92 -68
- atomicshop/wrappers/socketw/socket_client.py +1 -1
- atomicshop/wrappers/socketw/socket_wrapper.py +136 -46
- {atomicshop-2.20.8.dist-info → atomicshop-2.21.1.dist-info}/METADATA +1 -1
- {atomicshop-2.20.8.dist-info → atomicshop-2.21.1.dist-info}/RECORD +18 -18
- atomicshop/mitm/engines/create_module_template_example.py +0 -13
- {atomicshop-2.20.8.dist-info → atomicshop-2.21.1.dist-info}/LICENSE.txt +0 -0
- {atomicshop-2.20.8.dist-info → atomicshop-2.21.1.dist-info}/WHEEL +0 -0
- {atomicshop-2.20.8.dist-info → atomicshop-2.21.1.dist-info}/top_level.txt +0 -0
|
@@ -11,7 +11,6 @@ import multiprocessing
|
|
|
11
11
|
from ...print_api import print_api
|
|
12
12
|
from ..loggingw import loggingw
|
|
13
13
|
from ..psutilw import networks
|
|
14
|
-
from ... import queues
|
|
15
14
|
from ...basics import booleans, tracebacks
|
|
16
15
|
from ...file_io import csvs
|
|
17
16
|
|
|
@@ -145,18 +144,15 @@ class DnsServer:
|
|
|
145
144
|
# noinspection PyPep8Naming
|
|
146
145
|
def __init__(
|
|
147
146
|
self,
|
|
148
|
-
|
|
149
|
-
listening_port: int,
|
|
147
|
+
listening_address: str,
|
|
150
148
|
log_directory_path: str,
|
|
151
149
|
backupCount_log_files_x_days: int = 0,
|
|
152
150
|
forwarding_dns_service_ipv4: str = '8.8.8.8',
|
|
153
151
|
forwarding_dns_service_port: int = 53,
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
152
|
+
resolve_by_engine: tuple[bool, list] = (False, None),
|
|
153
|
+
resolve_regular_pass_thru: bool = False,
|
|
154
|
+
resolve_all_domains_to_ipv4: tuple[bool, str] = (False, '127.0.0.1'),
|
|
157
155
|
offline_mode: bool = False,
|
|
158
|
-
tcp_target_server_ipv4: str = '127.0.0.1',
|
|
159
|
-
tcp_resolve_domain_list: list = None,
|
|
160
156
|
request_domain_queue: multiprocessing.Queue = None,
|
|
161
157
|
buffer_size_receive: int = 8192,
|
|
162
158
|
response_ttl: int = 60,
|
|
@@ -169,9 +165,8 @@ class DnsServer:
|
|
|
169
165
|
"""
|
|
170
166
|
Initialize the DNS Server object with all the necessary settings.
|
|
171
167
|
|
|
172
|
-
:param
|
|
173
|
-
Example: '0.0.0.0'. For all interfaces.
|
|
174
|
-
:param listening_port: int: Port number that the DNS Server will listen on.
|
|
168
|
+
:param listening_address: str: Interface and a port that the DNS Server will listen on.
|
|
169
|
+
Example: '0.0.0.0:53'. For all interfaces on port 53.
|
|
175
170
|
:param log_directory_path: str: Path to the directory where the logs will be saved.
|
|
176
171
|
:param backupCount_log_files_x_days: int: How many days the log files will be kept.
|
|
177
172
|
Default is 0, which means that the log files will be kept indefinitely.
|
|
@@ -180,15 +175,14 @@ class DnsServer:
|
|
|
180
175
|
Example: '8.8.8.8'. For Google DNS Service.
|
|
181
176
|
:param forwarding_dns_service_port: int: Port number of the DNS Service that will be used for resolving.
|
|
182
177
|
Default is 53.
|
|
183
|
-
:param
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
:param
|
|
178
|
+
:param resolve_by_engine: tuple(boolean to enable the feature, list of engines).
|
|
179
|
+
True, The list of predefined engines will be used to resolve the domains.
|
|
180
|
+
Each list has a list of specific domains that will be routed to specified destination IPv4 address.
|
|
181
|
+
:param resolve_all_domains_to_ipv4: bool: If the DNS Server should resolve all the domains
|
|
182
|
+
to the provided origin DNS Service without altering the DNS request/response.
|
|
183
|
+
:param resolve_all_domains_to_ipv4: tuple(boolean to enable the feature, string IPv4 of the target).
|
|
184
|
+
True, the DNS Server will route all domains to the specified IPv4.
|
|
187
185
|
:param offline_mode: bool: If the DNS Server should work in offline mode.
|
|
188
|
-
:param tcp_target_server_ipv4: str: IPv4 address of the TCP Server that the specified booleans will resolve
|
|
189
|
-
the domains to.
|
|
190
|
-
:param tcp_resolve_domain_list: list: List of domains that will be resolved to the TCP Server.
|
|
191
|
-
This means that all the requests will be resolved to the specified offline IPv4 address.
|
|
192
186
|
:param request_domain_queue: multiprocessing Queue to pass all the requested domains that hit the DNS
|
|
193
187
|
:param buffer_size_receive: int: Buffer size of the connection while receiving messages.
|
|
194
188
|
:param response_ttl: int, Time to live of the DNS Response that will be returned. Default is 60 seconds.
|
|
@@ -205,17 +199,15 @@ class DnsServer:
|
|
|
205
199
|
You can pass only one of the following: 'logger', 'logging_queue'.
|
|
206
200
|
"""
|
|
207
201
|
|
|
208
|
-
self.
|
|
209
|
-
self.listening_port: int = listening_port
|
|
202
|
+
self.listening_address: str = listening_address
|
|
210
203
|
self.log_directory_path: str = log_directory_path
|
|
204
|
+
self.backupCount_log_files_x_days: int = backupCount_log_files_x_days
|
|
211
205
|
self.forwarding_dns_service_ipv4: str = forwarding_dns_service_ipv4
|
|
212
206
|
self.forwarding_dns_service_port: int = forwarding_dns_service_port
|
|
213
|
-
self.
|
|
214
|
-
self.
|
|
207
|
+
self.resolve_by_engine: tuple[bool, list] = resolve_by_engine
|
|
208
|
+
self.resolve_regular_pass_thru: bool = resolve_regular_pass_thru
|
|
209
|
+
self.resolve_all_domains_to_ipv4: tuple[bool, str] = resolve_all_domains_to_ipv4
|
|
215
210
|
self.offline_mode: bool = offline_mode
|
|
216
|
-
self.resolve_to_tcp_server_only_tcp_resolve_domains: bool = resolve_to_tcp_server_only_tcp_resolve_domains
|
|
217
|
-
self.resolve_to_tcp_server_all_domains: bool = resolve_to_tcp_server_all_domains
|
|
218
|
-
self.resolve_regular: bool = resolve_regular
|
|
219
211
|
self.request_domain_queue: multiprocessing.Queue = request_domain_queue
|
|
220
212
|
self.buffer_size_receive: int = buffer_size_receive
|
|
221
213
|
self.response_ttl: int = response_ttl
|
|
@@ -227,10 +219,27 @@ class DnsServer:
|
|
|
227
219
|
if logger and logging_queue:
|
|
228
220
|
raise ValueError("You can pass only one of the following: 'logger', 'logging_queue'.")
|
|
229
221
|
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
222
|
+
self.listening_interface, listening_port = self.listening_address.split(':')
|
|
223
|
+
self.listening_interface: str
|
|
224
|
+
self.listening_port: int = int(listening_port)
|
|
225
|
+
self.resolve_by_engine_enable, self.engine_list = self.resolve_by_engine
|
|
226
|
+
self.resolve_by_engine_enable: bool
|
|
227
|
+
self.engine_list: list
|
|
228
|
+
self.resolve_all_domains_to_ipv4_enable, self.resolve_all_domains_target = self.resolve_all_domains_to_ipv4
|
|
229
|
+
self.resolve_all_domains_to_ipv4_enable: bool
|
|
230
|
+
self.resolve_all_domains_target: str
|
|
231
|
+
|
|
232
|
+
self.intercept_domain_list: list = list()
|
|
233
|
+
for engine in self.engine_list:
|
|
234
|
+
# If the engine is not a reference engine.
|
|
235
|
+
if engine.engine_name != '__reference_general':
|
|
236
|
+
# Get the domains from the engine.
|
|
237
|
+
self.intercept_domain_list.extend(engine.domain_list)
|
|
238
|
+
|
|
239
|
+
# If the engine has no_sni section enabled, get the domains from it.
|
|
240
|
+
if engine.no_sni.serve_domain_on_address_enable:
|
|
241
|
+
for domain, ip_address in engine.no_sni.serve_domain_on_address_dict.items():
|
|
242
|
+
self.intercept_domain_list.append(domain)
|
|
234
243
|
|
|
235
244
|
# Settings for static DNS Responses in offline mode.
|
|
236
245
|
self.offline_route_ipv4: str = '10.10.10.10'
|
|
@@ -270,7 +279,7 @@ class DnsServer:
|
|
|
270
279
|
add_timedfile_with_internal_queue=True,
|
|
271
280
|
formatter_streamhandler='DEFAULT',
|
|
272
281
|
formatter_filehandler='DEFAULT',
|
|
273
|
-
backupCount=backupCount_log_files_x_days
|
|
282
|
+
backupCount=self.backupCount_log_files_x_days
|
|
274
283
|
)
|
|
275
284
|
elif logger:
|
|
276
285
|
# Create child logger for the provided logger with the module's name.
|
|
@@ -288,10 +297,9 @@ class DnsServer:
|
|
|
288
297
|
try:
|
|
289
298
|
booleans.is_only_1_true_in_list(
|
|
290
299
|
booleans_list_of_tuples=[
|
|
291
|
-
(self.
|
|
292
|
-
|
|
293
|
-
(self.
|
|
294
|
-
(self.resolve_regular, 'resolve_regular')
|
|
300
|
+
(self.resolve_by_engine_enable, 'resolve_by_engine_enable'),
|
|
301
|
+
(self.resolve_regular_pass_thru, 'resolve_regular_pass_thru'),
|
|
302
|
+
(self.resolve_all_domains_to_ipv4_enable, 'resolve_all_domains_to_ipv4_enable')
|
|
295
303
|
],
|
|
296
304
|
raise_if_all_false=True
|
|
297
305
|
)
|
|
@@ -345,19 +353,19 @@ class DnsServer:
|
|
|
345
353
|
known_a_records_ipv4_dict: dict = dict()
|
|
346
354
|
|
|
347
355
|
# Check if 'route_to_tcp_server_only_engine_domains' was set to 'True' and output message accordingly.
|
|
348
|
-
if self.
|
|
349
|
-
message = "Routing
|
|
356
|
+
if self.resolve_by_engine_enable:
|
|
357
|
+
message = "Routing engine domains to the specified IPv4 targets."
|
|
350
358
|
print_api(message, logger=self.logger)
|
|
351
359
|
|
|
352
|
-
message = f"Current
|
|
360
|
+
message = f"Current all engines domains: {self.intercept_domain_list}"
|
|
353
361
|
print_api(message, logger=self.logger, color='blue')
|
|
354
362
|
|
|
355
|
-
if self.
|
|
356
|
-
message = "Routing all domains to
|
|
363
|
+
if self.resolve_all_domains_to_ipv4_enable:
|
|
364
|
+
message = f"Routing all domains to the specified target: [{self.resolve_all_domains_target}]"
|
|
357
365
|
print_api(message, logger=self.logger, color='blue')
|
|
358
366
|
|
|
359
|
-
if self.
|
|
360
|
-
message = f"Routing all domains to
|
|
367
|
+
if self.resolve_regular_pass_thru:
|
|
368
|
+
message = f"Routing all domains to the specified Origin DNS Service: {self.forwarding_dns_service_ipv4}:{self.forwarding_dns_service_port}"
|
|
361
369
|
print_api(message, logger=self.logger, color='blue')
|
|
362
370
|
|
|
363
371
|
# The list that will hold all the threads that can be joined later
|
|
@@ -462,10 +470,10 @@ class DnsServer:
|
|
|
462
470
|
if qtype_string == "A":
|
|
463
471
|
# Check if 'resolve_to_tcp_server_only_tcp_resolve_domains' is set to 'True'.
|
|
464
472
|
# If so, we need to check if the incoming domain contain any of the domains in the list.
|
|
465
|
-
if self.
|
|
473
|
+
if self.resolve_by_engine_enable:
|
|
466
474
|
# If current query domain (+ subdomains) CONTAIN any of the domains from modules config
|
|
467
475
|
# files and current request contains "A" (IPv4) record.
|
|
468
|
-
if any(x in question_domain for x in self.
|
|
476
|
+
if any(x in question_domain for x in self.intercept_domain_list):
|
|
469
477
|
# If incoming domain contains any of the 'engine_domains' then domain will
|
|
470
478
|
# be forwarded to our TCP Server.
|
|
471
479
|
forward_to_tcp_server = True
|
|
@@ -474,12 +482,12 @@ class DnsServer:
|
|
|
474
482
|
|
|
475
483
|
# If 'route_to_tcp_server_all_domains' was set to 'False' in 'config.ini' file then
|
|
476
484
|
# we'll forward all 'A' records domains to the Built-in TCP Server.
|
|
477
|
-
if self.
|
|
485
|
+
if self.resolve_all_domains_to_ipv4_enable:
|
|
478
486
|
forward_to_tcp_server = True
|
|
479
487
|
|
|
480
488
|
# If 'regular_resolving' was set to 'True' in 'config.ini' file then
|
|
481
489
|
# we'll forward all 'A' records domains to the Live DNS Service.
|
|
482
|
-
if self.
|
|
490
|
+
if self.resolve_regular_pass_thru:
|
|
483
491
|
forward_to_tcp_server = False
|
|
484
492
|
|
|
485
493
|
# If incoming record is not an "A" record, then it will not be forwarded to our TCP Server.
|
|
@@ -488,9 +496,33 @@ class DnsServer:
|
|
|
488
496
|
|
|
489
497
|
# If 'forward_to_tcp_server' is 'True' we'll resolve the record with our TCP Server IP address.
|
|
490
498
|
if forward_to_tcp_server:
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
499
|
+
if self.resolve_by_engine_enable:
|
|
500
|
+
for engine in self.engine_list:
|
|
501
|
+
# Check if the incoming domain contain any of the domains in the list.
|
|
502
|
+
if any(x in question_domain for x in engine.domain_list):
|
|
503
|
+
# Get the target IP address from the engine.
|
|
504
|
+
resolved_target_ipv4 = engine.dns_target
|
|
505
|
+
|
|
506
|
+
if engine.no_sni.get_from_dns:
|
|
507
|
+
# If the request is forwarded to TCP server, then we'll put the domain in the domain queue.
|
|
508
|
+
# self.request_domain_queue.put(question_domain)
|
|
509
|
+
self.request_domain_queue.put(question_domain)
|
|
510
|
+
|
|
511
|
+
break
|
|
512
|
+
|
|
513
|
+
if engine.no_sni.serve_domain_on_address_enable:
|
|
514
|
+
if question_domain in engine.no_sni.serve_domain_on_address_dict:
|
|
515
|
+
ip_port_address: str = engine.no_sni.serve_domain_on_address_dict[question_domain]
|
|
516
|
+
target_ip = ip_port_address.split(':')[0]
|
|
517
|
+
resolved_target_ipv4 = target_ip
|
|
518
|
+
break
|
|
519
|
+
|
|
520
|
+
if self.resolve_all_domains_to_ipv4_enable:
|
|
521
|
+
# Assign the target IPv4 address to the resolved target IPv4 variable.
|
|
522
|
+
resolved_target_ipv4 = self.resolve_all_domains_target
|
|
523
|
+
|
|
524
|
+
# Put the domain in the domain queue.
|
|
525
|
+
self.request_domain_queue.put(question_domain)
|
|
494
526
|
|
|
495
527
|
# Make DNS response that will refer TCP traffic to our server
|
|
496
528
|
dns_built_response = DNSRecord(
|
|
@@ -499,7 +531,7 @@ class DnsServer:
|
|
|
499
531
|
# q=DNSQuestion(question_domain),
|
|
500
532
|
q=dns_object.q,
|
|
501
533
|
a=RR(question_domain,
|
|
502
|
-
rdata=A(
|
|
534
|
+
rdata=A(resolved_target_ipv4),
|
|
503
535
|
ttl=self.response_ttl)
|
|
504
536
|
)
|
|
505
537
|
# Encode the response that was built above to legit DNS Response
|
|
@@ -883,19 +915,15 @@ class DnsServer:
|
|
|
883
915
|
|
|
884
916
|
# noinspection PyPep8Naming
|
|
885
917
|
def start_dns_server_multiprocessing_worker(
|
|
886
|
-
|
|
887
|
-
listening_port: int,
|
|
918
|
+
listening_address: str,
|
|
888
919
|
log_directory_path: str,
|
|
889
920
|
backupCount_log_files_x_days: int,
|
|
890
921
|
forwarding_dns_service_ipv4: str,
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
922
|
+
forwarding_dns_service_port: int,
|
|
923
|
+
resolve_by_engine: tuple[bool, list],
|
|
924
|
+
resolve_regular_pass_thru: bool,
|
|
925
|
+
resolve_all_domains_to_ipv4: tuple[bool, str],
|
|
895
926
|
offline_mode: bool,
|
|
896
|
-
resolve_to_tcp_server_only_tcp_resolve_domains: bool,
|
|
897
|
-
resolve_to_tcp_server_all_domains: bool,
|
|
898
|
-
resolve_regular: bool,
|
|
899
927
|
cache_timeout_minutes: int,
|
|
900
928
|
request_domain_queue: multiprocessing.Queue,
|
|
901
929
|
logging_queue: multiprocessing.Queue,
|
|
@@ -907,19 +935,15 @@ def start_dns_server_multiprocessing_worker(
|
|
|
907
935
|
|
|
908
936
|
try:
|
|
909
937
|
dns_server_instance = DnsServer(
|
|
910
|
-
|
|
911
|
-
listening_port=listening_port,
|
|
938
|
+
listening_address=listening_address,
|
|
912
939
|
log_directory_path=log_directory_path,
|
|
913
940
|
backupCount_log_files_x_days=backupCount_log_files_x_days,
|
|
914
941
|
forwarding_dns_service_ipv4=forwarding_dns_service_ipv4,
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
942
|
+
forwarding_dns_service_port=forwarding_dns_service_port,
|
|
943
|
+
resolve_by_engine=resolve_by_engine,
|
|
944
|
+
resolve_regular_pass_thru=resolve_regular_pass_thru,
|
|
945
|
+
resolve_all_domains_to_ipv4=resolve_all_domains_to_ipv4,
|
|
919
946
|
offline_mode=offline_mode,
|
|
920
|
-
resolve_to_tcp_server_only_tcp_resolve_domains=resolve_to_tcp_server_only_tcp_resolve_domains,
|
|
921
|
-
resolve_to_tcp_server_all_domains=resolve_to_tcp_server_all_domains,
|
|
922
|
-
resolve_regular=resolve_regular,
|
|
923
947
|
cache_timeout_minutes=cache_timeout_minutes,
|
|
924
948
|
request_domain_queue=request_domain_queue,
|
|
925
949
|
logging_queue=logging_queue,
|
|
@@ -28,7 +28,7 @@ class SocketClient:
|
|
|
28
28
|
service_port: int,
|
|
29
29
|
tls: bool = False,
|
|
30
30
|
connection_ip=None,
|
|
31
|
-
dns_servers_list=None,
|
|
31
|
+
dns_servers_list: list[str] = None,
|
|
32
32
|
logger: logging.Logger = None,
|
|
33
33
|
custom_pem_client_certificate_file_path: str = None,
|
|
34
34
|
enable_sslkeylogfile_env_to_client_ssl_context: bool = False
|
|
@@ -5,7 +5,9 @@ from pathlib import Path
|
|
|
5
5
|
import logging
|
|
6
6
|
import socket
|
|
7
7
|
import multiprocessing
|
|
8
|
+
import queue
|
|
8
9
|
|
|
10
|
+
from ...mitm import initialize_engines
|
|
9
11
|
from ..psutilw import networks
|
|
10
12
|
from ..certauthw import certauthw
|
|
11
13
|
from ..loggingw import loggingw
|
|
@@ -32,7 +34,6 @@ SNI_QUEUE = queues.NonBlockQueue()
|
|
|
32
34
|
class SocketWrapper:
|
|
33
35
|
def __init__(
|
|
34
36
|
self,
|
|
35
|
-
listening_address_list: list[str],
|
|
36
37
|
forwarding_dns_service_ipv4_list___only_for_localhost: list = None,
|
|
37
38
|
ca_certificate_name: str = None,
|
|
38
39
|
ca_certificate_filepath: str = None,
|
|
@@ -69,15 +70,14 @@ class SocketWrapper:
|
|
|
69
70
|
exceptions_logger: loggingw.ExceptionCsvLogger = None,
|
|
70
71
|
statistics_logs_directory: str = None,
|
|
71
72
|
request_domain_from_dns_server_queue: multiprocessing.Queue = None,
|
|
72
|
-
|
|
73
|
-
|
|
73
|
+
no_engine_usage_enable: bool = False,
|
|
74
|
+
no_engines_listening_address_list: list[str] = None,
|
|
75
|
+
engines_list: list[initialize_engines.ModuleCategory] = None
|
|
74
76
|
):
|
|
75
77
|
"""
|
|
76
78
|
Socket Wrapper class that will be used to create sockets, listen on them, accept connections and send them to
|
|
77
79
|
new threads.
|
|
78
80
|
|
|
79
|
-
:param listening_address_list: list, of ips+ports that will be listened on.
|
|
80
|
-
Example: ['0.0.0.0:443', '0.0.0.0:80']
|
|
81
81
|
:param ca_certificate_name: CA certificate name.
|
|
82
82
|
:param ca_certificate_filepath: CA certificate file path with '.pem' extension.
|
|
83
83
|
:param ca_certificate_crt_filepath: CA certificate file path with '.crt' extension.
|
|
@@ -166,19 +166,24 @@ class SocketWrapper:
|
|
|
166
166
|
to get the domain name that was requested from the DNS server (atomicshop.wrappers.socketw.dns_server).
|
|
167
167
|
This is used to get the domain name that got to the DNS server and set it to the socket in case SNI
|
|
168
168
|
was empty (in the SNIHandler class to set the 'server_hostname' for the socket).
|
|
169
|
-
:param
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
169
|
+
:param no_engine_usage_enable: boolean, if True, 'engines_list' will be used to listen on the addresses,
|
|
170
|
+
but the "no_engines_listening_address_list" parameter will be used instead.
|
|
171
|
+
:param no_engines_listening_address_list: list, of ips+ports that will be listened on.
|
|
172
|
+
Example: ['0.0.0.0:443', '0.0.0.0:80']
|
|
173
|
+
:param engines_list: list, of engines that will be used to process the requests. Structure of engine_config.toml:
|
|
174
|
+
[engine]
|
|
175
|
+
"domains" = ["example.com"]
|
|
176
|
+
|
|
177
|
+
[mtls]
|
|
178
|
+
# "subdomain.domain.com" = "file_name_in_current_dir.pem"
|
|
179
|
+
|
|
180
|
+
[no_sni]
|
|
181
|
+
#get_from_dns = 1 # Blocking, the accept function will wait until the domain is received from DNS.
|
|
182
|
+
#get_from_engine = 0
|
|
183
|
+
#try_to_get_from_dns_on_empty_get_from_engine = 0 # Non-blocking, on empty DNS server queue, accept() will connect to the domain from below.
|
|
184
|
+
#"domain" = "example.com"
|
|
179
185
|
"""
|
|
180
186
|
|
|
181
|
-
self.listening_address_list: list[str] = listening_address_list
|
|
182
187
|
self.ca_certificate_name: str = ca_certificate_name
|
|
183
188
|
self.ca_certificate_filepath: str = ca_certificate_filepath
|
|
184
189
|
self.ca_certificate_crt_filepath: str = ca_certificate_crt_filepath
|
|
@@ -211,8 +216,21 @@ class SocketWrapper:
|
|
|
211
216
|
self.forwarding_dns_service_ipv4_list___only_for_localhost = (
|
|
212
217
|
forwarding_dns_service_ipv4_list___only_for_localhost)
|
|
213
218
|
self.request_domain_from_dns_server_queue: multiprocessing.Queue = request_domain_from_dns_server_queue
|
|
214
|
-
self.
|
|
215
|
-
self.
|
|
219
|
+
self.no_engine_usage_enable: bool = no_engine_usage_enable
|
|
220
|
+
self.no_engines_listening_address_list: list[str] = no_engines_listening_address_list
|
|
221
|
+
self.engines_list: list[initialize_engines.ModuleCategory] = engines_list
|
|
222
|
+
|
|
223
|
+
# dictionary of engines that will be used to find the engine name. Example:
|
|
224
|
+
# [{'this_is_engine_name': ['example.com', 'example.org']},
|
|
225
|
+
# {'this_is_engine_name2': ['example2.com', 'example2.org']}]
|
|
226
|
+
self.engines_domains: dict = dict()
|
|
227
|
+
for engine in self.engines_list:
|
|
228
|
+
self.engines_domains[engine.engine_name] = engine.domain_list
|
|
229
|
+
|
|
230
|
+
if engine.no_sni.serve_domain_on_address_enable:
|
|
231
|
+
for domain, ip_port_address in engine.no_sni.serve_domain_on_address_dict.items():
|
|
232
|
+
if domain not in self.engines_domains[engine.engine_name]:
|
|
233
|
+
self.engines_domains[engine.engine_name].append(domain)
|
|
216
234
|
|
|
217
235
|
self.socket_object = None
|
|
218
236
|
|
|
@@ -275,6 +293,13 @@ class SocketWrapper:
|
|
|
275
293
|
"You can't set both [sni_use_default_callback_function = True] and [sni_custom_callback_function]."
|
|
276
294
|
raise SocketWrapperConfigurationValuesError(message)
|
|
277
295
|
|
|
296
|
+
if self.no_engine_usage_enable and not self.no_engines_listening_address_list:
|
|
297
|
+
message = "You set [no_engine_usage_enable = True], but you didn't set [no_engines_listening_address_list]."
|
|
298
|
+
raise SocketWrapperConfigurationValuesError(message)
|
|
299
|
+
elif not self.no_engine_usage_enable and not self.engines_list:
|
|
300
|
+
message = "You set [no_engine_usage_enable = False], but you didn't set [engines_list]."
|
|
301
|
+
raise SocketWrapperConfigurationValuesError(message)
|
|
302
|
+
|
|
278
303
|
try:
|
|
279
304
|
booleans.is_only_1_true_in_list(
|
|
280
305
|
booleans_list_of_tuples=[
|
|
@@ -322,7 +347,16 @@ class SocketWrapper:
|
|
|
322
347
|
print_api(message, color='red', logger=self.logger)
|
|
323
348
|
return 1
|
|
324
349
|
|
|
325
|
-
|
|
350
|
+
# Checking if listening address is in use.
|
|
351
|
+
listening_check_list: list = list()
|
|
352
|
+
if self.engines_list:
|
|
353
|
+
for engine in self.engines_list:
|
|
354
|
+
for address in engine.tcp_listening_address_list:
|
|
355
|
+
if address not in listening_check_list:
|
|
356
|
+
listening_check_list.append(address)
|
|
357
|
+
else:
|
|
358
|
+
listening_check_list = self.no_engines_listening_address_list
|
|
359
|
+
port_in_use = networks.get_processes_using_port_list(listening_check_list)
|
|
326
360
|
if port_in_use:
|
|
327
361
|
error_messages: list = list()
|
|
328
362
|
for port, process_info in port_in_use.items():
|
|
@@ -399,26 +433,74 @@ class SocketWrapper:
|
|
|
399
433
|
|
|
400
434
|
return self.socket_object
|
|
401
435
|
|
|
402
|
-
def
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
port = int(port_str)
|
|
412
|
-
socket_by_port = self.create_socket_ipv4_tcp(
|
|
413
|
-
ip_address, port)
|
|
414
|
-
|
|
415
|
-
self.listening_sockets.append(socket_by_port)
|
|
436
|
+
def start_listening_sockets(
|
|
437
|
+
self,
|
|
438
|
+
reference_function_name,
|
|
439
|
+
reference_function_args=(),
|
|
440
|
+
pass_function_reference_to_thread: bool = True
|
|
441
|
+
):
|
|
442
|
+
"""
|
|
443
|
+
Start listening sockets with parameters.
|
|
444
|
+
"""
|
|
416
445
|
|
|
417
|
-
|
|
446
|
+
# If engines were passed, we will use the listening addresses from the engines.
|
|
447
|
+
if not self.no_engine_usage_enable:
|
|
448
|
+
for engine in self.engines_list:
|
|
449
|
+
# Start all the regular listening interfaces.
|
|
450
|
+
for address in engine.tcp_listening_address_list:
|
|
451
|
+
ip_address, port_str = address.split(':')
|
|
452
|
+
port = int(port_str)
|
|
453
|
+
socket_by_port = self.create_socket_ipv4_tcp(ip_address, port)
|
|
454
|
+
threading.Thread(
|
|
455
|
+
target=self.listening_socket_loop,
|
|
456
|
+
args=(socket_by_port, engine, reference_function_name,
|
|
457
|
+
reference_function_args, pass_function_reference_to_thread),
|
|
458
|
+
name=f"acceptor-{engine.engine_name}-{ip_address}:{port}",
|
|
459
|
+
daemon=True
|
|
460
|
+
).start()
|
|
461
|
+
|
|
462
|
+
# Start all the interfaces configured in the no_sni section.
|
|
463
|
+
if engine.no_sni.serve_domain_on_address_enable:
|
|
464
|
+
for domain, ip_port_address in engine.no_sni.serve_domain_on_address_dict.items():
|
|
465
|
+
ip_address, port_str = ip_port_address.split(':')
|
|
466
|
+
port = int(port_str)
|
|
467
|
+
socket_by_port = self.create_socket_ipv4_tcp(ip_address, port)
|
|
468
|
+
threading.Thread(
|
|
469
|
+
target=self.listening_socket_loop,
|
|
470
|
+
args=(socket_by_port, engine, reference_function_name,
|
|
471
|
+
reference_function_args, pass_function_reference_to_thread),
|
|
472
|
+
name=f"acceptor-{engine.engine_name}-{ip_address}:{port}",
|
|
473
|
+
daemon=True
|
|
474
|
+
).start()
|
|
475
|
+
else:
|
|
476
|
+
# If no engines were passed, we will use the listening addresses from the configuration.
|
|
477
|
+
for address in self.no_engines_listening_address_list:
|
|
478
|
+
ip_address, port_str = address.split(':')
|
|
479
|
+
port = int(port_str)
|
|
480
|
+
socket_by_port = self.create_socket_ipv4_tcp(ip_address, port)
|
|
481
|
+
threading.Thread(
|
|
482
|
+
target=self.listening_socket_loop,
|
|
483
|
+
args=(socket_by_port, None, reference_function_name,
|
|
484
|
+
reference_function_args, pass_function_reference_to_thread),
|
|
485
|
+
name=f"acceptor-{ip_address}:{port}",
|
|
486
|
+
daemon=True
|
|
487
|
+
).start()
|
|
488
|
+
|
|
489
|
+
# # Creating a socket for each port in the list set in configuration file
|
|
490
|
+
# for address in self.listening_address_list:
|
|
491
|
+
# ip_address, port_str = address.split(':')
|
|
492
|
+
# port = int(port_str)
|
|
493
|
+
# socket_by_port = self.create_socket_ipv4_tcp(
|
|
494
|
+
# ip_address, port)
|
|
495
|
+
#
|
|
496
|
+
# self.listening_sockets.append(socket_by_port)
|
|
497
|
+
|
|
498
|
+
def listening_socket_loop(
|
|
418
499
|
self,
|
|
500
|
+
listening_socket_object: socket.socket,
|
|
501
|
+
engine: initialize_engines.ModuleCategory,
|
|
419
502
|
reference_function_name,
|
|
420
503
|
reference_function_args=(),
|
|
421
|
-
listening_socket_list: list = None,
|
|
422
504
|
pass_function_reference_to_thread: bool = True
|
|
423
505
|
):
|
|
424
506
|
"""
|
|
@@ -426,6 +508,8 @@ class SocketWrapper:
|
|
|
426
508
|
The boolean variable was declared True in the beginning of the script and will be set to False if the process
|
|
427
509
|
will be killed or closed.
|
|
428
510
|
|
|
511
|
+
:param listening_socket_object: listening socket that was created with bind.
|
|
512
|
+
:param engine: ModuleCategory.
|
|
429
513
|
:param reference_function_name: callable, function reference that you want to execute when client
|
|
430
514
|
socket received by 'accept()' and connection has been made.
|
|
431
515
|
:param reference_function_args: tuple, that will be passed to 'function_reference' when it will be called.
|
|
@@ -439,17 +523,13 @@ class SocketWrapper:
|
|
|
439
523
|
process_name: string, process name that was gathered from the socket.
|
|
440
524
|
is_tls: boolean, if the socket is SSL/TLS.
|
|
441
525
|
domain_from_dns_server: string, domain that was requested from DNS server.
|
|
442
|
-
:param listening_socket_list: list, of sockets that you want to listen on.
|
|
443
526
|
:param pass_function_reference_to_thread: boolean, that sets if 'function_reference' will be
|
|
444
527
|
executed as is, or passed to thread. 'function_reference' can include passing to a thread,
|
|
445
528
|
but you don't have to use it, since SocketWrapper can do it for you.
|
|
446
529
|
:return:
|
|
447
530
|
"""
|
|
448
531
|
|
|
449
|
-
|
|
450
|
-
if not listening_socket_list and self.listening_sockets:
|
|
451
|
-
# Then assign 'self.listening_sockets'.
|
|
452
|
-
listening_socket_list = self.listening_sockets
|
|
532
|
+
listening_sockets: list = [listening_socket_object]
|
|
453
533
|
|
|
454
534
|
while True:
|
|
455
535
|
try:
|
|
@@ -457,7 +537,7 @@ class SocketWrapper:
|
|
|
457
537
|
# operating system types: Windows / Linux / BSD.
|
|
458
538
|
# To accept connection, we don't need "writable" and "exceptional", since "readable" holds the currently
|
|
459
539
|
# connected socket.
|
|
460
|
-
readable, writable, exceptional = select.select(
|
|
540
|
+
readable, writable, exceptional = select.select(listening_sockets, [], [])
|
|
461
541
|
listening_socket_object = readable[0]
|
|
462
542
|
|
|
463
543
|
# Get the domain queue. Tried using "Queue.Queue" object, but it stomped the SSL Sockets
|
|
@@ -465,11 +545,21 @@ class SocketWrapper:
|
|
|
465
545
|
domain_from_dns_server = None
|
|
466
546
|
if self.request_domain_from_dns_server_queue is not None:
|
|
467
547
|
# domain_from_dns_server = self.request_domain_from_dns_server_queue.get()
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
548
|
+
if engine.no_sni.get_from_dns:
|
|
549
|
+
domain_from_dns_server = self.request_domain_from_dns_server_queue.get()
|
|
550
|
+
|
|
551
|
+
if engine.no_sni.serve_domain_on_address_enable:
|
|
552
|
+
# try:
|
|
553
|
+
# domain_from_dns_server = self.request_domain_from_dns_server_queue.get_nowait()
|
|
554
|
+
# except queue.Empty:
|
|
555
|
+
# domain_from_dns_server = engine.no_sni['domain']
|
|
556
|
+
|
|
557
|
+
listening_ip, listening_port = listening_socket_object.getsockname()
|
|
558
|
+
for domain, ip_port_address in engine.no_sni.serve_domain_on_address_dict.items():
|
|
559
|
+
ip_address: str = ip_port_address.split(':')[0]
|
|
560
|
+
if ip_address == listening_ip:
|
|
561
|
+
domain_from_dns_server = domain
|
|
562
|
+
break
|
|
473
563
|
|
|
474
564
|
self.logger.info(f"Requested domain from DNS Server: {domain_from_dns_server}")
|
|
475
565
|
|