atomicshop 2.21.1__py3-none-any.whl → 3.0.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.
Potentially problematic release.
This version of atomicshop might be problematic. Click here for more details.
- atomicshop/__init__.py +1 -1
- atomicshop/basics/multiprocesses.py +228 -30
- atomicshop/dns.py +2 -0
- atomicshop/mitm/config_static.py +2 -1
- atomicshop/mitm/engines/create_module_template.py +2 -7
- atomicshop/mitm/import_config.py +30 -26
- atomicshop/mitm/initialize_engines.py +9 -24
- atomicshop/mitm/mitm_main.py +187 -59
- atomicshop/networks.py +448 -0
- atomicshop/wrappers/ctyping/setup_device.py +466 -0
- atomicshop/wrappers/dockerw/dockerw.py +17 -21
- atomicshop/wrappers/mongodbw/mongodbw.py +1 -0
- atomicshop/wrappers/psutilw/{networks.py → psutil_networks.py} +3 -1
- atomicshop/wrappers/pywin32w/wmis/msft_netipaddress.py +76 -0
- atomicshop/wrappers/pywin32w/wmis/win32_networkadapterconfiguration.py +262 -0
- atomicshop/wrappers/pywin32w/wmis/win32networkadapter.py +51 -82
- atomicshop/wrappers/pywin32w/wmis/wmi_helpers.py +235 -0
- atomicshop/wrappers/socketw/accepter.py +15 -1
- atomicshop/wrappers/socketw/creator.py +7 -1
- atomicshop/wrappers/socketw/dns_server.py +33 -39
- atomicshop/wrappers/socketw/exception_wrapper.py +20 -11
- atomicshop/wrappers/socketw/socket_wrapper.py +29 -78
- atomicshop/wrappers/winregw/winreg_network.py +20 -0
- {atomicshop-2.21.1.dist-info → atomicshop-3.0.0.dist-info}/METADATA +2 -1
- {atomicshop-2.21.1.dist-info → atomicshop-3.0.0.dist-info}/RECORD +28 -24
- atomicshop/wrappers/pywin32w/wmis/helpers.py +0 -131
- {atomicshop-2.21.1.dist-info → atomicshop-3.0.0.dist-info}/LICENSE.txt +0 -0
- {atomicshop-2.21.1.dist-info → atomicshop-3.0.0.dist-info}/WHEEL +0 -0
- {atomicshop-2.21.1.dist-info → atomicshop-3.0.0.dist-info}/top_level.txt +0 -0
|
@@ -2,12 +2,21 @@ from . import exception_wrapper
|
|
|
2
2
|
|
|
3
3
|
|
|
4
4
|
@exception_wrapper.connection_exception_decorator
|
|
5
|
-
def accept_connection(
|
|
5
|
+
def accept_connection(
|
|
6
|
+
socket_object,
|
|
7
|
+
domain_from_dns_server: str = None,
|
|
8
|
+
print_kwargs: dict = None
|
|
9
|
+
):
|
|
6
10
|
"""
|
|
7
11
|
Accept connection from client.
|
|
8
12
|
This function is wrapped with exception wrapper.
|
|
9
13
|
After you execute the function, you can get the error message if there was any with:
|
|
10
14
|
error_message = accept_connection.message
|
|
15
|
+
|
|
16
|
+
:param socket_object: The socket object to accept the connection on.
|
|
17
|
+
:param domain_from_dns_server: The domain that will be printed to console on logger, needed for the decorator.
|
|
18
|
+
If not provided, the TCP data will be used.
|
|
19
|
+
:param print_kwargs: Additional arguments for the print_api function, needed for the decorator.
|
|
11
20
|
"""
|
|
12
21
|
|
|
13
22
|
client_socket = None
|
|
@@ -33,6 +42,11 @@ def accept_connection_with_error(
|
|
|
33
42
|
domain_from_dns_server,
|
|
34
43
|
print_kwargs: dict = None
|
|
35
44
|
):
|
|
45
|
+
"""
|
|
46
|
+
:param socket_object: The socket object to accept the connection on.
|
|
47
|
+
:param domain_from_dns_server: The domain that will be printed to console on logger.
|
|
48
|
+
:param print_kwargs: Additional arguments for the print_api function.
|
|
49
|
+
"""
|
|
36
50
|
client_socket, client_address_tuple = accept_connection(
|
|
37
51
|
socket_object, domain_from_dns_server, print_kwargs=print_kwargs)
|
|
38
52
|
error_message = accept_connection.message
|
|
@@ -151,13 +151,19 @@ def create_server_ssl_context___load_certificate_and_key(certificate_file_path:
|
|
|
151
151
|
def wrap_socket_with_ssl_context_server(
|
|
152
152
|
socket_object,
|
|
153
153
|
ssl_context,
|
|
154
|
-
domain_from_dns_server,
|
|
154
|
+
domain_from_dns_server: str = None,
|
|
155
155
|
print_kwargs: dict = None
|
|
156
156
|
):
|
|
157
157
|
"""
|
|
158
158
|
This function is wrapped with exception wrapper.
|
|
159
159
|
After you execute the function, you can get the error message if there was any with:
|
|
160
160
|
error_message = wrap_socket_with_ssl_context_server.message
|
|
161
|
+
|
|
162
|
+
:param socket_object: The socket object to accept the connection on.
|
|
163
|
+
:param ssl_context: The SSL context to wrap the socket with.
|
|
164
|
+
:param domain_from_dns_server: The domain that will be printed to console on logger, needed for the decorator.
|
|
165
|
+
If not provided, the TCP data will be used.
|
|
166
|
+
:param print_kwargs: Additional arguments for the print_api function, needed for the decorator.
|
|
161
167
|
"""
|
|
162
168
|
|
|
163
169
|
# Wrapping the server socket with SSL context. This should happen right after setting up the raw socket.
|
|
@@ -5,12 +5,12 @@ import threading
|
|
|
5
5
|
import socket
|
|
6
6
|
import logging
|
|
7
7
|
from pathlib import Path
|
|
8
|
-
from typing import Literal
|
|
8
|
+
from typing import Literal, Optional
|
|
9
9
|
import multiprocessing
|
|
10
10
|
|
|
11
11
|
from ...print_api import print_api
|
|
12
12
|
from ..loggingw import loggingw
|
|
13
|
-
from ..psutilw import
|
|
13
|
+
from ..psutilw import psutil_networks
|
|
14
14
|
from ...basics import booleans, tracebacks
|
|
15
15
|
from ...file_io import csvs
|
|
16
16
|
|
|
@@ -153,7 +153,6 @@ class DnsServer:
|
|
|
153
153
|
resolve_regular_pass_thru: bool = False,
|
|
154
154
|
resolve_all_domains_to_ipv4: tuple[bool, str] = (False, '127.0.0.1'),
|
|
155
155
|
offline_mode: bool = False,
|
|
156
|
-
request_domain_queue: multiprocessing.Queue = None,
|
|
157
156
|
buffer_size_receive: int = 8192,
|
|
158
157
|
response_ttl: int = 60,
|
|
159
158
|
dns_service_retries: int = 5,
|
|
@@ -183,7 +182,6 @@ class DnsServer:
|
|
|
183
182
|
:param resolve_all_domains_to_ipv4: tuple(boolean to enable the feature, string IPv4 of the target).
|
|
184
183
|
True, the DNS Server will route all domains to the specified IPv4.
|
|
185
184
|
:param offline_mode: bool: If the DNS Server should work in offline mode.
|
|
186
|
-
:param request_domain_queue: multiprocessing Queue to pass all the requested domains that hit the DNS
|
|
187
185
|
:param buffer_size_receive: int: Buffer size of the connection while receiving messages.
|
|
188
186
|
:param response_ttl: int, Time to live of the DNS Response that will be returned. Default is 60 seconds.
|
|
189
187
|
:param dns_service_retries: int, How many times the request will be sent to forwarded DNS Service on errors:
|
|
@@ -208,7 +206,6 @@ class DnsServer:
|
|
|
208
206
|
self.resolve_regular_pass_thru: bool = resolve_regular_pass_thru
|
|
209
207
|
self.resolve_all_domains_to_ipv4: tuple[bool, str] = resolve_all_domains_to_ipv4
|
|
210
208
|
self.offline_mode: bool = offline_mode
|
|
211
|
-
self.request_domain_queue: multiprocessing.Queue = request_domain_queue
|
|
212
209
|
self.buffer_size_receive: int = buffer_size_receive
|
|
213
210
|
self.response_ttl: int = response_ttl
|
|
214
211
|
self.dns_service_retries: int = dns_service_retries
|
|
@@ -229,17 +226,13 @@ class DnsServer:
|
|
|
229
226
|
self.resolve_all_domains_to_ipv4_enable: bool
|
|
230
227
|
self.resolve_all_domains_target: str
|
|
231
228
|
|
|
232
|
-
self.
|
|
229
|
+
self.intercept_domain_dict: dict = dict()
|
|
233
230
|
for engine in self.engine_list:
|
|
234
231
|
# If the engine is not a reference engine.
|
|
235
232
|
if engine.engine_name != '__reference_general':
|
|
236
233
|
# Get the domains from the engine.
|
|
237
|
-
self.intercept_domain_list.extend(engine.domain_list)
|
|
238
234
|
|
|
239
|
-
|
|
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)
|
|
235
|
+
self.intercept_domain_dict.update(engine.domain_target_dict)
|
|
243
236
|
|
|
244
237
|
# Settings for static DNS Responses in offline mode.
|
|
245
238
|
self.offline_route_ipv4: str = '10.10.10.10'
|
|
@@ -310,7 +303,7 @@ class DnsServer:
|
|
|
310
303
|
raise DnsConfigurationValuesError(e)
|
|
311
304
|
|
|
312
305
|
ips_ports: list[str] = [f'{self.listening_interface}:{self.listening_port}']
|
|
313
|
-
port_in_use =
|
|
306
|
+
port_in_use = psutil_networks.get_processes_using_port_list(ips_ports)
|
|
314
307
|
if port_in_use:
|
|
315
308
|
error_messages: list = list()
|
|
316
309
|
for port, process_info in port_in_use.items():
|
|
@@ -357,7 +350,7 @@ class DnsServer:
|
|
|
357
350
|
message = "Routing engine domains to the specified IPv4 targets."
|
|
358
351
|
print_api(message, logger=self.logger)
|
|
359
352
|
|
|
360
|
-
message = f"Current all engines domains: {self.
|
|
353
|
+
message = f"Current all engines domains: {list(self.intercept_domain_dict.keys())}"
|
|
361
354
|
print_api(message, logger=self.logger, color='blue')
|
|
362
355
|
|
|
363
356
|
if self.resolve_all_domains_to_ipv4_enable:
|
|
@@ -473,7 +466,7 @@ class DnsServer:
|
|
|
473
466
|
if self.resolve_by_engine_enable:
|
|
474
467
|
# If current query domain (+ subdomains) CONTAIN any of the domains from modules config
|
|
475
468
|
# files and current request contains "A" (IPv4) record.
|
|
476
|
-
if any(x in question_domain for x in self.
|
|
469
|
+
if any(x in question_domain for x in self.intercept_domain_dict.keys()):
|
|
477
470
|
# If incoming domain contains any of the 'engine_domains' then domain will
|
|
478
471
|
# be forwarded to our TCP Server.
|
|
479
472
|
forward_to_tcp_server = True
|
|
@@ -498,32 +491,14 @@ class DnsServer:
|
|
|
498
491
|
if forward_to_tcp_server:
|
|
499
492
|
if self.resolve_by_engine_enable:
|
|
500
493
|
for engine in self.engine_list:
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
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
|
-
|
|
494
|
+
resolved_target_ipv4 = get_target_ip_from_engine(question_domain, engine.domain_target_dict)
|
|
495
|
+
# If the domain was found in the current engine's domain list, we can stop the loop.
|
|
496
|
+
if resolved_target_ipv4:
|
|
511
497
|
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:
|
|
498
|
+
elif self.resolve_all_domains_to_ipv4_enable:
|
|
521
499
|
# Assign the target IPv4 address to the resolved target IPv4 variable.
|
|
522
500
|
resolved_target_ipv4 = self.resolve_all_domains_target
|
|
523
501
|
|
|
524
|
-
# Put the domain in the domain queue.
|
|
525
|
-
self.request_domain_queue.put(question_domain)
|
|
526
|
-
|
|
527
502
|
# Make DNS response that will refer TCP traffic to our server
|
|
528
503
|
dns_built_response = DNSRecord(
|
|
529
504
|
# dns_object.header,
|
|
@@ -913,6 +888,27 @@ class DnsServer:
|
|
|
913
888
|
continue
|
|
914
889
|
|
|
915
890
|
|
|
891
|
+
def get_target_ip_from_engine(
|
|
892
|
+
target_domain: str,
|
|
893
|
+
engine_domain_target_dict: dict
|
|
894
|
+
) -> Optional[str]:
|
|
895
|
+
"""
|
|
896
|
+
Get the target IP address from the engine.
|
|
897
|
+
|
|
898
|
+
:param target_domain: str: The domain to return the target IP address for.
|
|
899
|
+
:param engine_domain_target_dict: dict: The dictionary of domains and their target IPs.
|
|
900
|
+
|
|
901
|
+
:return: str: The target IP address.
|
|
902
|
+
"""
|
|
903
|
+
# Iterate through the list of engines.
|
|
904
|
+
for domain, target_ip_port in engine_domain_target_dict.items():
|
|
905
|
+
if domain in target_domain:
|
|
906
|
+
# Get the target IP address from the engine.
|
|
907
|
+
return target_ip_port['ip']
|
|
908
|
+
|
|
909
|
+
return None
|
|
910
|
+
|
|
911
|
+
|
|
916
912
|
# noinspection PyPep8Naming
|
|
917
913
|
def start_dns_server_multiprocessing_worker(
|
|
918
914
|
listening_address: str,
|
|
@@ -925,7 +921,6 @@ def start_dns_server_multiprocessing_worker(
|
|
|
925
921
|
resolve_all_domains_to_ipv4: tuple[bool, str],
|
|
926
922
|
offline_mode: bool,
|
|
927
923
|
cache_timeout_minutes: int,
|
|
928
|
-
request_domain_queue: multiprocessing.Queue,
|
|
929
924
|
logging_queue: multiprocessing.Queue,
|
|
930
925
|
logger_name: str
|
|
931
926
|
):
|
|
@@ -945,7 +940,6 @@ def start_dns_server_multiprocessing_worker(
|
|
|
945
940
|
resolve_all_domains_to_ipv4=resolve_all_domains_to_ipv4,
|
|
946
941
|
offline_mode=offline_mode,
|
|
947
942
|
cache_timeout_minutes=cache_timeout_minutes,
|
|
948
|
-
request_domain_queue=request_domain_queue,
|
|
949
943
|
logging_queue=logging_queue,
|
|
950
944
|
logger_name=logger_name
|
|
951
945
|
)
|
|
@@ -954,4 +948,4 @@ def start_dns_server_multiprocessing_worker(
|
|
|
954
948
|
time.sleep(1)
|
|
955
949
|
return 1
|
|
956
950
|
|
|
957
|
-
dns_server_instance.start()
|
|
951
|
+
dns_server_instance.start()
|
|
@@ -14,7 +14,13 @@ def connection_exception_decorator(function_name):
|
|
|
14
14
|
args, kwargs = get_target_function_default_args_and_combine_with_current(function_name, *args, **kwargs)
|
|
15
15
|
|
|
16
16
|
wrapper_handle_connection_exceptions.message = None
|
|
17
|
-
port = kwargs['socket_object'].getsockname()
|
|
17
|
+
listen_ipv4, port = kwargs['socket_object'].getsockname()
|
|
18
|
+
|
|
19
|
+
domain_from_dns_server = kwargs['domain_from_dns_server']
|
|
20
|
+
if not domain_from_dns_server:
|
|
21
|
+
# If the domain is not passed, we will use the TCP data.
|
|
22
|
+
# This is needed for the decorator to work properly.
|
|
23
|
+
domain_from_dns_server = listen_ipv4
|
|
18
24
|
|
|
19
25
|
try:
|
|
20
26
|
# Since our 'kwargs' has already all the needed arguments, we don't need 'args'.
|
|
@@ -24,12 +30,12 @@ def connection_exception_decorator(function_name):
|
|
|
24
30
|
# After that second exception will be "pass"-ed. This is an exception inside an exception handling.
|
|
25
31
|
# Looks like was introduced in Python 3 in PEP 3134.
|
|
26
32
|
except ConnectionAbortedError:
|
|
27
|
-
message = f"Socket Accept: {
|
|
33
|
+
message = f"Socket Accept: {domain_from_dns_server}:{port}: " \
|
|
28
34
|
f"* Established connection was aborted by software on the host..."
|
|
29
35
|
wrapper_handle_connection_exceptions.message = message
|
|
30
36
|
print_api(message, logger_method='error', traceback_string=True, oneline=True, **kwargs['print_kwargs'])
|
|
31
37
|
except ConnectionResetError:
|
|
32
|
-
message = f"Socket Accept: {
|
|
38
|
+
message = f"Socket Accept: {domain_from_dns_server}:{port}: " \
|
|
33
39
|
f"* An existing connection was forcibly closed by the remote host..."
|
|
34
40
|
wrapper_handle_connection_exceptions.message = message
|
|
35
41
|
print_api(message, logger_method='error', traceback_string=True, oneline=True, **kwargs['print_kwargs'])
|
|
@@ -43,10 +49,11 @@ def connection_exception_decorator(function_name):
|
|
|
43
49
|
wrapper_handle_connection_exceptions.message = message
|
|
44
50
|
try:
|
|
45
51
|
message = \
|
|
46
|
-
f"Socket Accept: {
|
|
52
|
+
f"Socket Accept: {domain_from_dns_server}:{port}: {message}"
|
|
47
53
|
wrapper_handle_connection_exceptions.message = message
|
|
48
54
|
print_api(message, error_type=True, logger_method='error', oneline=True, **kwargs['print_kwargs'])
|
|
49
|
-
except Exception:
|
|
55
|
+
except Exception as e:
|
|
56
|
+
_ = e
|
|
50
57
|
message = f"Socket Accept: port {port}: {message}"
|
|
51
58
|
wrapper_handle_connection_exceptions.message = message
|
|
52
59
|
print_api(message, logger_method='error', traceback_string=True, oneline=True, **kwargs['print_kwargs'])
|
|
@@ -57,10 +64,11 @@ def connection_exception_decorator(function_name):
|
|
|
57
64
|
wrapper_handle_connection_exceptions.message = message
|
|
58
65
|
try:
|
|
59
66
|
message = \
|
|
60
|
-
f"Socket Accept: {
|
|
67
|
+
f"Socket Accept: {domain_from_dns_server}:{port}: {message}"
|
|
61
68
|
wrapper_handle_connection_exceptions.message = message
|
|
62
69
|
print_api(message, logger_method='error', oneline=True, **kwargs['print_kwargs'])
|
|
63
|
-
except Exception:
|
|
70
|
+
except Exception as e:
|
|
71
|
+
_ = e
|
|
64
72
|
message = f"Socket Accept: port {port}: {message}"
|
|
65
73
|
wrapper_handle_connection_exceptions.message = message
|
|
66
74
|
print_api(message, logger_method='error', traceback_string=True, oneline=True, **kwargs['print_kwargs'])
|
|
@@ -91,20 +99,21 @@ def connection_exception_decorator(function_name):
|
|
|
91
99
|
message = f'ssl.SSLError:{exception_object}'
|
|
92
100
|
wrapper_handle_connection_exceptions.message = message
|
|
93
101
|
message = \
|
|
94
|
-
f"Socket Accept: {
|
|
102
|
+
f"Socket Accept: {domain_from_dns_server}:{port}: {message}"
|
|
95
103
|
wrapper_handle_connection_exceptions.message = message
|
|
96
104
|
print_api(message, logger_method='error', oneline=True, **kwargs['print_kwargs'])
|
|
97
105
|
pass
|
|
98
106
|
except FileNotFoundError:
|
|
99
107
|
message = "'SSLSocket.accept()' crashed: 'FileNotFoundError'. Some problem with SSL during Handshake - " \
|
|
100
108
|
"Could be certificate, client, or server."
|
|
101
|
-
message = f"Socket Accept: {
|
|
109
|
+
message = f"Socket Accept: {domain_from_dns_server}:{port}: {message}"
|
|
102
110
|
wrapper_handle_connection_exceptions.message = message
|
|
103
111
|
print_api(message, logger_method='error', traceback_string=True, oneline=True, **kwargs['print_kwargs'])
|
|
104
112
|
pass
|
|
105
|
-
except Exception:
|
|
113
|
+
except Exception as e:
|
|
114
|
+
_ = e
|
|
106
115
|
message = "Undocumented exception on accept."
|
|
107
|
-
message = f"Socket Accept: {
|
|
116
|
+
message = f"Socket Accept: {domain_from_dns_server}:{port}: {message}"
|
|
108
117
|
wrapper_handle_connection_exceptions.message = message
|
|
109
118
|
print_api(message, logger_method='error', traceback_string=True, oneline=True, **kwargs['print_kwargs'])
|
|
110
119
|
pass
|
|
@@ -4,11 +4,9 @@ from typing import Literal, Union
|
|
|
4
4
|
from pathlib import Path
|
|
5
5
|
import logging
|
|
6
6
|
import socket
|
|
7
|
-
import multiprocessing
|
|
8
|
-
import queue
|
|
9
7
|
|
|
10
8
|
from ...mitm import initialize_engines
|
|
11
|
-
from ..psutilw import
|
|
9
|
+
from ..psutilw import psutil_networks
|
|
12
10
|
from ..certauthw import certauthw
|
|
13
11
|
from ..loggingw import loggingw
|
|
14
12
|
from ...script_as_string_processor import ScriptAsStringProcessor
|
|
@@ -69,7 +67,6 @@ class SocketWrapper:
|
|
|
69
67
|
logger: logging.Logger = None,
|
|
70
68
|
exceptions_logger: loggingw.ExceptionCsvLogger = None,
|
|
71
69
|
statistics_logs_directory: str = None,
|
|
72
|
-
request_domain_from_dns_server_queue: multiprocessing.Queue = None,
|
|
73
70
|
no_engine_usage_enable: bool = False,
|
|
74
71
|
no_engines_listening_address_list: list[str] = None,
|
|
75
72
|
engines_list: list[initialize_engines.ModuleCategory] = None
|
|
@@ -162,10 +159,6 @@ class SocketWrapper:
|
|
|
162
159
|
|
|
163
160
|
statistics_writer: statistics_csv.StatisticsCSVWriter object, there is a logger object that
|
|
164
161
|
will be used to write the statistics file.
|
|
165
|
-
:param request_domain_from_dns_server_queue: multiprocessing queue that will be used
|
|
166
|
-
to get the domain name that was requested from the DNS server (atomicshop.wrappers.socketw.dns_server).
|
|
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
|
-
was empty (in the SNIHandler class to set the 'server_hostname' for the socket).
|
|
169
162
|
:param no_engine_usage_enable: boolean, if True, 'engines_list' will be used to listen on the addresses,
|
|
170
163
|
but the "no_engines_listening_address_list" parameter will be used instead.
|
|
171
164
|
:param no_engines_listening_address_list: list, of ips+ports that will be listened on.
|
|
@@ -215,23 +208,10 @@ class SocketWrapper:
|
|
|
215
208
|
self.statistics_logs_directory: str = statistics_logs_directory
|
|
216
209
|
self.forwarding_dns_service_ipv4_list___only_for_localhost = (
|
|
217
210
|
forwarding_dns_service_ipv4_list___only_for_localhost)
|
|
218
|
-
self.request_domain_from_dns_server_queue: multiprocessing.Queue = request_domain_from_dns_server_queue
|
|
219
211
|
self.no_engine_usage_enable: bool = no_engine_usage_enable
|
|
220
212
|
self.no_engines_listening_address_list: list[str] = no_engines_listening_address_list
|
|
221
213
|
self.engines_list: list[initialize_engines.ModuleCategory] = engines_list
|
|
222
214
|
|
|
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)
|
|
234
|
-
|
|
235
215
|
self.socket_object = None
|
|
236
216
|
|
|
237
217
|
# Server certificate file path that will be loaded into SSL Context.
|
|
@@ -351,12 +331,13 @@ class SocketWrapper:
|
|
|
351
331
|
listening_check_list: list = list()
|
|
352
332
|
if self.engines_list:
|
|
353
333
|
for engine in self.engines_list:
|
|
354
|
-
for
|
|
334
|
+
for _, ip_port_dict in engine.domain_target_dict.items():
|
|
335
|
+
address: str = f"{ip_port_dict['ip']}:{ip_port_dict['port']}"
|
|
355
336
|
if address not in listening_check_list:
|
|
356
337
|
listening_check_list.append(address)
|
|
357
338
|
else:
|
|
358
339
|
listening_check_list = self.no_engines_listening_address_list
|
|
359
|
-
port_in_use =
|
|
340
|
+
port_in_use = psutil_networks.get_processes_using_port_list(listening_check_list)
|
|
360
341
|
if port_in_use:
|
|
361
342
|
error_messages: list = list()
|
|
362
343
|
for port, process_info in port_in_use.items():
|
|
@@ -447,9 +428,9 @@ class SocketWrapper:
|
|
|
447
428
|
if not self.no_engine_usage_enable:
|
|
448
429
|
for engine in self.engines_list:
|
|
449
430
|
# Start all the regular listening interfaces.
|
|
450
|
-
for
|
|
451
|
-
ip_address
|
|
452
|
-
port = int(
|
|
431
|
+
for domain, ip_port_dict in engine.domain_target_dict.items():
|
|
432
|
+
ip_address: str = ip_port_dict['ip']
|
|
433
|
+
port = int(ip_port_dict['port'])
|
|
453
434
|
socket_by_port = self.create_socket_ipv4_tcp(ip_address, port)
|
|
454
435
|
threading.Thread(
|
|
455
436
|
target=self.listening_socket_loop,
|
|
@@ -458,20 +439,6 @@ class SocketWrapper:
|
|
|
458
439
|
name=f"acceptor-{engine.engine_name}-{ip_address}:{port}",
|
|
459
440
|
daemon=True
|
|
460
441
|
).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
442
|
else:
|
|
476
443
|
# If no engines were passed, we will use the listening addresses from the configuration.
|
|
477
444
|
for address in self.no_engines_listening_address_list:
|
|
@@ -540,33 +507,21 @@ class SocketWrapper:
|
|
|
540
507
|
readable, writable, exceptional = select.select(listening_sockets, [], [])
|
|
541
508
|
listening_socket_object = readable[0]
|
|
542
509
|
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
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
|
|
563
|
-
|
|
564
|
-
self.logger.info(f"Requested domain from DNS Server: {domain_from_dns_server}")
|
|
510
|
+
listening_ip, listening_port = listening_socket_object.getsockname()
|
|
511
|
+
|
|
512
|
+
domain_from_engine = None
|
|
513
|
+
for engine in self.engines_list:
|
|
514
|
+
for domain, ip_port_dict in engine.domain_target_dict.items():
|
|
515
|
+
if ip_port_dict['ip'] == listening_ip:
|
|
516
|
+
domain_from_engine = domain
|
|
517
|
+
break
|
|
518
|
+
|
|
519
|
+
self.logger.info(f"NO SNI requested domain setting: {domain_from_engine}")
|
|
565
520
|
|
|
566
521
|
# Wait from any connection on "accept()".
|
|
567
522
|
# 'client_socket' is socket or ssl socket, 'client_address' is a tuple (ip_address, port).
|
|
568
523
|
client_socket, client_address, accept_error_message = accepter.accept_connection_with_error(
|
|
569
|
-
listening_socket_object, domain_from_dns_server=
|
|
524
|
+
listening_socket_object, domain_from_dns_server=domain_from_engine,
|
|
570
525
|
print_kwargs={'logger': self.logger})
|
|
571
526
|
|
|
572
527
|
# This is the earliest stage to ask for process name.
|
|
@@ -585,7 +540,7 @@ class SocketWrapper:
|
|
|
585
540
|
|
|
586
541
|
source_ip: str = client_address[0]
|
|
587
542
|
source_hostname: str = socket.gethostbyaddr(source_ip)[0]
|
|
588
|
-
engine_name: str = get_engine_name(
|
|
543
|
+
engine_name: str = get_engine_name(domain_from_engine, self.engines_list)
|
|
589
544
|
dest_port: int = listening_socket_object.getsockname()[1]
|
|
590
545
|
|
|
591
546
|
# If 'accept()' function worked well, SSL worked well, then 'client_socket' won't be empty.
|
|
@@ -625,7 +580,7 @@ class SocketWrapper:
|
|
|
625
580
|
custom_server_certificate_usage=self.custom_server_certificate_usage,
|
|
626
581
|
custom_server_certificate_path=self.custom_server_certificate_path,
|
|
627
582
|
custom_private_key_path=self.custom_private_key_path,
|
|
628
|
-
domain_from_dns_server=
|
|
583
|
+
domain_from_dns_server=domain_from_engine,
|
|
629
584
|
forwarding_dns_service_ipv4_list___only_for_localhost=(
|
|
630
585
|
self.forwarding_dns_service_ipv4_list___only_for_localhost),
|
|
631
586
|
tls=is_tls,
|
|
@@ -643,7 +598,7 @@ class SocketWrapper:
|
|
|
643
598
|
if engine_name == '':
|
|
644
599
|
sni_hostname: str = ssl_client_socket.server_hostname
|
|
645
600
|
if sni_hostname:
|
|
646
|
-
engine_name = get_engine_name(sni_hostname, self.
|
|
601
|
+
engine_name = get_engine_name(sni_hostname, self.engines_list)
|
|
647
602
|
|
|
648
603
|
if accept_error_message:
|
|
649
604
|
# Write statistics after wrap is there was an error.
|
|
@@ -653,7 +608,7 @@ class SocketWrapper:
|
|
|
653
608
|
source_ip=source_ip,
|
|
654
609
|
error_message=accept_error_message,
|
|
655
610
|
dest_port=str(dest_port),
|
|
656
|
-
host=
|
|
611
|
+
host=domain_from_engine,
|
|
657
612
|
process_name=process_name)
|
|
658
613
|
|
|
659
614
|
continue
|
|
@@ -668,7 +623,7 @@ class SocketWrapper:
|
|
|
668
623
|
client_socket = None
|
|
669
624
|
client_socket = ssl_client_socket
|
|
670
625
|
thread_args = \
|
|
671
|
-
((client_socket, process_name, is_tls, tls_type, tls_version,
|
|
626
|
+
((client_socket, process_name, is_tls, tls_type, tls_version, domain_from_engine) +
|
|
672
627
|
reference_function_args)
|
|
673
628
|
# If 'pass_function_reference_to_thread' was set to 'False', execute the callable passed function
|
|
674
629
|
# as is.
|
|
@@ -691,7 +646,7 @@ class SocketWrapper:
|
|
|
691
646
|
source_ip=source_ip,
|
|
692
647
|
error_message=accept_error_message,
|
|
693
648
|
dest_port=str(dest_port),
|
|
694
|
-
host=
|
|
649
|
+
host=domain_from_engine,
|
|
695
650
|
process_name=process_name)
|
|
696
651
|
except Exception as e:
|
|
697
652
|
self.exceptions_logger.write(e)
|
|
@@ -729,20 +684,16 @@ def before_socket_thread_worker(
|
|
|
729
684
|
exceptions_logger.write(e)
|
|
730
685
|
|
|
731
686
|
|
|
732
|
-
def get_engine_name(domain: str,
|
|
687
|
+
def get_engine_name(domain: str, engine_list: list):
|
|
733
688
|
"""
|
|
734
689
|
Function that will get the engine name from the domain name.
|
|
735
690
|
:param domain: string, domain name.
|
|
736
|
-
:param
|
|
737
|
-
[
|
|
738
|
-
{'this_is_engine_name': ['example.com', 'example.org']},
|
|
739
|
-
{'this_is_engine_name2': ['example2.com', 'example2.org']}
|
|
740
|
-
]
|
|
691
|
+
:param engine_list: list that contains the engine names and domains.
|
|
741
692
|
:return: string, engine name.
|
|
742
693
|
"""
|
|
743
694
|
|
|
744
|
-
for
|
|
745
|
-
if
|
|
746
|
-
return engine_name
|
|
695
|
+
for engine in engine_list:
|
|
696
|
+
if domain in engine.domain_target_dict:
|
|
697
|
+
return engine.engine_name
|
|
747
698
|
|
|
748
699
|
return ''
|
|
@@ -205,3 +205,23 @@ def get_default_dns_gateway() -> tuple[bool, list[str]]:
|
|
|
205
205
|
|
|
206
206
|
# noinspection PyTypeChecker
|
|
207
207
|
return function_result
|
|
208
|
+
|
|
209
|
+
|
|
210
|
+
def change_metric_of_network_adapter(
|
|
211
|
+
adapter_guid: str,
|
|
212
|
+
metric: int
|
|
213
|
+
) -> None:
|
|
214
|
+
"""
|
|
215
|
+
Change the metric of a network adapter.
|
|
216
|
+
After you set new metric you need to restart the network adapter for the changes to take effect.
|
|
217
|
+
|
|
218
|
+
:param adapter_guid: str, GUID of the network adapter.
|
|
219
|
+
:param metric: int, new metric value.
|
|
220
|
+
:return: None
|
|
221
|
+
"""
|
|
222
|
+
|
|
223
|
+
reg_path = fr"SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\Interfaces\{adapter_guid}"
|
|
224
|
+
|
|
225
|
+
with winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, reg_path, 0, winreg.KEY_SET_VALUE) as key:
|
|
226
|
+
winreg.SetValueEx(key, "UseAutomaticMetric", 0, winreg.REG_DWORD, 0)
|
|
227
|
+
winreg.SetValueEx(key, "InterfaceMetric", 0, winreg.REG_DWORD, metric)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: atomicshop
|
|
3
|
-
Version:
|
|
3
|
+
Version: 3.0.0
|
|
4
4
|
Summary: Atomic functions and classes to make developer life easier
|
|
5
5
|
Author: Denis Kras
|
|
6
6
|
License: MIT License
|
|
@@ -41,6 +41,7 @@ Requires-Dist: docker
|
|
|
41
41
|
Requires-Dist: flask-socketio
|
|
42
42
|
Requires-Dist: google-api-python-client
|
|
43
43
|
Requires-Dist: google-generativeai
|
|
44
|
+
Requires-Dist: icmplib
|
|
44
45
|
Requires-Dist: numpy
|
|
45
46
|
Requires-Dist: olefile
|
|
46
47
|
Requires-Dist: openpyxl
|