From 30a02da435e7b2ffa6aadf7c198dc4953805c003 Mon Sep 17 00:00:00 2001 From: cyril constantin Date: Sun, 20 Sep 2026 11:10:05 +0200 Subject: [PATCH] up --- check_host.sh | 39 ++++++++++++++++++++++ dnscap.service | 18 ++++++++++ log.nft | 41 +++++++++++++++++++++++ report.py | 89 ++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 187 insertions(+) create mode 100644 check_host.sh create mode 100644 dnscap.service create mode 100644 log.nft create mode 100644 report.py diff --git a/check_host.sh b/check_host.sh new file mode 100644 index 0000000..f68cfb7 --- /dev/null +++ b/check_host.sh @@ -0,0 +1,39 @@ +#!/usr/bin/env bash + +if ! sudo which nft +then + echo "install nftables" + exit 1 +fi + +if ! sudo nft list ruleset |grep output +then + sudo nft -f log.nft +fi + +if ! sudo nft list ruleset |grep output +then + echo "nft error" + exit 1 +fi + +if ! id | grep systemd-journal +then + echo "sudo adduser $(whoami) systemd-journal" + sudo adduser "$(whoami)" systemd-journal + exit 1 +fi + +packages="python3-systemd python3-tabulate python3-dns dnscap python3-pure-pcapy3 tshark" + +apt -s install "${packages}" +echo "apt-get -s ${packages}" +if apt-get -s install "${packages}" |grep ^Inst +then + echo "install python packages" + exit 1 +fi + +echo "####################" +echo "### System Ready " +echo "####################" \ No newline at end of file diff --git a/dnscap.service b/dnscap.service new file mode 100644 index 0000000..0581d22 --- /dev/null +++ b/dnscap.service @@ -0,0 +1,18 @@ +[Unit] +Description=Dnscap Daemon +After=network-online.target + +[Service] +Type=simple +User=root +Group=root +UMask=007 + +ExecStart=/usr/bin/dnscap -b -o pid_file=/var/run/dnscap.pid -i any -p -w - -t 600 -k /usr/bin/tshark -r - -T json | /usr/local/bin/report.py +Restart=on-failure + +# Configures the time to wait before service is stopped forcefully. +TimeoutStopSec=10 + +[Install] +WantedBy=multi-user.target diff --git a/log.nft b/log.nft new file mode 100644 index 0000000..0083e52 --- /dev/null +++ b/log.nft @@ -0,0 +1,41 @@ +#!/usr/sbin/nft -f + +flush ruleset + +table inet filter { + chain input { + type filter hook input priority 0; policy drop; + iif lo accept + ct state established,related accept + # Log and drop invalid packets + ct state invalid log prefix "INVALID: " level warn drop + # Log and accept SSH + tcp dport 22 ct state new log prefix "SSH: " level info accept + # Allow web traffic (no logging to reduce volume) + #tcp dport { 80, 443 } accept + # Log everything else that reaches the end (default drop) + log prefix "INPUT DROP: " level warn + } + + chain forward { + type filter hook forward priority 0; policy drop; + + log prefix "FORWARD DROP: " level warn + } + + chain output { + type filter hook output priority 0; policy accept; + # dns request + udp dport 53 log prefix "DNS:" level info + # accept local connection + ip daddr 192.168.122.1 counter accept + ip daddr 192.168.0.253 counter accept + ip daddr 192.168.0.254 counter accept + # counter output packets + counter comment "Count accepted packets" + # not logging established + ct state established,related accept + # Log and accept output packets + log prefix "OUTPUT:" level info flags skuid accept + } +} \ No newline at end of file diff --git a/report.py b/report.py new file mode 100644 index 0000000..4c355e9 --- /dev/null +++ b/report.py @@ -0,0 +1,89 @@ +#!/usr/bin/env python3 + +from systemd import journal +from datetime import datetime, timedelta +import re # read lines +# Import smtplib for the actual sending function +import smtplib +# Import the email modules we'll need +from email.message import EmailMessage +from tabulate import tabulate +import os +import socket +import logging +import logging.config +import sys +import json + +class connection: + def __init__(self,logger): + self.logger = logger + self.records = [] + def __get_list(self): + liste = [] + for e in self.records: + self.logger.debug("interface {} source {} destination {} proto {} dport {} uid {} gid {}".format(e['interface'],e['source'],e['destination'],e['proto'],e['dport'],e['uid'],e['gid'])) + try: + self.logger.debug("--- ask reverse lookup for : {}".format(e['destination'])) + domain, alias, addresslist = socket.gethostbyaddr(e['destination']) + except socket.herror as he: + self.logger.debug("--- can't resolv {}".format(e['destination'])) + domain = 'unknown' + item = [ e['interface'], e['source'], e['destination'], e['proto'], e['dport'], e['uid'], e['gid'] , domain ] + if not item in liste: + liste.append(item) + self.logger.debug(liste) + return liste + def report(self): + headers = { 'Interface':'', 'Source':'', 'Destination':'', 'Protocol':'', 'DestinationPort':'', 'UID':'', 'GID':'' , 'domain':'' } + header = headers.keys() + msg = EmailMessage() + msg.set_content(tabulate(self.__get_list(),headers)) + msg['Subject'] = f'[ssh][attempts] Reporting' + msg['From'] = "{}@{}".format(os.getlogin(),socket.gethostname()) + msg['To'] = "{}@{}".format(os.getlogin(),'192.168.0.238') + print(msg) + #s = smtplib.SMTP('localhost') + #s.send_message(msg) + #s.quit() + def addmessage(self, message:str): + self.logger.debug("-- scan {}".format(message)) + nftop = r'''^OUTPUT:IN= OUT=(?P[a-z0-9]+)[ ]SRC=(?P[0-9.]+)[ ]DST=(?P[0-9.]+)[ ]LEN=([0-9]+)[ ]TOS=([0-9x]+)[ ]PREC=([0-9x]+)[ ]TTL=([0-9]+)[ ]ID=([0-9]+)[ ]DF[ ]PROTO=(?P[CDTUP]+)[ ]SPT=([0-9]+)[ ]DPT=(?P[0-9]+)[ ]WINDOW=([0-9]+)[ ]RES=([0-9x]+)[ ]SYN[ ]URGP=([0-9]+)[ ]UID=(?P[0-9]+)[ ]GID=(?P[0-9]+)[ ]+$''' + nftsp = r'''^SSH:[ ]IN=(?P[a-z0-9]+)[ ]OUT=[ ]MAC=(?P[0-9a-f:]+)[ ]SRC=(?P[0-9.]+)[ ]DST=(?P[0-9.]+)[ ]LEN=([0-9]+)[ ]TOS=([0-9x]+)[ ]PREC=([0-9A-Fx]+)[ ]TTL=([0-9]+)[ ]ID=([0-9]+)[ ]DF[ ]PROTO=(?P[CDTUP]+)[ ]SPT=([0-9]+)[ ]DPT=(?P[0-9]+)[ ]WINDOW=([0-9]+)[ ]RES=([0-9x]+)[ ](SYN |ACK )(PSH |)URGP=(?P[0-9]+)[ ]+$''' + nftom = re.match(re.compile(nftop),message) + nftsm = re.match(re.compile(nftsp),message) + if nftom: + self.logger.debug("$$$ matched: {}".format(nftom)) + self.records.append(nftom.groupdict()) + elif nftsm: + self.logger.debug("$$$ matched: {}".format(nftsm)) + self.records.append(nftsm.groupdict()) + +# initiate +logging.basicConfig(filename='/tmp/outlog_reporting.log',level=logging.DEBUG) +logger=logging.getLogger(__name__) +c = connection(logger) + +# read from dnscap +try: + queries = [] + js = json.load(sys.stdin) + logger.debug("Json : {}".format(js)) + for request in js: + for k,v in request['_source']['layers']['dns']['Queries'].items(): + query = v['dns.qry.name'] + logger.debug("query: {}".format(query)) + queries.append(query) + logger.debug("queries: {}".format(queries)) +except json.decoder.JSONDecodeError as jde: + logger.warning("No json found as input") + +# read logs from kernel journal +j = journal.Reader() +j.seek_realtime(datetime.now() - timedelta(hours=1)) +j.add_match('_TRANSPORT=kernel') +for entry in j: + logger.debug(entry['MESSAGE']) + c.addmessage(entry['MESSAGE']) +logger.debug("--- Generating report") +c.report()