15 Commits

Author SHA1 Message Date
897f498bcd Merge dev into main: resolve conflicts, keep tests out of main
Some checks failed
Release / Auto-tag release (push) Successful in 14s
Release / Build, scan & push cowrie (push) Failing after 6m9s
Release / Build, scan & push docker_api (push) Failing after 31s
Release / Build, scan & push elasticsearch (push) Failing after 30s
Release / Build, scan & push ftp (push) Failing after 30s
Release / Build, scan & push http (push) Failing after 33s
Release / Build, scan & push imap (push) Failing after 30s
Release / Build, scan & push k8s (push) Failing after 30s
Release / Build, scan & push ldap (push) Failing after 33s
Release / Build, scan & push llmnr (push) Failing after 29s
Release / Build, scan & push mongodb (push) Failing after 30s
Release / Build, scan & push mqtt (push) Failing after 30s
Release / Build, scan & push mssql (push) Failing after 30s
Release / Build, scan & push mysql (push) Failing after 30s
Release / Build, scan & push pop3 (push) Failing after 32s
Release / Build, scan & push postgres (push) Failing after 29s
Release / Build, scan & push rdp (push) Failing after 29s
Release / Build, scan & push real_ssh (push) Failing after 31s
Release / Build, scan & push redis (push) Failing after 29s
Release / Build, scan & push sip (push) Failing after 30s
Release / Build, scan & push smb (push) Failing after 32s
Release / Build, scan & push smtp (push) Failing after 31s
Release / Build, scan & push snmp (push) Failing after 29s
Release / Build, scan & push tftp (push) Failing after 29s
Release / Build, scan & push vnc (push) Failing after 30s
2026-04-04 18:00:17 -03:00
ea409650fa Trigger CI: token now has repo:write permission
All checks were successful
CI / Lint (ruff) (push) Successful in 11s
CI / Test (pytest) (3.11) (push) Successful in 18s
CI / Test (pytest) (3.12) (push) Successful in 18s
CI / SAST (bandit) (push) Successful in 11s
CI / Dependency audit (pip-audit) (push) Successful in 19s
CI / Open PR to main (push) Successful in 5s
PR Gate / Lint (ruff) (pull_request) Successful in 10s
PR Gate / Test (pytest) (3.11) (pull_request) Successful in 17s
PR Gate / Test (pytest) (3.12) (pull_request) Successful in 18s
2026-04-04 17:54:37 -03:00
d92aa99b81 Add DEVELOPMENT.md for CI/CD pipeline test
All checks were successful
CI / Lint (ruff) (push) Successful in 11s
CI / Test (pytest) (3.11) (push) Successful in 17s
CI / Test (pytest) (3.12) (push) Successful in 19s
CI / SAST (bandit) (push) Successful in 11s
CI / Dependency audit (pip-audit) (push) Successful in 19s
CI / Open PR to main (push) Successful in 4s
2026-04-04 17:51:51 -03:00
fc7fca998f Add API response logging to open-pr step for debugging
All checks were successful
CI / Lint (ruff) (push) Successful in 10s
CI / Test (pytest) (3.11) (push) Successful in 19s
CI / Test (pytest) (3.12) (push) Successful in 18s
CI / SAST (bandit) (push) Successful in 11s
CI / Dependency audit (pip-audit) (push) Successful in 18s
CI / Open PR to main (push) Successful in 3s
2026-04-04 17:47:43 -03:00
ed749a8c31 Merge security jobs into CI workflow so open-pr needs all checks
All checks were successful
CI / Lint (ruff) (push) Successful in 11s
CI / Test (pytest) (3.11) (push) Successful in 18s
CI / Test (pytest) (3.12) (push) Successful in 19s
CI / SAST (bandit) (push) Successful in 12s
CI / Dependency audit (pip-audit) (push) Successful in 18s
CI / Open PR to main (push) Successful in 4s
2026-04-04 17:43:55 -03:00
cf36ebcd84 Auto-open PR to main when CI passes on dev
Some checks failed
CI / Lint (ruff) (push) Successful in 13s
CI / Test (pytest) (3.11) (push) Successful in 19s
CI / Test (pytest) (3.12) (push) Successful in 20s
Security / SAST (bandit) (push) Successful in 12s
CI / Open PR to main (push) Has been cancelled
Security / Dependency audit (pip-audit) (push) Successful in 18s
2026-04-04 17:42:42 -03:00
6a5c6f098e Remove accidentally committed artifacts and update .gitignore
All checks were successful
CI / Lint (ruff) (push) Successful in 11s
CI / Test (pytest) (3.11) (push) Successful in 18s
CI / Test (pytest) (3.12) (push) Successful in 18s
Security / SAST (bandit) (push) Successful in 12s
Security / Dependency audit (pip-audit) (push) Successful in 19s
2026-04-04 17:36:35 -03:00
988732f4f9 Fix all ruff lint errors across decnet/, templates/, and tests/
Some checks failed
CI / Test (pytest) (3.11) (push) Has been cancelled
CI / Test (pytest) (3.12) (push) Has been cancelled
Security / SAST (bandit) (push) Has been cancelled
Security / Dependency audit (pip-audit) (push) Has been cancelled
CI / Lint (ruff) (push) Has been cancelled
2026-04-04 17:36:16 -03:00
4acfa3f779 Fix pip-audit skipping local editable package
Some checks failed
CI / Lint (ruff) (push) Failing after 10s
CI / Test (pytest) (3.11) (push) Successful in 18s
CI / Test (pytest) (3.12) (push) Successful in 19s
Security / SAST (bandit) (push) Successful in 11s
Security / Dependency audit (pip-audit) (push) Successful in 18s
2026-04-04 17:31:16 -03:00
35c67ec34d Fix registry auto-discovery skipping non-service subclasses (CustomService)
Some checks failed
CI / Lint (ruff) (push) Failing after 11s
CI / Test (pytest) (3.11) (push) Successful in 19s
CI / Test (pytest) (3.12) (push) Successful in 18s
Security / SAST (bandit) (push) Successful in 11s
Security / Dependency audit (pip-audit) (push) Successful in 18s
2026-04-04 17:29:30 -03:00
fe7354554f Add bandit, pip-audit and trivy to CI/CD security pipeline
Some checks failed
CI / Lint (ruff) (push) Failing after 10s
CI / Test (pytest) (3.11) (push) Failing after 39s
CI / Test (pytest) (3.12) (push) Failing after 1m4s
Security / SAST (bandit) (push) Successful in 11s
Security / Dependency audit (pip-audit) (push) Successful in 18s
2026-04-04 17:24:43 -03:00
b3b3597011 Add smoke test: verify all modules import cleanly
Some checks failed
CI / Lint (ruff) (push) Failing after 4s
CI / Test (pytest) (3.11) (push) Failing after 3s
CI / Test (pytest) (3.12) (push) Failing after 4s
2026-04-04 17:18:21 -03:00
92e06cb193 Add release workflow for auto-tagging and Docker image builds
Some checks failed
Release / Auto-tag release (push) Failing after 3s
Release / Build & push cowrie (push) Has been skipped
Release / Build & push docker_api (push) Has been skipped
Release / Build & push elasticsearch (push) Has been skipped
Release / Build & push ftp (push) Has been skipped
Release / Build & push http (push) Has been skipped
Release / Build & push imap (push) Has been skipped
Release / Build & push k8s (push) Has been skipped
Release / Build & push ldap (push) Has been skipped
Release / Build & push llmnr (push) Has been skipped
Release / Build & push mongodb (push) Has been skipped
Release / Build & push mqtt (push) Has been skipped
Release / Build & push mssql (push) Has been skipped
Release / Build & push mysql (push) Has been skipped
Release / Build & push pop3 (push) Has been skipped
Release / Build & push postgres (push) Has been skipped
Release / Build & push rdp (push) Has been skipped
Release / Build & push real_ssh (push) Has been skipped
Release / Build & push redis (push) Has been skipped
Release / Build & push sip (push) Has been skipped
Release / Build & push smb (push) Has been skipped
Release / Build & push smtp (push) Has been skipped
Release / Build & push snmp (push) Has been skipped
Release / Build & push tftp (push) Has been skipped
Release / Build & push vnc (push) Has been skipped
2026-04-04 17:16:53 -03:00
38b1efa8c0 Add Gitea Actions CI/CD workflows and ruff dependency
Some checks failed
CI / Test (pytest) (3.11) (push) Failing after 3s
CI / Test (pytest) (3.12) (push) Failing after 3s
CI / Lint (ruff) (push) Failing after 1m49s
2026-04-04 17:16:45 -03:00
d7a6aeff86 dev: add pytest as core dependency 2026-04-04 16:29:17 -03:00
62 changed files with 402 additions and 208 deletions

