atomicshop 2.15.13__py3-none-any.whl → 2.16.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/a_installs/ubuntu/pycharm.py +7 -0
- atomicshop/a_installs/win/pycharm.py +2 -2
- atomicshop/{addons/mains/install_wsl_ubuntu_lts_admin.py → a_installs/win/wsl_ubuntu_lts.py} +1 -0
- atomicshop/{addons/mains → a_mains}/FACT/update_extract.py +3 -2
- atomicshop/a_mains/dns_gateway_setting.py +11 -0
- atomicshop/basics/booleans.py +14 -5
- atomicshop/dns.py +104 -0
- atomicshop/file_io/docxs.py +8 -0
- atomicshop/file_io/tomls.py +133 -0
- atomicshop/filesystem.py +5 -4
- atomicshop/get_process_list.py +3 -3
- atomicshop/mitm/config_static.py +195 -0
- atomicshop/mitm/config_toml_editor.py +55 -0
- atomicshop/mitm/connection_thread_worker.py +54 -90
- atomicshop/mitm/import_config.py +148 -139
- atomicshop/mitm/initialize_engines.py +7 -2
- atomicshop/mitm/initialize_mitm_server.py +162 -107
- atomicshop/mitm/shared_functions.py +0 -1
- atomicshop/mitm/statistic_analyzer.py +13 -1
- atomicshop/mitm/statistic_analyzer_helper/moving_average_helper.py +54 -14
- atomicshop/permissions/__init__.py +0 -0
- atomicshop/permissions/permissions.py +22 -0
- atomicshop/{permissions.py → permissions/ubuntu_permissions.py} +4 -54
- atomicshop/permissions/win_permissions.py +33 -0
- atomicshop/script_as_string_processor.py +5 -1
- atomicshop/wrappers/cryptographyw.py +3 -3
- atomicshop/wrappers/dockerw/install_docker.py +6 -5
- atomicshop/wrappers/elasticsearchw/install_elastic.py +2 -1
- atomicshop/wrappers/factw/install/pre_install_and_install_before_restart.py +5 -4
- atomicshop/wrappers/mongodbw/install_mongodb.py +2 -1
- atomicshop/wrappers/msiw.py +2 -3
- atomicshop/wrappers/psutilw/networks.py +25 -1
- atomicshop/wrappers/pycharmw/__init__.py +0 -0
- atomicshop/wrappers/pycharmw/ubuntu.py +38 -0
- atomicshop/wrappers/{pycharmw.py → pycharmw/win.py} +2 -2
- atomicshop/wrappers/pywin32w/wmis/__init__.py +0 -0
- atomicshop/wrappers/pywin32w/wmis/helpers.py +127 -0
- atomicshop/wrappers/pywin32w/wmis/win32networkadapter.py +167 -0
- atomicshop/wrappers/socketw/accepter.py +8 -8
- atomicshop/wrappers/socketw/base.py +13 -0
- atomicshop/wrappers/socketw/certificator.py +202 -149
- atomicshop/wrappers/socketw/creator.py +15 -35
- atomicshop/wrappers/socketw/dns_server.py +155 -102
- atomicshop/wrappers/socketw/exception_wrapper.py +8 -27
- atomicshop/wrappers/socketw/get_process.py +115 -95
- atomicshop/wrappers/socketw/sni.py +298 -164
- atomicshop/wrappers/socketw/socket_client.py +5 -12
- atomicshop/wrappers/socketw/socket_server_tester.py +1 -1
- atomicshop/wrappers/socketw/socket_wrapper.py +328 -72
- atomicshop/wrappers/socketw/statistics_csv.py +94 -16
- atomicshop/wrappers/ubuntu_terminal.py +6 -6
- atomicshop/wrappers/wslw.py +1 -0
- {atomicshop-2.15.13.dist-info → atomicshop-2.16.1.dist-info}/METADATA +1 -1
- {atomicshop-2.15.13.dist-info → atomicshop-2.16.1.dist-info}/RECORD +63 -54
- atomicshop/addons/mains/__pycache__/install_fibratus_windows.cpython-312.pyc +0 -0
- atomicshop/addons/mains/__pycache__/msi_unpacker.cpython-312.pyc +0 -0
- atomicshop/mitm/config_editor.py +0 -37
- /atomicshop/{addons/mains/install_docker_rootless_ubuntu.py → a_installs/ubuntu/docker_rootless.py} +0 -0
- /atomicshop/{addons/mains/install_docker_ubuntu_main_sudo.py → a_installs/ubuntu/docker_sudo.py} +0 -0
- /atomicshop/{addons/mains/install_elastic_search_and_kibana_ubuntu.py → a_installs/ubuntu/elastic_search_and_kibana.py} +0 -0
- /atomicshop/{addons/mains → a_mains}/FACT/factw_fact_extractor_docker_image_main_sudo.py +0 -0
- /atomicshop/wrappers/pywin32w/{wmi_win32process.py → wmis/win32process.py} +0 -0
- {atomicshop-2.15.13.dist-info → atomicshop-2.16.1.dist-info}/LICENSE.txt +0 -0
- {atomicshop-2.15.13.dist-info → atomicshop-2.16.1.dist-info}/WHEEL +0 -0
- {atomicshop-2.15.13.dist-info → atomicshop-2.16.1.dist-info}/top_level.txt +0 -0
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import socket
|
|
2
2
|
import ssl
|
|
3
3
|
|
|
4
|
-
from . import base,
|
|
4
|
+
from . import base, exception_wrapper
|
|
5
5
|
from ...print_api import print_api
|
|
6
6
|
|
|
7
7
|
|
|
@@ -101,17 +101,16 @@ def create_server_ssl_context___load_certificate_and_key(certificate_file_path:
|
|
|
101
101
|
|
|
102
102
|
|
|
103
103
|
@exception_wrapper.connection_exception_decorator
|
|
104
|
-
def wrap_socket_with_ssl_context_server(
|
|
104
|
+
def wrap_socket_with_ssl_context_server(
|
|
105
|
+
socket_object,
|
|
106
|
+
ssl_context,
|
|
107
|
+
domain_from_dns_server,
|
|
108
|
+
print_kwargs: dict = None
|
|
109
|
+
):
|
|
105
110
|
"""
|
|
106
111
|
This function is wrapped with exception wrapper.
|
|
107
112
|
After you execute the function, you can get the error message if there was any with:
|
|
108
113
|
error_message = wrap_socket_with_ssl_context_server.message
|
|
109
|
-
|
|
110
|
-
:param socket_object:
|
|
111
|
-
:param ssl_context:
|
|
112
|
-
:param dns_domain:
|
|
113
|
-
:param print_kwargs:
|
|
114
|
-
:return:
|
|
115
114
|
"""
|
|
116
115
|
|
|
117
116
|
# Wrapping the server socket with SSL context. This should happen right after setting up the raw socket.
|
|
@@ -122,10 +121,16 @@ def wrap_socket_with_ssl_context_server(socket_object, ssl_context, dns_domain:
|
|
|
122
121
|
|
|
123
122
|
|
|
124
123
|
def wrap_socket_with_ssl_context_server_with_error_message(
|
|
125
|
-
socket_object,
|
|
124
|
+
socket_object,
|
|
125
|
+
ssl_context,
|
|
126
|
+
domain_from_dns_server,
|
|
127
|
+
print_kwargs: dict = None
|
|
128
|
+
):
|
|
126
129
|
|
|
127
130
|
ssl_socket = wrap_socket_with_ssl_context_server(
|
|
128
|
-
socket_object, ssl_context,
|
|
131
|
+
socket_object=socket_object, ssl_context=ssl_context, domain_from_dns_server=domain_from_dns_server,
|
|
132
|
+
print_kwargs=print_kwargs)
|
|
133
|
+
|
|
129
134
|
error_message = wrap_socket_with_ssl_context_server.message
|
|
130
135
|
|
|
131
136
|
return ssl_socket, error_message
|
|
@@ -190,28 +195,3 @@ def wrap_socket_with_ssl_context_client___default_certs___ignore_verification(
|
|
|
190
195
|
socket_object, ssl_context, server_hostname=server_hostname)
|
|
191
196
|
|
|
192
197
|
return ssl_socket
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
def wrap_socket_with_ssl_context_server_sni_extended(
|
|
196
|
-
socket_object, config: dict, dns_domain: str = None, print_kwargs: dict = None):
|
|
197
|
-
|
|
198
|
-
ssl_context = create_ssl_context_for_server()
|
|
199
|
-
|
|
200
|
-
sni.add_sni_callback_function_reference_to_ssl_context(
|
|
201
|
-
ssl_context=ssl_context, config=config, dns_domain=dns_domain, use_default_sni_function=True,
|
|
202
|
-
use_sni_extended=True, print_kwargs=print_kwargs)
|
|
203
|
-
|
|
204
|
-
server_certificate_file_path, server_private_key_file_path = \
|
|
205
|
-
certificator.select_server_ssl_context_certificate(config=config, print_kwargs=print_kwargs)
|
|
206
|
-
|
|
207
|
-
# If the user chose 'sni_create_server_certificate_for_each_domain = 1' in the configuration file,
|
|
208
|
-
# it means that 'self.server_certificate_file_path' will be empty, which is OK, since we'll inject
|
|
209
|
-
# dynamically created certificate from certs folder through SNI.
|
|
210
|
-
if server_certificate_file_path:
|
|
211
|
-
load_certificate_and_key_into_server_ssl_context(
|
|
212
|
-
ssl_context, server_certificate_file_path, server_private_key_file_path,
|
|
213
|
-
print_kwargs=print_kwargs)
|
|
214
|
-
|
|
215
|
-
ssl_socket, error_message = wrap_socket_with_ssl_context_server_with_error_message(
|
|
216
|
-
socket_object, ssl_context, dns_domain=dns_domain, print_kwargs=print_kwargs)
|
|
217
|
-
return ssl_socket, error_message
|
|
@@ -7,8 +7,12 @@ import socket
|
|
|
7
7
|
from ...print_api import print_api
|
|
8
8
|
from ..loggingw import loggingw
|
|
9
9
|
from ..psutilw import networks
|
|
10
|
+
from ... import queues
|
|
11
|
+
from ...basics import booleans
|
|
10
12
|
|
|
13
|
+
# noinspection PyPackageRequirements
|
|
11
14
|
import dnslib
|
|
15
|
+
# noinspection PyPackageRequirements
|
|
12
16
|
from dnslib import DNSRecord, DNSHeader, RR, A
|
|
13
17
|
|
|
14
18
|
|
|
@@ -16,7 +20,8 @@ class DnsPortInUseError(Exception):
|
|
|
16
20
|
pass
|
|
17
21
|
|
|
18
22
|
|
|
19
|
-
|
|
23
|
+
class DnsConfigurationValuesError(Exception):
|
|
24
|
+
pass
|
|
20
25
|
|
|
21
26
|
|
|
22
27
|
class DnsServer:
|
|
@@ -25,33 +30,89 @@ class DnsServer:
|
|
|
25
30
|
"""
|
|
26
31
|
logger = loggingw.get_logger_with_level("network." + __name__.rpartition('.')[2])
|
|
27
32
|
|
|
28
|
-
def __init__(
|
|
33
|
+
def __init__(
|
|
34
|
+
self,
|
|
35
|
+
listening_interface: str,
|
|
36
|
+
listening_port: int,
|
|
37
|
+
log_directory_path: str,
|
|
38
|
+
forwarding_dns_service_ipv4: str = '8.8.8.8',
|
|
39
|
+
forwarding_dns_service_port: int = 53,
|
|
40
|
+
resolve_to_tcp_server_only_tcp_resolve_domains: bool = False,
|
|
41
|
+
resolve_to_tcp_server_all_domains: bool = False,
|
|
42
|
+
resolve_regular: bool = False,
|
|
43
|
+
offline_mode: bool = False,
|
|
44
|
+
tcp_target_server_ipv4: str = '127.0.0.1',
|
|
45
|
+
tcp_resolve_domain_list: list = None,
|
|
46
|
+
request_domain_queue: queues.NonBlockQueue = None,
|
|
47
|
+
buffer_size_receive: int = 8192,
|
|
48
|
+
response_ttl: int = 60,
|
|
49
|
+
dns_service_retries: int = 5,
|
|
50
|
+
cache_timeout_minutes: int = 60,
|
|
51
|
+
):
|
|
52
|
+
"""
|
|
53
|
+
Initialize the DNS Server object with all the necessary settings.
|
|
54
|
+
|
|
55
|
+
:param listening_interface: str: Interface that the DNS Server will listen on.
|
|
56
|
+
Example: '0.0.0.0'. For all interfaces.
|
|
57
|
+
:param listening_port: int: Port number that the DNS Server will listen on.
|
|
58
|
+
:param log_directory_path: str: Path to the directory where the logs will be saved.
|
|
59
|
+
:param forwarding_dns_service_ipv4: str: IPv4 address of the DNS Service that will be used for resolving.
|
|
60
|
+
Example: '8.8.8.8'. For Google DNS Service.
|
|
61
|
+
:param forwarding_dns_service_port: int: Port number of the DNS Service that will be used for resolving.
|
|
62
|
+
Default is 53.
|
|
63
|
+
:param resolve_to_tcp_server_only_tcp_resolve_domains: bool: If the DNS Server should route only the
|
|
64
|
+
domains from 'tcp_resolve_domain_list' to the TCP Server in 'tcp_target_server_ipv4'.
|
|
65
|
+
:param resolve_to_tcp_server_all_domains: bool: If the DNS Server should route all domains to the TCP Server.
|
|
66
|
+
:param resolve_regular: bool: If the DNS Server should resolve all the domains to the Live DNS Service.
|
|
67
|
+
:param offline_mode: bool: If the DNS Server should work in offline mode.
|
|
68
|
+
:param tcp_target_server_ipv4: str: IPv4 address of the TCP Server that the specified booleans will resolve
|
|
69
|
+
the domains to.
|
|
70
|
+
:param tcp_resolve_domain_list: list: List of domains that will be resolved to the TCP Server.
|
|
71
|
+
This means that all the requests will be resolved to the specified offline IPv4 address.
|
|
72
|
+
:param request_domain_queue: queues.NonBlockQueue: Queue to pass all the requested domains that hit the DNS
|
|
73
|
+
:param buffer_size_receive: int: Buffer size of the connection while receiving messages.
|
|
74
|
+
:param response_ttl: int, Time to live of the DNS Response that will be returned. Default is 60 seconds.
|
|
75
|
+
:param dns_service_retries: int, How many times the request will be sent to forwarded DNS Service on errors:
|
|
76
|
+
(socket connect / request send / response receive).
|
|
77
|
+
:param cache_timeout_minutes: int: Timeout in minutes to clear the DNS Cache.
|
|
78
|
+
server. Each domain will be pass in the queue as a string.
|
|
79
|
+
"""
|
|
80
|
+
|
|
81
|
+
self.listening_interface: str = listening_interface
|
|
82
|
+
self.listening_port: int = listening_port
|
|
83
|
+
self.log_directory_path: str = log_directory_path
|
|
84
|
+
self.forwarding_dns_service_ipv4: str = forwarding_dns_service_ipv4
|
|
85
|
+
self.forwarding_dns_service_port: int = forwarding_dns_service_port
|
|
86
|
+
self.tcp_target_server_ipv4: str = tcp_target_server_ipv4
|
|
87
|
+
self.tcp_resolve_domain_list: list = tcp_resolve_domain_list
|
|
88
|
+
self.offline_mode: bool = offline_mode
|
|
89
|
+
self.resolve_to_tcp_server_only_tcp_resolve_domains: bool = resolve_to_tcp_server_only_tcp_resolve_domains
|
|
90
|
+
self.resolve_to_tcp_server_all_domains: bool = resolve_to_tcp_server_all_domains
|
|
91
|
+
self.resolve_regular: bool = resolve_regular
|
|
92
|
+
self.request_domain_queue: queues.NonBlockQueue = request_domain_queue
|
|
93
|
+
self.buffer_size_receive: int = buffer_size_receive
|
|
94
|
+
self.response_ttl: int = response_ttl
|
|
95
|
+
self.dns_service_retries: int = dns_service_retries
|
|
96
|
+
self.cache_timeout_minutes: int = cache_timeout_minutes
|
|
97
|
+
|
|
98
|
+
if not tcp_resolve_domain_list:
|
|
99
|
+
self.tcp_resolve_domain_list = list()
|
|
100
|
+
else:
|
|
101
|
+
self.tcp_resolve_domain_list = tcp_resolve_domain_list
|
|
102
|
+
|
|
29
103
|
# Settings for static DNS Responses in offline mode.
|
|
30
|
-
self.offline_route_ipv4 = '10.10.10.10'
|
|
31
|
-
self.offline_route_ipv6 = 'fe80::3c09:df29:d52b:af39'
|
|
32
|
-
self.offline_route_domain = 'domain.com'
|
|
33
|
-
self.offline_srv_answer = \
|
|
104
|
+
self.offline_route_ipv4: str = '10.10.10.10'
|
|
105
|
+
self.offline_route_ipv6: str = 'fe80::3c09:df29:d52b:af39'
|
|
106
|
+
self.offline_route_domain: str = 'domain.com'
|
|
107
|
+
self.offline_srv_answer: str = \
|
|
34
108
|
'. 86391 IN SOA domain.com. domain.com. 2022012500 1800 900 604800 86400'
|
|
109
|
+
# self.offline_https_answer: str = str()
|
|
35
110
|
|
|
36
|
-
# Other settings.
|
|
37
|
-
# Full domain list to pass to TCP Server module.
|
|
38
|
-
self.domain_list: list = list()
|
|
39
|
-
|
|
40
|
-
# Set Buffer size of the connection while receiving messages. The function uses this variable right away.
|
|
41
|
-
self.buffer_size_receive: int = 8192
|
|
42
|
-
# TTL variable that is going to be returned in DNS response.
|
|
43
|
-
self.response_ttl: int = 60
|
|
44
|
-
# How many times the DNS Service will retry on errors (socket connect / request send / response receive)
|
|
45
|
-
self.dns_service_retries: int = 5
|
|
46
111
|
# If forwarding to Live DNS Service fails. Currently, we didn't send anything, so it's 'False'.
|
|
47
112
|
self.retried: bool = False
|
|
48
113
|
# Defining cache dictionary for assigning DNS Questions to DNS Answers
|
|
49
114
|
self.dns_questions_to_answers_cache: dict = dict()
|
|
50
115
|
|
|
51
|
-
# Queue for all the requested domains that hit the dns server.
|
|
52
|
-
# self.request_domain_queue: queue.Queue = queue.Queue()
|
|
53
|
-
self.request_domain_queue = None
|
|
54
|
-
|
|
55
116
|
# Filename to save all the known domains and their relative IPv4 addresses.
|
|
56
117
|
self.known_domains_filename: str = 'dns_known_domains.txt'
|
|
57
118
|
# Filename to save all the known IPv4 addresses and their relative domains.
|
|
@@ -59,18 +120,35 @@ class DnsServer:
|
|
|
59
120
|
# Filename to save domains and their IPv4 addresses by time they hit the DNS server.
|
|
60
121
|
self.known_dns_ipv4_by_time_filename: str = 'dns_ipv4_by_time.txt'
|
|
61
122
|
|
|
62
|
-
# Configuration object with all the settings.
|
|
63
|
-
self.config = config
|
|
64
|
-
|
|
65
123
|
# Logger that logs all the DNS Requests and responses in DNS format. These entries will not present in
|
|
66
124
|
# network log of TCP Server module.
|
|
67
125
|
self.dns_full_logger = loggingw.create_logger(
|
|
68
126
|
logger_name="dns",
|
|
69
|
-
directory_path=self.
|
|
127
|
+
directory_path=self.log_directory_path,
|
|
70
128
|
add_timedfile=True,
|
|
71
129
|
formatter_filehandler='DEFAULT'
|
|
72
130
|
)
|
|
73
131
|
|
|
132
|
+
self.test_config()
|
|
133
|
+
|
|
134
|
+
def test_config(self):
|
|
135
|
+
try:
|
|
136
|
+
booleans.check_3_booleans_when_only_1_can_be_true(
|
|
137
|
+
(self.resolve_to_tcp_server_only_tcp_resolve_domains,
|
|
138
|
+
'resolve_to_tcp_server_only_tcp_resolve_domains'),
|
|
139
|
+
(self.resolve_to_tcp_server_all_domains, 'resolve_to_tcp_server_all_domains'),
|
|
140
|
+
(self.resolve_regular, 'resolve_regular')
|
|
141
|
+
)
|
|
142
|
+
except ValueError as e:
|
|
143
|
+
raise DnsConfigurationValuesError(e)
|
|
144
|
+
|
|
145
|
+
port_in_use = networks.get_processes_using_port_list([self.listening_port])
|
|
146
|
+
if port_in_use:
|
|
147
|
+
error_messages: list = list()
|
|
148
|
+
for port, process_info in port_in_use.items():
|
|
149
|
+
error_messages.append(f"Port [{port}] is already in use by process: {process_info}")
|
|
150
|
+
raise DnsPortInUseError("\n".join(error_messages))
|
|
151
|
+
|
|
74
152
|
def thread_worker_empty_dns_cache(self, function_sleep_time: int):
|
|
75
153
|
"""
|
|
76
154
|
A thread worker function to empty the cache of DNS request and response lists.
|
|
@@ -90,11 +168,6 @@ class DnsServer:
|
|
|
90
168
|
:return: None.
|
|
91
169
|
"""
|
|
92
170
|
|
|
93
|
-
port_in_use = networks.get_processes_using_port_list([self.config['dns']['listening_port']])
|
|
94
|
-
if port_in_use:
|
|
95
|
-
for port, process_info in port_in_use.items():
|
|
96
|
-
raise DnsPortInUseError(f"Port [{port}] is already in use by process: {process_info}")
|
|
97
|
-
|
|
98
171
|
self.logger.info("DNS Server Module Started.")
|
|
99
172
|
|
|
100
173
|
# Define objects for global usage
|
|
@@ -107,19 +180,19 @@ class DnsServer:
|
|
|
107
180
|
known_a_records_ipv4_dict: dict = dict()
|
|
108
181
|
|
|
109
182
|
# Check if 'route_to_tcp_server_only_engine_domains' was set to 'True' and output message accordingly.
|
|
110
|
-
if self.
|
|
183
|
+
if self.resolve_to_tcp_server_only_tcp_resolve_domains:
|
|
111
184
|
message = "Routing only engine domains to Built-in TCP Server."
|
|
112
185
|
print_api(message, logger=self.logger)
|
|
113
186
|
|
|
114
|
-
message = f"Current engine domains: {self.
|
|
187
|
+
message = f"Current engine domains: {self.tcp_resolve_domain_list}"
|
|
115
188
|
print_api(message, logger=self.logger, color='green')
|
|
116
189
|
|
|
117
|
-
if self.
|
|
190
|
+
if self.resolve_to_tcp_server_all_domains:
|
|
118
191
|
message = "Routing all domains to Built-in TCP Server."
|
|
119
192
|
print_api(message, logger=self.logger, color='green')
|
|
120
193
|
|
|
121
|
-
if self.
|
|
122
|
-
message = f"Routing all domains to Live DNS Service: {self.
|
|
194
|
+
if self.resolve_regular:
|
|
195
|
+
message = f"Routing all domains to Live DNS Service: {self.forwarding_dns_service_ipv4}"
|
|
123
196
|
print_api(message, logger=self.logger, color='green')
|
|
124
197
|
|
|
125
198
|
# The list that will hold all the threads that can be joined later
|
|
@@ -127,7 +200,7 @@ class DnsServer:
|
|
|
127
200
|
|
|
128
201
|
# Starting a thread that will empty the DNS Cache lists
|
|
129
202
|
thread_current = threading.Thread(target=self.thread_worker_empty_dns_cache,
|
|
130
|
-
args=(self.
|
|
203
|
+
args=(self.cache_timeout_minutes,))
|
|
131
204
|
thread_current.daemon = True
|
|
132
205
|
# Start the thread
|
|
133
206
|
thread_current.start()
|
|
@@ -142,12 +215,13 @@ class DnsServer:
|
|
|
142
215
|
|
|
143
216
|
# Binding / assigning the port to the server / this script, that is going to be used for
|
|
144
217
|
# receiving connections.
|
|
145
|
-
main_socket_object.bind((self.
|
|
218
|
+
main_socket_object.bind((self.listening_interface, self.listening_port))
|
|
146
219
|
|
|
147
220
|
while True:
|
|
148
221
|
# Needed this logging line when DNS was separate process.
|
|
149
222
|
# self.logger.info("Waiting to receive new requests...")
|
|
150
223
|
|
|
224
|
+
# noinspection PyBroadException
|
|
151
225
|
try:
|
|
152
226
|
client_data, client_address = main_socket_object.recvfrom(self.buffer_size_receive)
|
|
153
227
|
client_data: bytes
|
|
@@ -171,6 +245,7 @@ class DnsServer:
|
|
|
171
245
|
pass
|
|
172
246
|
continue
|
|
173
247
|
|
|
248
|
+
# noinspection PyBroadException
|
|
174
249
|
try:
|
|
175
250
|
# This is the real point when the request received was logged, but since it takes too much place
|
|
176
251
|
# on the screen, moved it to full request logging position.
|
|
@@ -180,11 +255,11 @@ class DnsServer:
|
|
|
180
255
|
|
|
181
256
|
# Received DNS request that needs to be parsed to readable format
|
|
182
257
|
dns_object: dnslib.dns.DNSRecord = DNSRecord.parse(client_data)
|
|
183
|
-
# "qtype" returns as numeric identification, we need to convert it to
|
|
184
|
-
# provided by the dnslib
|
|
258
|
+
# "qtype" returns as numeric identification, we need to convert it to
|
|
259
|
+
# Readable QType (DNS Record Type) provided by the dnslib
|
|
185
260
|
# "dns_object.q" is the Question from the client that holds all the DNS question data,
|
|
186
|
-
# like which domain was
|
|
187
|
-
#
|
|
261
|
+
# like which domain was questioned for resolving,
|
|
262
|
+
# the class (example: IN), DNS Record Type that was questioned and a header.
|
|
188
263
|
# "dns_object.q.qtype" returns only QType of the Question
|
|
189
264
|
qtype_string: str = dnslib.QTYPE[dns_object.q.qtype]
|
|
190
265
|
# "qclass" returns as numeric identification, we need to convert it
|
|
@@ -204,7 +279,8 @@ class DnsServer:
|
|
|
204
279
|
self.dns_full_logger.info(f"QTYPE: {qtype_string}")
|
|
205
280
|
self.dns_full_logger.info(f"Question Domain: {question_domain}")
|
|
206
281
|
|
|
207
|
-
message = f"Received request
|
|
282
|
+
message = (f"Received DNS request: {question_domain} | {qclass_string} | {qtype_string} | "
|
|
283
|
+
f"From: {client_address}.")
|
|
208
284
|
self.logger.info(message)
|
|
209
285
|
self.dns_full_logger.info(message)
|
|
210
286
|
|
|
@@ -229,12 +305,12 @@ class DnsServer:
|
|
|
229
305
|
else:
|
|
230
306
|
# Check if the incoming Record is "A" record.
|
|
231
307
|
if qtype_string == "A":
|
|
232
|
-
# Check if '
|
|
233
|
-
# If so, we need to check if the incoming domain contain any of the
|
|
234
|
-
if self.
|
|
308
|
+
# Check if 'resolve_to_tcp_server_only_tcp_resolve_domains' is set to 'True'.
|
|
309
|
+
# If so, we need to check if the incoming domain contain any of the domains in the list.
|
|
310
|
+
if self.resolve_to_tcp_server_only_tcp_resolve_domains:
|
|
235
311
|
# If current query domain (+ subdomains) CONTAIN any of the domains from modules config
|
|
236
312
|
# files and current request contains "A" (IPv4) record.
|
|
237
|
-
if any(x in question_domain for x in self.
|
|
313
|
+
if any(x in question_domain for x in self.tcp_resolve_domain_list):
|
|
238
314
|
# If incoming domain contains any of the 'engine_domains' then domain will
|
|
239
315
|
# be forwarded to our TCP Server.
|
|
240
316
|
forward_to_tcp_server = True
|
|
@@ -243,12 +319,12 @@ class DnsServer:
|
|
|
243
319
|
|
|
244
320
|
# If 'route_to_tcp_server_all_domains' was set to 'False' in 'config.ini' file then
|
|
245
321
|
# we'll forward all 'A' records domains to the Built-in TCP Server.
|
|
246
|
-
if self.
|
|
322
|
+
if self.resolve_to_tcp_server_all_domains:
|
|
247
323
|
forward_to_tcp_server = True
|
|
248
324
|
|
|
249
325
|
# If 'regular_resolving' was set to 'True' in 'config.ini' file then
|
|
250
326
|
# we'll forward all 'A' records domains to the Live DNS Service.
|
|
251
|
-
if self.
|
|
327
|
+
if self.resolve_regular:
|
|
252
328
|
forward_to_tcp_server = False
|
|
253
329
|
|
|
254
330
|
# If incoming record is not an "A" record, then it will not be forwarded to our TCP Server.
|
|
@@ -268,7 +344,7 @@ class DnsServer:
|
|
|
268
344
|
# q=DNSQuestion(question_domain),
|
|
269
345
|
q=dns_object.q,
|
|
270
346
|
a=RR(question_domain,
|
|
271
|
-
rdata=A(self.
|
|
347
|
+
rdata=A(self.tcp_target_server_ipv4),
|
|
272
348
|
ttl=self.response_ttl)
|
|
273
349
|
)
|
|
274
350
|
# Encode the response that was built above to legit DNS Response
|
|
@@ -279,7 +355,7 @@ class DnsServer:
|
|
|
279
355
|
# any of the domains from modules config files
|
|
280
356
|
else:
|
|
281
357
|
# If we're in offline mode
|
|
282
|
-
if self.
|
|
358
|
+
if self.offline_mode:
|
|
283
359
|
# Make DNS response that will refer TCP traffic to our server
|
|
284
360
|
# dns_question = DNSRecord.question(question_domain)
|
|
285
361
|
dns_built_response = dns_object.reply()
|
|
@@ -290,8 +366,8 @@ class DnsServer:
|
|
|
290
366
|
if qtype_string == "AAAA":
|
|
291
367
|
dns_built_response.add_answer(
|
|
292
368
|
*RR.fromZone(
|
|
293
|
-
question_domain
|
|
294
|
-
self.offline_route_ipv6)
|
|
369
|
+
f'{question_domain} {str(self.response_ttl)} {qtype_string} '
|
|
370
|
+
f'{self.offline_route_ipv6}')
|
|
295
371
|
)
|
|
296
372
|
|
|
297
373
|
message = f"!!! Question / Answer is in offline mode returning " \
|
|
@@ -308,7 +384,7 @@ class DnsServer:
|
|
|
308
384
|
# com. domain.com. 2022012500 1800 900 604800 86400
|
|
309
385
|
# Basically SOA is the same, but can be with additional fields.
|
|
310
386
|
# Since, it's offline and not online - we don't really care.
|
|
311
|
-
elif qtype_string == "SRV" or qtype_string == "SOA":
|
|
387
|
+
elif qtype_string == "SRV" or qtype_string == "SOA" or qtype_string == "HTTPS":
|
|
312
388
|
dns_built_response.add_answer(*RR.fromZone(self.offline_srv_answer))
|
|
313
389
|
|
|
314
390
|
message = f"!!! Question / Answer is in offline mode returning: " \
|
|
@@ -317,8 +393,6 @@ class DnsServer:
|
|
|
317
393
|
self.dns_full_logger.info(message)
|
|
318
394
|
elif qtype_string == "ANY":
|
|
319
395
|
dns_built_response.add_answer(
|
|
320
|
-
# *RR.fromZone(question_domain + " " + str(response_ttl) + " " + qclass_string +
|
|
321
|
-
# " CNAME " + dns_server_offline_route_domain)
|
|
322
396
|
*RR.fromZone(question_domain + " " + str(self.response_ttl) + " CNAME " +
|
|
323
397
|
self.offline_route_domain)
|
|
324
398
|
)
|
|
@@ -330,8 +404,8 @@ class DnsServer:
|
|
|
330
404
|
else:
|
|
331
405
|
dns_built_response.add_answer(
|
|
332
406
|
*RR.fromZone(
|
|
333
|
-
question_domain + " " + str(self.response_ttl) + " " + qtype_string +
|
|
334
|
-
self.offline_route_ipv4)
|
|
407
|
+
question_domain + " " + str(self.response_ttl) + " " + qtype_string +
|
|
408
|
+
" " + self.offline_route_ipv4)
|
|
335
409
|
)
|
|
336
410
|
|
|
337
411
|
message = f"!!! Question / Answer is in offline mode returning " \
|
|
@@ -353,7 +427,8 @@ class DnsServer:
|
|
|
353
427
|
# General exception in response creation.
|
|
354
428
|
except Exception:
|
|
355
429
|
message = \
|
|
356
|
-
f"Unknown exception while creating response for QTYPE: {qtype_string}.
|
|
430
|
+
(f"Unknown exception while creating response for QTYPE: {qtype_string}. "
|
|
431
|
+
f"Response: ")
|
|
357
432
|
print_api(message, logger=self.logger, logger_method='critical',
|
|
358
433
|
traceback_string=True, oneline=True)
|
|
359
434
|
print_api(f"{dns_built_response}", logger=self.logger, logger_method='critical',
|
|
@@ -381,8 +456,8 @@ class DnsServer:
|
|
|
381
456
|
self.logger.info(f"Retry #: {counter}/{self.dns_service_retries}")
|
|
382
457
|
self.dns_full_logger.info(
|
|
383
458
|
f"Forwarding request. Creating UDP socket to: "
|
|
384
|
-
f"{self.
|
|
385
|
-
f"{
|
|
459
|
+
f"{self.forwarding_dns_service_ipv4}:"
|
|
460
|
+
f"{self.forwarding_dns_service_port}")
|
|
386
461
|
try:
|
|
387
462
|
google_dns_ipv4_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
|
388
463
|
google_dns_ipv4_socket.settimeout(5)
|
|
@@ -392,8 +467,8 @@ class DnsServer:
|
|
|
392
467
|
self.dns_full_logger.info(message)
|
|
393
468
|
|
|
394
469
|
google_dns_ipv4_socket.sendto(client_data, (
|
|
395
|
-
self.
|
|
396
|
-
|
|
470
|
+
self.forwarding_dns_service_ipv4,
|
|
471
|
+
self.forwarding_dns_service_port
|
|
397
472
|
))
|
|
398
473
|
# The script needs to wait a second or receive can hang
|
|
399
474
|
message = "Request sent to the forwarding DNS, Receiving the answer..."
|
|
@@ -417,7 +492,7 @@ class DnsServer:
|
|
|
417
492
|
self.logger.info(
|
|
418
493
|
f"Retried {self.dns_service_retries} times. "
|
|
419
494
|
f"Couldn't forward DNS request to: "
|
|
420
|
-
f"[{self.
|
|
495
|
+
f"[{self.forwarding_dns_service_ipv4}]. "
|
|
421
496
|
f"Continuing to next request.")
|
|
422
497
|
self.dns_full_logger.info("==========")
|
|
423
498
|
|
|
@@ -433,7 +508,7 @@ class DnsServer:
|
|
|
433
508
|
continue
|
|
434
509
|
|
|
435
510
|
self.dns_full_logger.info(
|
|
436
|
-
f"Answer received from: {self.
|
|
511
|
+
f"Answer received from: {self.forwarding_dns_service_ipv4}")
|
|
437
512
|
|
|
438
513
|
# Closing the socket to forwarding service
|
|
439
514
|
google_dns_ipv4_socket.close()
|
|
@@ -442,20 +517,11 @@ class DnsServer:
|
|
|
442
517
|
# Appending current DNS Request and DNS Answer to the Cache
|
|
443
518
|
self.dns_questions_to_answers_cache.update({client_data: dns_response})
|
|
444
519
|
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
# dns_response = dns_object.reply()
|
|
448
|
-
# dns_response.add_answer(*RR.fromZone(f"{question_domain} 60 {qtype_object} 8.8.8.8"))
|
|
449
|
-
|
|
450
|
-
# dns_built_response = \
|
|
451
|
-
# DNSRecord(
|
|
452
|
-
# DNSHeader(id=dns_object.header.id, qr=1, aa=1, ra=1), q=DNSQuestion(question_domain),
|
|
453
|
-
# a=RR.fromZone(question_domain + " 60 " + qtype_object + " " + dns_server_offline_ipv4))
|
|
454
|
-
|
|
455
|
-
# If 'forward_to_tcp_server' it means that we built the response, and we don't need to reparse it, since
|
|
456
|
-
# we already have all the data.
|
|
520
|
+
# If 'forward_to_tcp_server' it means that we built the response, and we don't need to reparse it,
|
|
521
|
+
# since we already have all the data.
|
|
457
522
|
if forward_to_tcp_server:
|
|
458
523
|
self.dns_full_logger.info(f"Response IP: {dns_built_response.short()}")
|
|
524
|
+
self.logger.info(f"Response {dns_built_response.short()}")
|
|
459
525
|
|
|
460
526
|
message = f"Response Details: {dns_built_response.rr}"
|
|
461
527
|
print_api(message, logger=self.dns_full_logger, logger_method='info', oneline=True)
|
|
@@ -501,7 +567,7 @@ class DnsServer:
|
|
|
501
567
|
# for index, ip_address in enumerate(ipv4_addresses):
|
|
502
568
|
# ipv4_addresses[index] = str(ip_address)
|
|
503
569
|
|
|
504
|
-
#
|
|
570
|
+
# ==================================================================================================
|
|
505
571
|
# # Known domain dictionary of last 2 A records' management.
|
|
506
572
|
#
|
|
507
573
|
# # Sorting the addresses, so it will be easier to compare dictionaries in the list.
|
|
@@ -523,7 +589,7 @@ class DnsServer:
|
|
|
523
589
|
#
|
|
524
590
|
# dns.logger.info(f"Latest known list: {known_a_records_domains_list_last_entries}")
|
|
525
591
|
|
|
526
|
-
#
|
|
592
|
+
# ==================================================================================================
|
|
527
593
|
# Known domain list management (A Records only)
|
|
528
594
|
|
|
529
595
|
# If current request is in the cache,
|
|
@@ -569,20 +635,20 @@ class DnsServer:
|
|
|
569
635
|
|
|
570
636
|
# Save this string object as log file.
|
|
571
637
|
with open(
|
|
572
|
-
self.
|
|
638
|
+
self.log_directory_path + os.sep + self.known_domains_filename, 'w'
|
|
573
639
|
) as output_file:
|
|
574
640
|
output_file.write(record_string_line)
|
|
575
641
|
|
|
576
642
|
self.dns_full_logger.info(
|
|
577
643
|
f"Saved new known domains file: "
|
|
578
|
-
f"{self.
|
|
644
|
+
f"{self.log_directory_path}{os.sep}{self.known_domains_filename}")
|
|
579
645
|
|
|
580
646
|
# Known domain list managements EOF
|
|
581
|
-
#
|
|
647
|
+
# ==================================================================================================
|
|
582
648
|
# Known IPv4 address to domains list management (A Records only)
|
|
583
649
|
|
|
584
650
|
# If DNS Server 'offline_mode' was set to 'False'.
|
|
585
|
-
if not self.
|
|
651
|
+
if not self.offline_mode:
|
|
586
652
|
dump_ipv4_dictionary_to_file = False
|
|
587
653
|
# If IPv4 address list is not empty, meaning this DNS request was A type.
|
|
588
654
|
if ipv4_addresses:
|
|
@@ -595,9 +661,9 @@ class DnsServer:
|
|
|
595
661
|
# If so, get the list of current domains for current ipv4 address.
|
|
596
662
|
current_domains_list = known_a_records_ipv4_dict[current_ip_address]
|
|
597
663
|
|
|
598
|
-
# If current question domain is not in the known domains that we had from
|
|
599
|
-
# requests for the same IPv4 address, then we'll add this domain
|
|
600
|
-
# list for this IPv4.
|
|
664
|
+
# If current question domain is not in the known domains that we had from
|
|
665
|
+
# previous DNS requests for the same IPv4 address, then we'll add this domain
|
|
666
|
+
# to the known domains list for this IPv4.
|
|
601
667
|
# And update the dictionary of known IPv4 addresses and their domains.
|
|
602
668
|
if question_domain not in current_domains_list:
|
|
603
669
|
current_domains_list.append(question_domain)
|
|
@@ -628,16 +694,16 @@ class DnsServer:
|
|
|
628
694
|
|
|
629
695
|
# Save this string object as log file.
|
|
630
696
|
with open(
|
|
631
|
-
self.
|
|
697
|
+
self.log_directory_path + os.sep + self.known_ipv4_filename, 'w'
|
|
632
698
|
) as output_file:
|
|
633
699
|
output_file.write(record_string_line)
|
|
634
700
|
|
|
635
701
|
self.dns_full_logger.info(
|
|
636
702
|
f"Saved new known IPv4 addresses file: "
|
|
637
|
-
f"{self.
|
|
703
|
+
f"{self.log_directory_path}{os.sep}{self.known_ipv4_filename}")
|
|
638
704
|
|
|
639
705
|
# Known IPv4 address to domains list management EOF
|
|
640
|
-
#
|
|
706
|
+
# ==================================================================================================
|
|
641
707
|
# Writing IPs by time.
|
|
642
708
|
|
|
643
709
|
# If IPv4 address list is not empty, meaning this DNS request was A type.
|
|
@@ -648,25 +714,12 @@ class DnsServer:
|
|
|
648
714
|
|
|
649
715
|
# Save this string object as log file.
|
|
650
716
|
with open(
|
|
651
|
-
self.
|
|
717
|
+
self.log_directory_path + os.sep + self.known_dns_ipv4_by_time_filename, 'a'
|
|
652
718
|
) as output_file:
|
|
653
719
|
output_file.write(record_string_line + '\n')
|
|
654
720
|
|
|
655
721
|
# EOF Writing IPs by time.
|
|
656
|
-
#
|
|
657
|
-
# SSH Remote / LOCALHOST script execution to identify process section
|
|
658
|
-
|
|
659
|
-
# Starting a thread that will query IPs of the last DNS request.
|
|
660
|
-
# thread_current = \
|
|
661
|
-
# threading.Thread(
|
|
662
|
-
# target=thread_worker_check_process_by_ip, args=(ipv4_addresses, client_address[0],))
|
|
663
|
-
# # Append to list of threads, so they can be "joined" later
|
|
664
|
-
# threads_list.append(thread_current)
|
|
665
|
-
# # Start the thread
|
|
666
|
-
# thread_current.start()
|
|
667
|
-
|
|
668
|
-
# EOF SSH / LOCALHOST executing process command line harvesting.
|
|
669
|
-
# ==================================================================================================================
|
|
722
|
+
# ==================================================================================================
|
|
670
723
|
|
|
671
724
|
self.dns_full_logger.info("==========")
|
|
672
725
|
except Exception:
|