From 9974823464dce4d344f6beadee0f14ce9dccef64 Mon Sep 17 00:00:00 2001 From: Terrtia Date: Wed, 31 Mar 2021 11:25:09 +0200 Subject: [PATCH] chg: [passiveDns D4 Client] add passiveDns D4 Client --- .gitignore | 1 + bin/DomClassifier.py | 46 +++++--- bin/LAUNCH.sh | 2 + bin/core/D4_client.py | 52 ++++++++++ bin/lib/d4.py | 74 +++++++++++++ bin/lib/item_basic.py | 8 ++ bin/packages/modules.cfg | 4 + configs/d4client_passiveDNS_conf/destination | 1 + configs/d4client_passiveDNS_conf/key | 1 + configs/d4client_passiveDNS_conf/snaplen | 1 + configs/d4client_passiveDNS_conf/source | 1 + configs/d4client_passiveDNS_conf/type | 1 + configs/d4client_passiveDNS_conf/version | 1 + var/www/modules/settings/Flask_settings.py | 18 +++- .../settings/templates/passive_dns.html | 98 ++++++++++++++++++ var/www/static/image/d4-logo.png | Bin 0 -> 17341 bytes var/www/templates/settings/menu_sidebar.html | 11 ++ 17 files changed, 301 insertions(+), 19 deletions(-) create mode 100755 bin/core/D4_client.py create mode 100755 bin/lib/d4.py create mode 100644 configs/d4client_passiveDNS_conf/destination create mode 100644 configs/d4client_passiveDNS_conf/key create mode 100644 configs/d4client_passiveDNS_conf/snaplen create mode 100644 configs/d4client_passiveDNS_conf/source create mode 100644 configs/d4client_passiveDNS_conf/type create mode 100644 configs/d4client_passiveDNS_conf/version create mode 100644 var/www/modules/settings/templates/passive_dns.html create mode 100644 var/www/static/image/d4-logo.png diff --git a/.gitignore b/.gitignore index f9d2344e..b12d5a13 100644 --- a/.gitignore +++ b/.gitignore @@ -46,6 +46,7 @@ configs/core.cfg.backup configs/update.cfg update/current_version files +configs/d4client_passiveDNS_conf/uuid # Trackers bin/trackers/yara/custom-rules/* diff --git a/bin/DomClassifier.py b/bin/DomClassifier.py index 1ae5ba13..aee83ca9 100755 --- a/bin/DomClassifier.py +++ b/bin/DomClassifier.py @@ -9,13 +9,18 @@ The DomClassifier modules extract and classify Internet domains/hostnames/IP add the out output of the Global module. """ +import os +import sys import time -from packages import Paste from pubsublogger import publisher import DomainClassifier.domainclassifier from Helper import Process +sys.path.append(os.path.join(os.environ['AIL_BIN'], 'lib')) +import d4 +import item_basic + def main(): publisher.port = 6380 @@ -35,35 +40,42 @@ def main(): while True: try: - message = p.get_from_set() + item_id = p.get_from_set() - if message is not None: - PST = Paste.Paste(message) - else: + if item_id is None: publisher.debug("Script DomClassifier is idling 1s") time.sleep(1) continue - paste = PST.get_p_content() - mimetype = PST._get_p_encoding() - if mimetype == "text/plain": - c.text(rawtext=paste) + item_content = item_basic.get_item_content(item_id) + mimetype = item_basic.get_item_mimetype(item_id) + item_basename = item_basic.get_basename(item_id) + item_source = item_basic.get_source(item_id) + item_date = item_basic.get_item_date(item_id) + + if mimetype.split('/')[0] == "text": + c.text(rawtext=item_content) c.potentialdomain() - c.validdomain(rtype=['A'], extended=True) + c.validdomain(rtype=['A'], passive_dns=True, extended=False) + print(c.vdomain) + + if c.vdomain and d4.is_passive_dns_enabled(): + for dns_record in c.vdomain: + p.populate_set_out(dns_record) + localizeddomains = c.include(expression=cc_tld) if localizeddomains: print(localizeddomains) - publisher.warning('DomainC;{};{};{};Checked {} located in {};{}'.format( - PST.p_source, PST.p_date, PST.p_name, localizeddomains, cc_tld, PST.p_rel_path)) + publisher.warning(f"DomainC;{item_source};{item_date};{item_basename};Checked {localizeddomains} located in {cc_tld};{item_id}") localizeddomains = c.localizedomain(cc=cc) + if localizeddomains: print(localizeddomains) - publisher.warning('DomainC;{};{};{};Checked {} located in {};{}'.format( - PST.p_source, PST.p_date, PST.p_name, localizeddomains, cc, PST.p_rel_path)) + publisher.warning(f"DomainC;{item_source};{item_date};{item_basename};Checked {localizeddomains} located in {cc};{item_id}") + except IOError: - print("CRC Checksum Failed on :", PST.p_rel_path) - publisher.error('Duplicate;{};{};{};CRC Checksum Failed'.format( - PST.p_source, PST.p_date, PST.p_name)) + print("CRC Checksum Failed on :", item_id) + publisher.error(f"Duplicate;{item_source};{item_date};{item_basename};CRC Checksum Failed") if __name__ == "__main__": main() diff --git a/bin/LAUNCH.sh b/bin/LAUNCH.sh index e231966c..874108b7 100755 --- a/bin/LAUNCH.sh +++ b/bin/LAUNCH.sh @@ -152,6 +152,8 @@ function launching_scripts { sleep 0.1 screen -S "Script_AIL" -X screen -t "Crawler_manager" bash -c "cd ${AIL_BIN}/core; ${ENV_PY} ./Crawler_manager.py; read x" sleep 0.1 + screen -S "Script_AIL" -X screen -t "D4_client" bash -c "cd ${AIL_BIN}/core; ${ENV_PY} ./D4_client.py; read x" + sleep 0.1 screen -S "Script_AIL" -X screen -t "ModuleInformation" bash -c "cd ${AIL_BIN}; ${ENV_PY} ./ModulesInformationV2.py -k 0 -c 1; read x" diff --git a/bin/core/D4_client.py b/bin/core/D4_client.py new file mode 100755 index 00000000..ab5f99d2 --- /dev/null +++ b/bin/core/D4_client.py @@ -0,0 +1,52 @@ +#!/usr/bin/env python3 +# -*-coding:UTF-8 -* + +""" +The D4_Client Module +============================ + +The D4_Client modules send all DNS records to a D4 Server. +Data produced by D4 sensors are ingested into +a Passive DNS server which can be queried later to search for the Passive DNS records. +""" + +import os +import sys +import time +from pubsublogger import publisher +sys.path.append(os.environ['AIL_BIN']) +from Helper import Process + +sys.path.append(os.path.join(os.environ['AIL_BIN'], 'lib')) +import ConfigLoader +import d4 + +# # TODO: lauch me in core screen +# # TODO: check if already launched in core screen + +if __name__ == '__main__': + publisher.port = 6380 + publisher.channel = "Script" + + config_section = 'D4_client' + p = Process(config_section) + publisher.info("""D4_client is Running""") + + last_refresh = time.time() + d4_client = d4.create_d4_client() + + while True: + if last_refresh < d4.get_config_last_update_time(): + d4_client = d4.create_d4_client() + last_refresh = time.time() + print('D4 Client: config updated') + + dns_record = p.get_from_set() + if dns_record is None: + publisher.debug("Script D4_client is idling 1s") + time.sleep(1) + continue + + if d4_client: + # Send DNS Record to D4Server + d4_client.send_manual_data(dns_record) diff --git a/bin/lib/d4.py b/bin/lib/d4.py new file mode 100755 index 00000000..e3305f75 --- /dev/null +++ b/bin/lib/d4.py @@ -0,0 +1,74 @@ +#!/usr/bin/env python3 +# -*-coding:UTF-8 -* + +import os +import sys +import time +import redis +import d4_pyclient + +sys.path.append(os.path.join(os.environ['AIL_BIN'], 'lib')) +import ConfigLoader + +config_loader = ConfigLoader.ConfigLoader() +r_serv_db = config_loader.get_redis_conn("ARDB_DB") +r_cache = config_loader.get_redis_conn("Redis_Cache") +config_loader = None + +def get_ail_uuid(): + return r_serv_db.get('ail:uuid') + +def get_d4_client_config_dir(): + return os.path.join(os.environ['AIL_HOME'], 'configs', 'd4client_passiveDNS_conf') + +def create_d4_config_file(filename, content): + if not os.path.isfile(filename): + with open(filename, 'a') as f: + f.write(content) + +def get_d4_client_config(): + d4_client_config = get_d4_client_config_dir() + filename = os.path.join(d4_client_config, 'uuid') + if not os.path.isfile(filename): + create_d4_config_file(filename, get_ail_uuid()) + return d4_client_config + +def is_passive_dns_enabled(cache=True): + if cache: + res = r_cache.get('d4:passivedns:enabled') + if res is None: + res = r_serv_db.hget('d4:passivedns', 'enabled') == 'True' + r_cache.set('d4:passivedns:enabled', res) + return res + else: + return res == 'True' + else: + return r_serv_db.hget('d4:passivedns', 'enabled') == 'True' + +def change_passive_dns_state(new_state): + old_state = is_passive_dns_enabled(cache=False) + if old_state != new_state: + r_serv_db.hset('d4:passivedns', 'enabled', bool(new_state)) + r_cache.set('d4:passivedns:enabled', bool(new_state)) + update_time = time.time() + r_serv_db.hset('d4:passivedns', 'update_time', update_time) + r_cache.set('d4:passivedns:last_update_time', update_time) + return True + return False + +def get_config_last_update_time(): + last_update_time = r_cache.get('d4:passivedns:last_update_time') + if not last_update_time: + last_update_time = r_serv_db.hget('d4:passivedns', 'update_time') + if not last_update_time: + last_update_time = 0 + last_update_time = float(last_update_time) + r_cache.set('d4:passivedns:last_update_time', last_update_time) + return float(last_update_time) + +def create_d4_client(): + if is_passive_dns_enabled(): + d4_client = d4_pyclient.D4Client(get_d4_client_config(), False) + return d4_client + else: + return None diff --git a/bin/lib/item_basic.py b/bin/lib/item_basic.py index 010e30b6..1b7e0de5 100755 --- a/bin/lib/item_basic.py +++ b/bin/lib/item_basic.py @@ -5,6 +5,8 @@ import os import sys import gzip +import magic + sys.path.append(os.path.join(os.environ['AIL_BIN'], 'lib/')) import ConfigLoader @@ -35,6 +37,9 @@ def get_item_date(item_id, add_separator=False): else: return '{}{}{}'.format(l_directory[-4], l_directory[-3], l_directory[-2]) +def get_basename(item_id): + return os.path.basename(item_id) + def get_source(item_id): return item_id.split('/')[-5] @@ -63,6 +68,9 @@ def get_item_content(item_id): item_content = '' return str(item_content) +def get_item_mimetype(item_id): + return magic.from_buffer(get_item_content(item_id), mime=True) + #### TREE CHILD/FATHER #### def is_father(item_id): return r_serv_metadata.exists('paste_children:{}'.format(item_id)) diff --git a/bin/packages/modules.cfg b/bin/packages/modules.cfg index 302b68af..c29ff926 100644 --- a/bin/packages/modules.cfg +++ b/bin/packages/modules.cfg @@ -21,6 +21,10 @@ subscribe = Redis_Global [DomClassifier] subscribe = Redis_Global +publish = Redis_D4_client + +[D4_client] +subscribe = Redis_D4_client [TermTrackerMod] subscribe = Redis_Global diff --git a/configs/d4client_passiveDNS_conf/destination b/configs/d4client_passiveDNS_conf/destination new file mode 100644 index 00000000..69cef238 --- /dev/null +++ b/configs/d4client_passiveDNS_conf/destination @@ -0,0 +1 @@ +d4pdns.circl.lu:4443 diff --git a/configs/d4client_passiveDNS_conf/key b/configs/d4client_passiveDNS_conf/key new file mode 100644 index 00000000..2c8a76aa --- /dev/null +++ b/configs/d4client_passiveDNS_conf/key @@ -0,0 +1 @@ +ail passivedns sensor key diff --git a/configs/d4client_passiveDNS_conf/snaplen b/configs/d4client_passiveDNS_conf/snaplen new file mode 100644 index 00000000..801c306e --- /dev/null +++ b/configs/d4client_passiveDNS_conf/snaplen @@ -0,0 +1 @@ +4096 diff --git a/configs/d4client_passiveDNS_conf/source b/configs/d4client_passiveDNS_conf/source new file mode 100644 index 00000000..cf52303b --- /dev/null +++ b/configs/d4client_passiveDNS_conf/source @@ -0,0 +1 @@ +stdin diff --git a/configs/d4client_passiveDNS_conf/type b/configs/d4client_passiveDNS_conf/type new file mode 100644 index 00000000..45a4fb75 --- /dev/null +++ b/configs/d4client_passiveDNS_conf/type @@ -0,0 +1 @@ +8 diff --git a/configs/d4client_passiveDNS_conf/version b/configs/d4client_passiveDNS_conf/version new file mode 100644 index 00000000..d00491fd --- /dev/null +++ b/configs/d4client_passiveDNS_conf/version @@ -0,0 +1 @@ +1 diff --git a/var/www/modules/settings/Flask_settings.py b/var/www/modules/settings/Flask_settings.py index 6b8cdb09..68ccd517 100644 --- a/var/www/modules/settings/Flask_settings.py +++ b/var/www/modules/settings/Flask_settings.py @@ -14,6 +14,7 @@ import json import datetime import git_status +import d4 # ============ VARIABLES ============ import Flask_config @@ -21,8 +22,6 @@ import Flask_config app = Flask_config.app baseUrl = Flask_config.baseUrl r_serv_db = Flask_config.r_serv_db -max_preview_char = Flask_config.max_preview_char -max_preview_modal = Flask_config.max_preview_modal REPO_ORIGIN = Flask_config.REPO_ORIGIN dict_update_description = Flask_config.dict_update_description email_regex = Flask_config.email_regex @@ -274,5 +273,20 @@ def get_background_update_stats_json(): else: return jsonify({}) +@settings.route("/settings/passivedns", methods=['GET']) +@login_required +@login_read_only +def passive_dns(): + passivedns_enabled = d4.is_passive_dns_enabled() + return render_template("passive_dns.html", passivedns_enabled=passivedns_enabled) + +@settings.route("/settings/passivedns/change_state", methods=['GET']) +@login_required +@login_admin +def passive_dns_change_state(): + new_state = request.args.get('state') == 'enable' + passivedns_enabled = d4.change_passive_dns_state(new_state) + return redirect(url_for('settings.passive_dns')) + # ========= REGISTRATION ========= app.register_blueprint(settings, url_prefix=baseUrl) diff --git a/var/www/modules/settings/templates/passive_dns.html b/var/www/modules/settings/templates/passive_dns.html new file mode 100644 index 00000000..0b21c82f --- /dev/null +++ b/var/www/modules/settings/templates/passive_dns.html @@ -0,0 +1,98 @@ + + + + + Passive DNS - AIL + + + + + + + + + + + + + + + + + + {% include 'nav_bar.html' %} + +
+
+ + {% include 'settings/menu_sidebar.html' %} + +
+ +
+ + D4 project + +
+ +

+ Passive DNS or pDNS is a service which records domain name system server (DNS) answers to DNS client requests.
+ In order to see the evolution of records over time, a history is recorded.
+ Various sources can be used to build a large sensor network.
+
+ Enabling the D4 passive DNS sensor in AIL will contribute resolved domains and host to the global Passive DNS community operated by + + CIRCL.lu + +
+
+ (if you want to have access to the global Passive DNS community + + https://www.circl.lu/services/passive-dns + + ) +

+ + + {% if passivedns_enabled %} + + + + {% else %} + + + + {% endif %} +
+
+
+ + + + + + diff --git a/var/www/static/image/d4-logo.png b/var/www/static/image/d4-logo.png new file mode 100644 index 0000000000000000000000000000000000000000..63fe5a0972bdf1db26d88b3a739e17264718427c GIT binary patch literal 17341 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 g9;|d%JimUICMMv%>Ua + +