86
.gitea/workflows/ci.yml Normal file
View File

@@ -0,0 +1,86 @@
name: CI
on:
push:
branches: [dev, testing]
jobs:
lint:
name: Lint (ruff)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: "3.11"
- run: pip install ruff
- run: ruff check .
test:
name: Test (pytest)
runs-on: ubuntu-latest
strategy:
matrix:
python-version: ["3.11", "3.12"]
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}
- run: pip install -e .
- run: pytest tests/ -v --tb=short
bandit:
name: SAST (bandit)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: "3.11"
- run: pip install bandit
- run: bandit -r decnet/ -ll -x decnet/services/registry.py
pip-audit:
name: Dependency audit (pip-audit)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: "3.11"
- run: pip install pip-audit
- run: pip install -e .
- run: pip-audit --skip-editable
open-pr:
name: Open PR to main
runs-on: ubuntu-latest
needs: [lint, test, bandit, pip-audit]
if: github.ref == 'refs/heads/dev'
steps:
- name: Open PR via Gitea API
run: |
echo "--- Checking for existing open PRs ---"
LIST_RESPONSE=$(curl -s \
-H "Authorization: token ${{ secrets.DECNET_PR_TOKEN }}" \
"https://git.resacachile.cl/api/v1/repos/anti/DECNET/pulls?state=open&head=anti:dev&base=main&limit=5")
echo "$LIST_RESPONSE"
EXISTING=$(echo "$LIST_RESPONSE" | python3 -c "import sys, json; print(len(json.load(sys.stdin)))")
echo "Open PRs found: $EXISTING"
if [ "$EXISTING" -gt "0" ]; then
echo "PR already open, skipping."
exit 0
fi
echo "--- Creating PR ---"
CREATE_RESPONSE=$(curl -s -X POST \
-H "Authorization: token ${{ secrets.DECNET_PR_TOKEN }}" \
-H "Content-Type: application/json" \
-d '{
"title": "Auto PR: dev → main",
"head": "dev",
"base": "main",
"body": "All CI and security checks passed. Review and merge when ready."
}' \
"https://git.resacachile.cl/api/v1/repos/anti/DECNET/pulls")
echo "$CREATE_RESPONSE"

31
.gitea/workflows/pr.yml Normal file
View File

@@ -0,0 +1,31 @@
name: PR Gate
on:
pull_request:
branches: [main]
jobs:
lint:
name: Lint (ruff)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: "3.11"
- run: pip install ruff
- run: ruff check .
test:
name: Test (pytest)
runs-on: ubuntu-latest
strategy:
matrix:
python-version: ["3.11", "3.12"]
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}
- run: pip install -e .
- run: pytest tests/ -v --tb=short

View File

@@ -0,0 +1,116 @@
name: Release
on:
push:
branches: [main]
env:
REGISTRY: git.resacachile.cl
OWNER: anti
jobs:
tag:
name: Auto-tag release
runs-on: ubuntu-latest
outputs:
version: ${{ steps.version.outputs.version }}
tag_created: ${{ steps.tag.outputs.created }}
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Extract version from pyproject.toml
id: version
run: |
VERSION=$(python3 -c "import tomllib; f=open('pyproject.toml','rb'); d=tomllib.load(f); print(d['project']['version'])")
echo "version=$VERSION" >> $GITHUB_OUTPUT
- name: Create tag if not exists
id: tag
run: |
VERSION=${{ steps.version.outputs.version }}
if git rev-parse "v$VERSION" >/dev/null 2>&1; then
echo "Tag v$VERSION already exists, skipping."
echo "created=false" >> $GITHUB_OUTPUT
else
git config user.name "gitea-actions"
git config user.email "actions@git.resacachile.cl"
git tag -a "v$VERSION" -m "Release v$VERSION"
git push origin "v$VERSION"
echo "created=true" >> $GITHUB_OUTPUT
fi
docker:
name: Build, scan & push ${{ matrix.service }}
runs-on: ubuntu-latest
needs: tag
strategy:
fail-fast: false
matrix:
service:
- cowrie
- docker_api
- elasticsearch
- ftp
- http
- imap
- k8s
- ldap
- llmnr
- mongodb
- mqtt
- mssql
- mysql
- pop3
- postgres
- rdp
- redis
- real_ssh
- sip
- smb
- smtp
- snmp
- tftp
- vnc
steps:
- uses: actions/checkout@v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Log in to Gitea container registry
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ secrets.REGISTRY_USER }}
password: ${{ secrets.REGISTRY_TOKEN }}
- name: Build image locally
uses: docker/build-push-action@v5
with:
context: templates/${{ matrix.service }}
load: true
push: false
tags: decnet-${{ matrix.service }}:scan
cache-from: type=gha
cache-to: type=gha,mode=max
- name: Scan with Trivy
uses: aquasecurity/trivy-action@master
with:
image-ref: decnet-${{ matrix.service }}:scan
exit-code: "1"
severity: CRITICAL
ignore-unfixed: true
- name: Push image
if: success()
uses: docker/build-push-action@v5
with:
context: templates/${{ matrix.service }}
push: true
tags: |
${{ env.REGISTRY }}/${{ env.OWNER }}/decnet-${{ matrix.service }}:latest
${{ env.REGISTRY }}/${{ env.OWNER }}/decnet-${{ matrix.service }}:v${{ needs.tag.outputs.version }}
cache-from: type=gha

7
.gitignore vendored
View File

@@ -9,3 +9,10 @@ decnet-compose.yml
decnet-state.json decnet-state.json
*.ini *.ini
.env .env
decnet.log*
*.loggy
*.nmap
linterfails.log
test-scan
webmail
windows1

View File

@@ -54,3 +54,4 @@ DECNET is a honeypot/deception network framework. It deploys fake machines (call
- NEVER pass broken code to the user. - NEVER pass broken code to the user.
- Broken means: not running, not passing 100% tests, etc. - Broken means: not running, not passing 100% tests, etc.
- After tests pass with 100%, always git commit your changes. - After tests pass with 100%, always git commit your changes.
- NEVER add "Co-Authored-By" or any Claude attribution lines to git commit messages.

1
DEVELOPMENT.md Normal file
View File

@@ -0,0 +1 @@
CI/CD TEST 2

View File

@@ -51,3 +51,63 @@ docker network create -d macvlan \
#### Issues #### Issues
This initial test doesn't seem to be working. Might be that I'm using WSL, so I downloaded a Ubuntu 22.04 Server ISO. I'll try the MACVLAN network on it. Now, if that doesn't work, I don't see how the 802.1q would work, at least on _my network_. Perhaps if I had a switch I could make it work, but currently I don't have one :c This initial test doesn't seem to be working. Might be that I'm using WSL, so I downloaded a Ubuntu 22.04 Server ISO. I'll try the MACVLAN network on it. Now, if that doesn't work, I don't see how the 802.1q would work, at least on _my network_. Perhaps if I had a switch I could make it work, but currently I don't have one :c
---
# TODO
## Core / Hardening
- [ ] **Attacker fingerprinting** — Beyond IP logging: capture TLS JA3/JA4 hashes, TCP window sizes, User-Agent strings, SSH client banners, and tool signatures (nmap, masscan, Metasploit, Cobalt Strike). Build attacker profiles across sessions.
- [ ] **Canary tokens** — Embed canary URLs, fake AWS keys, fake API tokens, and honeydocs (PDF/DOCX with phone-home URLs) into decky filesystems. Fire an alert the moment one is used.
- [ ] **Tarpit mode** — Slow down attackers by making services respond extremely slowly (e.g., SSH that takes 60s to reject, HTTP that drip-feeds bytes). Wastes attacker time and resources.
- [ ] **Dynamic decky mutation** — Deckies that change their exposed services or OS fingerprint over time to confuse port-scan caching and appear more "alive."
- [ ] **Credential harvesting DB** — Every username/password attempt across all services lands in a queryable database. Expose via CLI (`decnet creds`) and flag reuse across deckies.
- [ ] **Session recording** — Full session capture for SSH/Telnet (keystroke logs, commands run, files downloaded). Cowrie already does this — surface it better in the CLI and correlation engine.
- [ ] **Payload capture** — Store every file uploaded or command executed by an attacker. Hash and auto-submit to VirusTotal or a local sandbox.
## Detection & Intelligence
- [ ] **Real-time alerting** — Webhook/Slack/Telegram notifications when an attacker hits a decky for the first time, crosses N deckies (lateral movement), or uses a known bad IP.
- [ ] **Threat intel enrichment** — Auto-lookup attacker IPs against AbuseIPDB, Shodan, GreyNoise, and AlienVault OTX. Tag known scanners vs. targeted attackers.
- [ ] **Attack campaign clustering** — Group attacker sessions by tooling signatures, timing patterns, and credential sets. Identify coordinated campaigns hitting multiple deckies.
- [ ] **GeoIP mapping** — Attacker origin on a world map. Correlate with ASN data to identify cloud exit nodes, VPNs, and Tor exits.
- [ ] **TTPs tagging** — Map observed attacker behaviors to MITRE ATT&CK techniques automatically. Tag events in the correlation engine.
- [ ] **Honeypot interaction scoring** — Score attackers on a scale: casual scanner vs. persistent targeted attacker, based on depth of interaction and commands run.
## Dashboard & Visibility
- [ ] **Web dashboard** — Real-time web UI showing live decky status, attacker activity, traversal graphs, and credential stats. Could be a simple FastAPI + HTMX or a full React app.
- [ ] **Pre-built Kibana/Grafana dashboards** — Ship dashboard JSON exports out of the box so ELK/Grafana deployments are plug-and-play.
- [ ] **CLI live feed**`decnet watch` command: tail all decky logs in a unified, colored terminal stream (like `docker-compose logs -f` but prettier).
- [ ] **Traversal graph export** — Export attacker traversal graphs as DOT/Graphviz or JSON for visualization in external tools.
- [ ] **Daily digest** — Automated daily summary email/report: new attackers, top credentials tried, most-hit services.
## Deployment & Infrastructure
- [ ] **SWARM / multihost mode** — Full Ansible-based orchestration for deploying deckies across N real hosts.
- [ ] **Terraform/Pulumi provider** — Spin up cloud-hosted deckies on AWS/GCP/Azure with one command. Useful for internet-facing honeynets.
- [ ] **Auto-scaling** — When attack traffic increases, automatically spawn more deckies to absorb and log more activity.
- [ ] **Kubernetes deployment mode** — Run deckies as Kubernetes pods for environments already running k8s.
- [ ] **Proxmox/libvirt backend** — Full VM-based deckies instead of containers, for even more realistic OS fingerprints and behavior. Docker for speed; VMs for realism.
- [ ] **Raspberry Pi / ARM support** — Low-cost physical honeynets using RPis. Validate ARM image builds.
- [ ] **Decky health monitoring** — Watchdog that auto-restarts crashed deckies and alerts if a service goes dark.
## Services & Realism
- [ ] **HTTPS/TLS support** — HTTP honeypot with a self-signed or Let's Encrypt cert. Many real-world services use HTTPS; plain HTTP stands out.
- [ ] **Fake Active Directory** — A convincing fake AD/LDAP with fake users, groups, and GPOs. Attacker tools like BloodHound should get juicy (fake) data.
- [ ] **Fake file shares** — SMB/NFS shares pre-populated with enticing but fake files: "passwords.xlsx", "vpn_config.ovpn", "backup_keys.tar.gz". All instrumented to detect access.
- [ ] **Realistic web apps** — HTTP honeypot serving convincing fake apps: a fake WordPress, a fake phpMyAdmin, a fake Grafana login — all logging every interaction.
- [ ] **OT/ICS profiles** — Expand Conpot support: Modbus, DNP3, BACnet, EtherNet/IP. Convincing industrial control system decoys.
- [ ] **Printer/IoT archetypes** — Expand existing printer/camera archetypes with actual service emulation (IPP, ONVIF, WS-Discovery).
- [ ] **Service interaction depth** — Some services currently just log the connection. Deepen interaction: fake MySQL that accepts queries and returns realistic fake data, fake Redis that stores and retrieves dummy keys.
## Developer Experience
- [ ] **Plugin SDK docs** — Full documentation and an example plugin for adding custom services. Lower the barrier for community contributions.
- [ ] **Integration tests** — Full deploy/teardown cycle tests against a real Docker daemon (not just unit tests).
- [ ] **Per-service tests** — Each of the 29 service implementations deserves its own test coverage.
- [ ] **CI/CD pipeline** — GitHub/Gitea Actions: run tests on push, lint, build Docker images, publish releases.
- [ ] **Config validation CLI**`decnet validate my.ini` to dry-check an INI config before deploying.
- [ ] **Config generator wizard**`decnet wizard` interactive prompt to generate an INI config without writing one by hand.

View File

@@ -22,7 +22,6 @@ Usage
from __future__ import annotations from __future__ import annotations
import json
from collections import defaultdict from collections import defaultdict
from pathlib import Path from pathlib import Path

View File

@@ -17,7 +17,7 @@ The attacker IP may appear under several field names depending on service:
from __future__ import annotations from __future__ import annotations
import re import re
from dataclasses import dataclass, field from dataclasses import dataclass
from datetime import datetime from datetime import datetime
# RFC 5424 line structure # RFC 5424 line structure

View File

@@ -14,11 +14,8 @@ from decnet.config import DecnetConfig, clear_state, load_state, save_state
from decnet.composer import write_compose from decnet.composer import write_compose
from decnet.network import ( from decnet.network import (
MACVLAN_NETWORK_NAME, MACVLAN_NETWORK_NAME,
allocate_ips,
create_ipvlan_network, create_ipvlan_network,
create_macvlan_network, create_macvlan_network,
detect_interface,
detect_subnet,
get_host_ip, get_host_ip,
ips_to_range, ips_to_range,
remove_macvlan_network, remove_macvlan_network,

View File

@@ -1,4 +1,3 @@
from __future__ import annotations
""" """
Rotating file handler for DECNET syslog output. Rotating file handler for DECNET syslog output.
@@ -7,6 +6,8 @@ Path is controlled by the DECNET_LOG_FILE environment variable
(default: /var/log/decnet/decnet.log). (default: /var/log/decnet/decnet.log).
""" """
from __future__ import annotations
import logging import logging
import logging.handlers import logging.handlers
import os import os

View File

@@ -1,4 +1,3 @@
from __future__ import annotations
""" """
RFC 5424 syslog formatter for DECNET. RFC 5424 syslog formatter for DECNET.
@@ -9,6 +8,8 @@ Facility: local0 (16)
PEN for structured data: decnet@55555 PEN for structured data: decnet@55555
""" """
from __future__ import annotations
from datetime import datetime, timezone from datetime import datetime, timezone
from typing import Any from typing import Any

View File

@@ -8,10 +8,7 @@ Handles:
- IP allocation (sequential, skipping reserved addresses) - IP allocation (sequential, skipping reserved addresses)
""" """
import ipaddress
import os import os
import shutil
import socket
import subprocess import subprocess
from ipaddress import IPv4Address, IPv4Interface, IPv4Network from ipaddress import IPv4Address, IPv4Interface, IPv4Network

View File

@@ -26,6 +26,8 @@ def _load_plugins() -> None:
continue continue
importlib.import_module(f"decnet.services.{module_info.name}") importlib.import_module(f"decnet.services.{module_info.name}")
for cls in BaseService.__subclasses__(): for cls in BaseService.__subclasses__():
if not cls.__module__.startswith("decnet.services."):
continue
instance = cls() instance = cls()
_registry[instance.name] = instance _registry[instance.name] = instance
_loaded = True _loaded = True

View File

@@ -13,6 +13,10 @@ dependencies = [
"docker>=7.0", "docker>=7.0",
"pyyaml>=6.0", "pyyaml>=6.0",
"jinja2>=3.1", "jinja2>=3.1",
"pytest>=8.0",
"ruff>=0.4",
"bandit>=1.7",
"pip-audit>=2.0",
] ]
[project.scripts] [project.scripts]

View File

@@ -1,5 +1,4 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
from __future__ import annotations
""" """
Shared RFC 5424 syslog helper for DECNET service templates. Shared RFC 5424 syslog helper for DECNET service templates.

View File

@@ -1,5 +1,4 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
from __future__ import annotations
""" """
Shared RFC 5424 syslog helper for DECNET service templates. Shared RFC 5424 syslog helper for DECNET service templates.

View File

@@ -8,8 +8,6 @@ but fake data. Logs all requests as JSON.
import json import json
import os import os
import socket
from datetime import datetime, timezone
from flask import Flask, request from flask import Flask, request
from decnet_logging import syslog_line, write_syslog_file, forward_syslog from decnet_logging import syslog_line, write_syslog_file, forward_syslog

View File

@@ -1,5 +1,4 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
from __future__ import annotations
""" """
Shared RFC 5424 syslog helper for DECNET service templates. Shared RFC 5424 syslog helper for DECNET service templates.

View File

@@ -7,8 +7,6 @@ as JSON. Designed to attract automated scanners and credential stuffers.
import json import json
import os import os
import socket
from datetime import datetime, timezone
from http.server import BaseHTTPRequestHandler, HTTPServer from http.server import BaseHTTPRequestHandler, HTTPServer
from decnet_logging import syslog_line, write_syslog_file, forward_syslog from decnet_logging import syslog_line, write_syslog_file, forward_syslog

View File

@@ -1,5 +1,4 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
from __future__ import annotations
""" """
Shared RFC 5424 syslog helper for DECNET service templates. Shared RFC 5424 syslog helper for DECNET service templates.

View File

@@ -5,13 +5,10 @@ Accepts any credentials, logs all commands and file requests,
forwards events as JSON to LOG_TARGET if set. forwards events as JSON to LOG_TARGET if set.
""" """
import json
import os import os
import socket
import sys import sys
from datetime import datetime, timezone
from twisted.internet import defer, protocol, reactor from twisted.internet import defer, reactor
from twisted.protocols.ftp import FTP, FTPFactory from twisted.protocols.ftp import FTP, FTPFactory
from twisted.python import log as twisted_log from twisted.python import log as twisted_log
from decnet_logging import syslog_line, write_syslog_file, forward_syslog from decnet_logging import syslog_line, write_syslog_file, forward_syslog

View File

@@ -1,5 +1,4 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
from __future__ import annotations
""" """
Shared RFC 5424 syslog helper for DECNET service templates. Shared RFC 5424 syslog helper for DECNET service templates.

View File

@@ -7,8 +7,6 @@ and responds with configurable pages. Forwards events as JSON to LOG_TARGET if s
import json import json
import os import os
import socket
from datetime import datetime, timezone
from pathlib import Path from pathlib import Path
from flask import Flask, request, send_from_directory from flask import Flask, request, send_from_directory

View File

@@ -1,5 +1,4 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
from __future__ import annotations
""" """
Shared RFC 5424 syslog helper for DECNET service templates. Shared RFC 5424 syslog helper for DECNET service templates.

View File

@@ -6,10 +6,7 @@ AUTHENTICATE), then returns a NO response. Logs all commands as JSON.
""" """
import asyncio import asyncio
import json
import os import os
import socket
from datetime import datetime, timezone
from decnet_logging import syslog_line, write_syslog_file, forward_syslog from decnet_logging import syslog_line, write_syslog_file, forward_syslog
NODE_NAME = os.environ.get("NODE_NAME", "mailserver") NODE_NAME = os.environ.get("NODE_NAME", "mailserver")

View File

@@ -1,5 +1,4 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
from __future__ import annotations
""" """
Shared RFC 5424 syslog helper for DECNET service templates. Shared RFC 5424 syslog helper for DECNET service templates.

View File

@@ -8,8 +8,6 @@ Responds to recon endpoints (/version, /api, /apis, /api/v1/namespaces,
import json import json
import os import os
import socket
from datetime import datetime, timezone
from flask import Flask, request from flask import Flask, request
from decnet_logging import syslog_line, write_syslog_file, forward_syslog from decnet_logging import syslog_line, write_syslog_file, forward_syslog

View File

@@ -1,5 +1,4 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
from __future__ import annotations
""" """
Shared RFC 5424 syslog helper for DECNET service templates. Shared RFC 5424 syslog helper for DECNET service templates.

View File

@@ -6,10 +6,7 @@ invalidCredentials error. Logs all interactions as JSON.
""" """
import asyncio import asyncio
import json
import os import os
import socket
from datetime import datetime, timezone
from decnet_logging import syslog_line, write_syslog_file, forward_syslog from decnet_logging import syslog_line, write_syslog_file, forward_syslog
NODE_NAME = os.environ.get("NODE_NAME", "ldapserver") NODE_NAME = os.environ.get("NODE_NAME", "ldapserver")

View File

@@ -1,5 +1,4 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
from __future__ import annotations
""" """
Shared RFC 5424 syslog helper for DECNET service templates. Shared RFC 5424 syslog helper for DECNET service templates.

View File

@@ -7,11 +7,8 @@ Logs every packet with source IP and decoded query name where possible.
""" """
import asyncio import asyncio
import json
import os import os
import socket
import struct import struct
from datetime import datetime, timezone
from decnet_logging import syslog_line, write_syslog_file, forward_syslog from decnet_logging import syslog_line, write_syslog_file, forward_syslog
NODE_NAME = os.environ.get("NODE_NAME", "lan-host") NODE_NAME = os.environ.get("NODE_NAME", "lan-host")

View File

@@ -1,5 +1,4 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
from __future__ import annotations
""" """
Shared RFC 5424 syslog helper for DECNET service templates. Shared RFC 5424 syslog helper for DECNET service templates.

View File

@@ -7,11 +7,8 @@ received messages as JSON.
""" """
import asyncio import asyncio
import json
import os import os
import socket
import struct import struct
from datetime import datetime, timezone
from decnet_logging import syslog_line, write_syslog_file, forward_syslog from decnet_logging import syslog_line, write_syslog_file, forward_syslog
NODE_NAME = os.environ.get("NODE_NAME", "mongodb") NODE_NAME = os.environ.get("NODE_NAME", "mongodb")

View File

@@ -1,5 +1,4 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
from __future__ import annotations
""" """
Shared RFC 5424 syslog helper for DECNET service templates. Shared RFC 5424 syslog helper for DECNET service templates.

View File

@@ -7,11 +7,8 @@ interactions as JSON.
""" """
import asyncio import asyncio
import json
import os import os
import socket
import struct import struct
from datetime import datetime, timezone
from decnet_logging import syslog_line, write_syslog_file, forward_syslog from decnet_logging import syslog_line, write_syslog_file, forward_syslog
NODE_NAME = os.environ.get("NODE_NAME", "mqtt-broker") NODE_NAME = os.environ.get("NODE_NAME", "mqtt-broker")
@@ -48,11 +45,13 @@ def _parse_connect(payload: bytes):
# Protocol level (1 byte) # Protocol level (1 byte)
if pos >= len(payload): if pos >= len(payload):
return {}, pos return {}, pos
_proto_level = payload[pos]; pos += 1 _proto_level = payload[pos]
pos += 1
# Connect flags (1 byte) # Connect flags (1 byte)
if pos >= len(payload): if pos >= len(payload):
return {}, pos return {}, pos
flags = payload[pos]; pos += 1 flags = payload[pos]
pos += 1
# Keep alive (2 bytes) # Keep alive (2 bytes)
pos += 2 pos += 2
# Client ID # Client ID

View File

@@ -1,5 +1,4 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
from __future__ import annotations
""" """
Shared RFC 5424 syslog helper for DECNET service templates. Shared RFC 5424 syslog helper for DECNET service templates.

View File

@@ -6,11 +6,8 @@ a login failed error. Logs auth attempts as JSON.
""" """
import asyncio import asyncio
import json
import os import os
import socket
import struct import struct
from datetime import datetime, timezone
from decnet_logging import syslog_line, write_syslog_file, forward_syslog from decnet_logging import syslog_line, write_syslog_file, forward_syslog
NODE_NAME = os.environ.get("NODE_NAME", "dbserver") NODE_NAME = os.environ.get("NODE_NAME", "dbserver")

View File

@@ -1,5 +1,4 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
from __future__ import annotations
""" """
Shared RFC 5424 syslog helper for DECNET service templates. Shared RFC 5424 syslog helper for DECNET service templates.

View File

@@ -7,11 +7,8 @@ attempts as JSON.
""" """
import asyncio import asyncio
import json
import os import os
import socket
import struct import struct
from datetime import datetime, timezone
from decnet_logging import syslog_line, write_syslog_file, forward_syslog from decnet_logging import syslog_line, write_syslog_file, forward_syslog
NODE_NAME = os.environ.get("NODE_NAME", "dbserver") NODE_NAME = os.environ.get("NODE_NAME", "dbserver")

View File

@@ -1,5 +1,4 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
from __future__ import annotations
""" """
Shared RFC 5424 syslog helper for DECNET service templates. Shared RFC 5424 syslog helper for DECNET service templates.

View File

@@ -7,10 +7,7 @@ to LOG_TARGET if set.
""" """
import asyncio import asyncio
import json
import os import os
import socket
from datetime import datetime, timezone
from decnet_logging import syslog_line, write_syslog_file, forward_syslog from decnet_logging import syslog_line, write_syslog_file, forward_syslog
NODE_NAME = os.environ.get("NODE_NAME", "mailserver") NODE_NAME = os.environ.get("NODE_NAME", "mailserver")

View File

@@ -1,5 +1,4 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
from __future__ import annotations
""" """
Shared RFC 5424 syslog helper for DECNET service templates. Shared RFC 5424 syslog helper for DECNET service templates.

View File

@@ -7,11 +7,8 @@ returns an error. Logs all interactions as JSON.
""" """
import asyncio import asyncio
import json
import os import os
import socket
import struct import struct
from datetime import datetime, timezone
from decnet_logging import syslog_line, write_syslog_file, forward_syslog from decnet_logging import syslog_line, write_syslog_file, forward_syslog
NODE_NAME = os.environ.get("NODE_NAME", "pgserver") NODE_NAME = os.environ.get("NODE_NAME", "pgserver")

View File

@@ -1,5 +1,4 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
from __future__ import annotations
""" """
Shared RFC 5424 syslog helper for DECNET service templates. Shared RFC 5424 syslog helper for DECNET service templates.

View File

@@ -6,11 +6,8 @@ in the initial RDP negotiation request. Forwards events as JSON to
LOG_TARGET if set. LOG_TARGET if set.
""" """
import json
import os import os
import socket
import sys import sys
from datetime import datetime, timezone
from twisted.internet import protocol, reactor from twisted.internet import protocol, reactor
from twisted.python import log as twisted_log from twisted.python import log as twisted_log

View File

@@ -1,5 +1,4 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
from __future__ import annotations
""" """
Shared RFC 5424 syslog helper for DECNET service templates. Shared RFC 5424 syslog helper for DECNET service templates.

View File

@@ -6,10 +6,7 @@ KEYS, and arbitrary commands. Logs every command and argument as JSON.
""" """
import asyncio import asyncio
import json
import os import os
import socket
from datetime import datetime, timezone
from decnet_logging import syslog_line, write_syslog_file, forward_syslog from decnet_logging import syslog_line, write_syslog_file, forward_syslog
NODE_NAME = os.environ.get("NODE_NAME", "cache-server") NODE_NAME = os.environ.get("NODE_NAME", "cache-server")

View File

@@ -1,5 +1,4 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
from __future__ import annotations
""" """
Shared RFC 5424 syslog helper for DECNET service templates. Shared RFC 5424 syslog helper for DECNET service templates.

View File

@@ -6,11 +6,8 @@ Authorization header and call metadata, then responds with 401 Unauthorized.
""" """
import asyncio import asyncio
import json
import os import os
import re import re
import socket
from datetime import datetime, timezone
from decnet_logging import syslog_line, write_syslog_file, forward_syslog from decnet_logging import syslog_line, write_syslog_file, forward_syslog
NODE_NAME = os.environ.get("NODE_NAME", "pbx") NODE_NAME = os.environ.get("NODE_NAME", "pbx")

View File

@@ -1,5 +1,4 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
from __future__ import annotations
""" """
Shared RFC 5424 syslog helper for DECNET service templates. Shared RFC 5424 syslog helper for DECNET service templates.

View File

@@ -4,10 +4,7 @@ Minimal SMB server using Impacket's SimpleSMBServer.
Logs all connection attempts, optionally forwarding them as JSON to LOG_TARGET. Logs all connection attempts, optionally forwarding them as JSON to LOG_TARGET.
""" """
import json
import os import os
import socket
from datetime import datetime, timezone
from impacket import smbserver from impacket import smbserver
from decnet_logging import syslog_line, write_syslog_file, forward_syslog from decnet_logging import syslog_line, write_syslog_file, forward_syslog

View File

@@ -1,5 +1,4 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
from __future__ import annotations
""" """
Shared RFC 5424 syslog helper for DECNET service templates. Shared RFC 5424 syslog helper for DECNET service templates.

View File

@@ -5,10 +5,7 @@ Logs EHLO/AUTH/MAIL FROM/RCPT TO attempts as JSON, then denies auth.
""" """
import asyncio import asyncio
import json
import os import os
import socket
from datetime import datetime, timezone
from decnet_logging import syslog_line, write_syslog_file, forward_syslog from decnet_logging import syslog_line, write_syslog_file, forward_syslog
NODE_NAME = os.environ.get("NODE_NAME", "mailserver") NODE_NAME = os.environ.get("NODE_NAME", "mailserver")

View File

@@ -1,5 +1,4 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
from __future__ import annotations
""" """
Shared RFC 5424 syslog helper for DECNET service templates. Shared RFC 5424 syslog helper for DECNET service templates.

View File

@@ -7,11 +7,8 @@ Logs all requests as JSON.
""" """
import asyncio import asyncio
import json
import os import os
import socket
import struct import struct
from datetime import datetime, timezone
from decnet_logging import syslog_line, write_syslog_file, forward_syslog from decnet_logging import syslog_line, write_syslog_file, forward_syslog
NODE_NAME = os.environ.get("NODE_NAME", "switch") NODE_NAME = os.environ.get("NODE_NAME", "switch")
@@ -94,35 +91,46 @@ def _ber_tlv(tag: int, value: bytes) -> bytes:
def _parse_snmp(data: bytes): def _parse_snmp(data: bytes):
"""Return (version, community, request_id, oids) or raise.""" """Return (version, community, request_id, oids) or raise."""
pos = 0 pos = 0
assert data[pos] == 0x30; pos += 1 assert data[pos] == 0x30
pos += 1
_, pos = _read_ber_length(data, pos) _, pos = _read_ber_length(data, pos)
# version # version
assert data[pos] == 0x02; pos += 1 assert data[pos] == 0x02
pos += 1
v_len, pos = _read_ber_length(data, pos) v_len, pos = _read_ber_length(data, pos)
version = int.from_bytes(data[pos:pos + v_len], "big"); pos += v_len version = int.from_bytes(data[pos:pos + v_len], "big")
pos += v_len
# community # community
assert data[pos] == 0x04; pos += 1 assert data[pos] == 0x04
pos += 1
c_len, pos = _read_ber_length(data, pos) c_len, pos = _read_ber_length(data, pos)
community = data[pos:pos + c_len].decode(errors="replace"); pos += c_len community = data[pos:pos + c_len].decode(errors="replace")
pos += c_len
# PDU type (0xa0 = GetRequest, 0xa1 = GetNextRequest) # PDU type (0xa0 = GetRequest, 0xa1 = GetNextRequest)
pdu_type = data[pos]; pos += 1 pos += 1
_, pos = _read_ber_length(data, pos) _, pos = _read_ber_length(data, pos)
# request-id # request-id
assert data[pos] == 0x02; pos += 1 assert data[pos] == 0x02
pos += 1
r_len, pos = _read_ber_length(data, pos) r_len, pos = _read_ber_length(data, pos)
request_id = int.from_bytes(data[pos:pos + r_len], "big"); pos += r_len request_id = int.from_bytes(data[pos:pos + r_len], "big")
pos += r_len
pos += 4 # skip error-status and error-index pos += 4 # skip error-status and error-index
# varbind list # varbind list
assert data[pos] == 0x30; pos += 1 assert data[pos] == 0x30
pos += 1
vbl_len, pos = _read_ber_length(data, pos) vbl_len, pos = _read_ber_length(data, pos)
end = pos + vbl_len end = pos + vbl_len
oids = [] oids = []
while pos < end: while pos < end:
assert data[pos] == 0x30; pos += 1 assert data[pos] == 0x30
pos += 1
vb_len, pos = _read_ber_length(data, pos) vb_len, pos = _read_ber_length(data, pos)
assert data[pos] == 0x06; pos += 1 assert data[pos] == 0x06
pos += 1
oid_len, pos = _read_ber_length(data, pos) oid_len, pos = _read_ber_length(data, pos)
oid = _decode_oid(data[pos:pos + oid_len]); pos += oid_len oid = _decode_oid(data[pos:pos + oid_len])
pos += oid_len
oids.append(oid) oids.append(oid)
pos += vb_len - oid_len - 2 # skip value pos += vb_len - oid_len - 2 # skip value
return version, community, request_id, oids return version, community, request_id, oids

View File

@@ -1,5 +1,4 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
from __future__ import annotations
""" """
Shared RFC 5424 syslog helper for DECNET service templates. Shared RFC 5424 syslog helper for DECNET service templates.

View File

@@ -6,11 +6,8 @@ then responds with an error packet. Logs all requests as JSON.
""" """
import asyncio import asyncio
import json
import os import os
import socket
import struct import struct
from datetime import datetime, timezone
from decnet_logging import syslog_line, write_syslog_file, forward_syslog from decnet_logging import syslog_line, write_syslog_file, forward_syslog
NODE_NAME = os.environ.get("NODE_NAME", "tftpserver") NODE_NAME = os.environ.get("NODE_NAME", "tftpserver")

View File

@@ -1,5 +1,4 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
from __future__ import annotations
""" """
Shared RFC 5424 syslog helper for DECNET service templates. Shared RFC 5424 syslog helper for DECNET service templates.

View File

@@ -7,10 +7,7 @@ failed". Logs the raw response for offline cracking.
""" """
import asyncio import asyncio
import json
import os import os
import socket
from datetime import datetime, timezone
from decnet_logging import syslog_line, write_syslog_file, forward_syslog from decnet_logging import syslog_line, write_syslog_file, forward_syslog
NODE_NAME = os.environ.get("NODE_NAME", "desktop") NODE_NAME = os.environ.get("NODE_NAME", "desktop")

View File

@@ -1,98 +0,0 @@
# Nmap 7.92 scan initiated Sat Apr 4 04:41:05 2026 as: nmap -sS -sV -O -A -oN test-scan 192.168.1.110-119
Nmap scan report for 192.168.1.110
Host is up (0.000035s latency).
Not shown: 996 closed tcp ports (reset)
PORT STATE SERVICE VERSION
25/tcp open smtp Postfix smtpd
|_smtp-commands: decky-webmail, PIPELINING, SIZE 10240000, VRFY, ETRN, AUTH PLAIN LOGIN, ENHANCEDSTATUSCODES, 8BITMIME, DSN
80/tcp open http Apache httpd 2.4.54 ((Debian))
|_http-title: WordPress &rsaquo; Error
|_http-server-header: Werkzeug/3.1.8 Python/3.11.2
110/tcp open pop3
| fingerprint-strings:
| GenericLines, HTTPOptions:
| +OK decky-webmail POP3 server ready
| -ERR Unknown command
| -ERR Unknown command
| NULL:
|_ +OK decky-webmail POP3 server ready
|_pop3-capabilities: USER
143/tcp open imap
| fingerprint-strings:
| GenericLines, NULL:
| * OK [decky-webmail] IMAP4rev1 Service Ready
| GetRequest:
| * OK [decky-webmail] IMAP4rev1 Service Ready
|_ Command not recognized
|_imap-capabilities: OK CAPABILITY AUTH=LOGINA0001 IMAP4rev1 completed AUTH=PLAIN
2 services unrecognized despite returning data. If you know the service/version, please submit the following fingerprints at https://nmap.org/cgi-bin/submit.cgi?new-service :
==============NEXT SERVICE FINGERPRINT (SUBMIT INDIVIDUALLY)==============
SF-Port110-TCP:V=7.92%I=7%D=4/4%Time=69D0C099%P=x86_64-redhat-linux-gnu%r(
SF:NULL,25,"\+OK\x20decky-webmail\x20POP3\x20server\x20ready\r\n")%r(Gener
SF:icLines,51,"\+OK\x20decky-webmail\x20POP3\x20server\x20ready\r\n-ERR\x2
SF:0Unknown\x20command\r\n-ERR\x20Unknown\x20command\r\n")%r(HTTPOptions,5
SF:1,"\+OK\x20decky-webmail\x20POP3\x20server\x20ready\r\n-ERR\x20Unknown\
SF:x20command\r\n-ERR\x20Unknown\x20command\r\n");
==============NEXT SERVICE FINGERPRINT (SUBMIT INDIVIDUALLY)==============
SF-Port143-TCP:V=7.92%I=7%D=4/4%Time=69D0C099%P=x86_64-redhat-linux-gnu%r(
SF:NULL,2E,"\*\x20OK\x20\[decky-webmail\]\x20IMAP4rev1\x20Service\x20Ready
SF:\r\n")%r(GetRequest,4E,"\*\x20OK\x20\[decky-webmail\]\x20IMAP4rev1\x20S
SF:ervice\x20Ready\r\nGET\x20BAD\x20Command\x20not\x20recognized\r\n")%r(G
SF:enericLines,2E,"\*\x20OK\x20\[decky-webmail\]\x20IMAP4rev1\x20Service\x
SF:20Ready\r\n");
MAC Address: D2:55:C7:0D:B4:FC (Unknown)
Device type: general purpose
Running: Linux 5.X
OS CPE: cpe:/o:linux:linux_kernel:5
OS details: Linux 5.3 - 5.4
Network Distance: 1 hop
Service Info: Host: decky-webmail
TRACEROUTE
HOP RTT ADDRESS
1 0.04 ms 192.168.1.110
Nmap scan report for 192.168.1.111
Host is up (0.000016s latency).
Not shown: 998 closed tcp ports (reset)
PORT STATE SERVICE VERSION
21/tcp open ftp vsftpd (before 2.0.8) or WU-FTPD
445/tcp open microsoft-ds
| fingerprint-strings:
| SMBProgNeg:
| SMBr
|_ "3DUfw
1 service unrecognized despite returning data. If you know the service/version, please submit the following fingerprint at https://nmap.org/cgi-bin/submit.cgi?new-service :
SF-Port445-TCP:V=7.92%I=7%D=4/4%Time=69D0C09E%P=x86_64-redhat-linux-gnu%r(
SF:SMBProgNeg,51,"\0\0\0M\xffSMBr\0\0\0\0\x80\0\xc0\0\0\0\0\0\0\0\0\0\0\0\
SF:0\0\0@\x06\0\0\x01\0\x11\x07\0\x03\x01\0\x01\0\0\xfa\0\0\0\0\x01\0\0\0\
SF:0\0p\0\0\0\0\0\0\0\0\0\0\0\0\0\x08\x08\0\x11\"3DUfw\x88");
MAC Address: 92:44:B7:6C:F6:D0 (Unknown)
Device type: general purpose
Running: Linux 5.X
OS CPE: cpe:/o:linux:linux_kernel:5
OS details: Linux 5.3 - 5.4
Network Distance: 1 hop
Service Info: Host: Twisted
Host script results:
| smb-security-mode:
| account_used: guest
| authentication_level: user
| challenge_response: supported
|_ message_signing: disabled (dangerous, but default)
| smb2-time:
| date: 2026-04-04T07:41:24
|_ start_date: 2026-04-04T07:41:24
| smb2-security-mode:
| 2.0.2:
|_ Message signing enabled but not required
|_ms-sql-info: ERROR: Script execution failed (use -d to debug)
|_clock-skew: mean: -77660d15h50m42s, deviation: 109828d18h12m51s, median: -155321d07h41m24s
TRACEROUTE
HOP RTT ADDRESS
1 0.02 ms 192.168.1.111
OS and Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
# Nmap done at Sat Apr 4 04:41:33 2026 -- 10 IP addresses (2 hosts up) scanned in 28.27 seconds

61
tests/test_build.py Normal file
View File

@@ -0,0 +1,61 @@
"""Smoke test: verify the package and all submodules import cleanly."""
import importlib
import pytest
MODULES = [
"decnet",
"decnet.cli",
"decnet.config",
"decnet.composer",
"decnet.deployer",
"decnet.network",
"decnet.archetypes",
"decnet.distros",
"decnet.os_fingerprint",
"decnet.ini_loader",
"decnet.custom_service",
"decnet.correlation",
"decnet.correlation.engine",
"decnet.correlation.graph",
"decnet.correlation.parser",
"decnet.logging",
"decnet.logging.file_handler",
"decnet.logging.forwarder",
"decnet.logging.syslog_formatter",
"decnet.services",
"decnet.services.registry",
"decnet.services.base",
"decnet.services.ssh",
"decnet.services.ftp",
"decnet.services.http",
"decnet.services.smb",
"decnet.services.rdp",
"decnet.services.smtp",
"decnet.services.mysql",
"decnet.services.postgres",
"decnet.services.redis",
"decnet.services.mongodb",
"decnet.services.mssql",
"decnet.services.elasticsearch",
"decnet.services.ldap",
"decnet.services.k8s",
"decnet.services.docker_api",
"decnet.services.vnc",
"decnet.services.telnet",
"decnet.services.tftp",
"decnet.services.snmp",
"decnet.services.sip",
"decnet.services.mqtt",
"decnet.services.llmnr",
"decnet.services.imap",
"decnet.services.pop3",
"decnet.services.conpot",
"decnet.services.real_ssh",
"decnet.services.registry",
]
@pytest.mark.parametrize("module", MODULES)
def test_module_imports(module):
importlib.import_module(module)