49 Commits

Author SHA1 Message Date
overcuriousity
c4e6a8998a iteration on ws implementation 2025-09-20 16:52:05 +02:00
overcuriousity
75a595c9cb try to implement websockets 2025-09-20 14:17:17 +02:00
3ee23c9d05 Merge pull request 'remove-large-entity-temporarily' (#3) from remove-large-entity-temporarily into main
Reviewed-on: mstoeck3/dnsrecon#3
2025-09-19 12:29:26 +00:00
overcuriousity
8d402ab4b1 postgres 2025-09-19 14:28:37 +02:00
overcuriousity
7472e6f416 fixes to hint for incomplete data 2025-09-19 12:35:28 +02:00
overcuriousity
eabb532557 almost fixed 2025-09-19 01:10:07 +02:00
overcuriousity
0a6d12de9a large entity recreation 2025-09-19 00:38:26 +02:00
overcuriousity
332805709d remove 2025-09-18 23:44:24 +02:00
overcuriousity
1558731c1c attempt fix large entity 2025-09-18 23:22:49 +02:00
overcuriousity
95cebbf935 bug fixes, improvements 2025-09-18 22:39:12 +02:00
overcuriousity
4c48917993 fixes for scheduler 2025-09-18 21:32:26 +02:00
overcuriousity
9d9afa6a08 fixes 2025-09-18 21:04:29 +02:00
overcuriousity
12f834bb65 correlation engine 2025-09-18 20:51:13 +02:00
overcuriousity
cbfd40ee98 adjustments to shodan & export manager 2025-09-18 19:22:58 +02:00
overcuriousity
d4081e1a32 export manager modularized 2025-09-18 17:42:39 +02:00
overcuriousity
15227b392d readme file & some ux improvements 2025-09-18 00:24:35 +02:00
overcuriousity
fdc26dcf15 executive summary 2025-09-18 00:13:37 +02:00
140ef54674 Merge pull request 'data-model' (#2) from data-model into main
Reviewed-on: mstoeck3/dnsrecon#2
2025-09-17 21:56:17 +00:00
overcuriousity
aae459446c update requirements, fix some bugs 2025-09-17 23:55:41 +02:00
overcuriousity
98e1b2280b new node types 2025-09-17 22:42:08 +02:00
overcuriousity
cd14198452 smaller css 2025-09-17 22:39:26 +02:00
overcuriousity
284660ab8c new node types 2025-09-17 22:09:39 +02:00
overcuriousity
ecfb27e02a new scheduling, removed many debug prints 2025-09-17 21:47:03 +02:00
overcuriousity
39b4242200 fix cli last task started 2025-09-17 21:35:54 +02:00
overcuriousity
a56755320c initial targets managed in backend 2025-09-17 21:29:18 +02:00
overcuriousity
b985f1e5f0 potential bugfix for the right click hiding 2025-09-17 21:15:52 +02:00
overcuriousity
8ae4fdbf80 UX improvements 2025-09-17 21:12:11 +02:00
overcuriousity
d0ee415f0d enhancements 2025-09-17 19:42:14 +02:00
overcuriousity
173c3dcf92 some adjustments for clarity 2025-09-17 17:10:11 +02:00
overcuriousity
ec755b17ad remove many unnecessary debug print, improve large entity handling 2025-09-17 13:31:35 +02:00
overcuriousity
469c133f1b fix session handling 2025-09-17 11:18:06 +02:00
overcuriousity
f775c61731 iterating on fixes 2025-09-17 11:08:50 +02:00
overcuriousity
b984189e08 scheduler fixes 2025-09-17 00:31:12 +02:00
overcuriousity
f2db739fa1 attempt to fix some logic 2025-09-17 00:05:48 +02:00
overcuriousity
47ce7ff883 format keys reduction 2025-09-16 23:17:23 +02:00
overcuriousity
229746e1ec improving the display 2025-09-16 22:25:46 +02:00
overcuriousity
733e1da640 new data model refinement 2025-09-16 21:23:02 +02:00
overcuriousity
97aa18f788 implement new data api 2025-09-16 20:21:08 +02:00
overcuriousity
15421dd4a5 update caching logic 2025-09-16 15:36:29 +02:00
overcuriousity
ad4086b156 fix root computation 2025-09-16 15:25:39 +02:00
overcuriousity
0e92ec6e9a readme 2025-09-16 01:00:21 +02:00
overcuriousity
baa57bfac2 update the shodan to use only ip 2025-09-16 00:57:24 +02:00
overcuriousity
f0f80be955 finalize pop-out 2025-09-16 00:32:46 +02:00
overcuriousity
ecc143ddbb extraction feature works 2025-09-16 00:08:27 +02:00
overcuriousity
2c48316477 extract from node feature 2025-09-16 00:01:24 +02:00
overcuriousity
fc098aed28 remove cache 2025-09-15 22:48:49 +02:00
9285226cbc Merge pull request 'new-scheduler' (#1) from new-scheduler into main
Reviewed-on: mstoeck3/dnsrecon#1
2025-09-15 20:45:47 +00:00
overcuriousity
350055fcec successfully implemented scheduler 2025-09-15 22:44:38 +02:00
overcuriousity
4a5ecf7a37 new highest-priority-first scheduler 2025-09-15 22:21:17 +02:00
110 changed files with 6975 additions and 5454 deletions

View File

@@ -25,10 +25,10 @@ DEFAULT_RECURSION_DEPTH=2
# Default timeout for provider API requests in seconds. # Default timeout for provider API requests in seconds.
DEFAULT_TIMEOUT=30 DEFAULT_TIMEOUT=30
# The number of concurrent provider requests to make. # The number of concurrent provider requests to make.
MAX_CONCURRENT_REQUESTS=5 MAX_CONCURRENT_REQUESTS=1
# The number of results from a provider that triggers the "large entity" grouping. # The number of results from a provider that triggers the "large entity" grouping.
LARGE_ENTITY_THRESHOLD=100 LARGE_ENTITY_THRESHOLD=100
# The number of times to retry a target if a provider fails. # The number of times to retry a target if a provider fails.
MAX_RETRIES_PER_TARGET=8 MAX_RETRIES_PER_TARGET=8
# How long cached provider responses are stored (in hours). # How long cached provider responses are stored (in hours).
CACHE_EXPIRY_HOURS=12 CACHE_TIMEOUT_HOURS=12

1
.gitignore vendored
View File

@@ -169,3 +169,4 @@ cython_debug/
#.idea/ #.idea/
dump.rdb dump.rdb
cache/

307
README.md
View File

@@ -1,36 +1,66 @@
# DNSRecon - Passive Infrastructure Reconnaissance Tool # DNSRecon - Passive Infrastructure Reconnaissance Tool
DNSRecon is an interactive, passive reconnaissance tool designed to map adversary infrastructure. It operates on a "free-by-default" model, ensuring core functionality without subscriptions, while allowing power users to enhance its capabilities with paid API keys. DNSRecon is an interactive, passive reconnaissance tool designed to map adversary infrastructure. It operates on a "free-by-default" model, ensuring core functionality without subscriptions, while allowing power users to enhance its capabilities with paid API keys. It is aimed at cybersecurity researchers, pentesters, and administrators who want to understand the public footprint of a target domain.
**Current Status: Phase 2 Implementation** **Repo Link:** [https://git.cc24.dev/mstoeck3/dnsrecon](https://git.cc24.dev/mstoeck3/dnsrecon)
- ✅ Core infrastructure and graph engine -----
- ✅ Multi-provider support (crt.sh, DNS, Shodan)
- ✅ Session-based multi-user support ## Concept and Philosophy
- ✅ Real-time web interface with interactive visualization
- ✅ Forensic logging system and JSON export The core philosophy of DNSRecon is to provide a comprehensive and accurate map of a target's infrastructure using only **passive data sources** by default. This means that, out of the box, DNSRecon will not send any traffic to the target's servers. Instead, it queries public and historical data sources to build a picture of the target's online presence. This approach is ideal for researchers and pentesters who want to gather intelligence without alerting the target, and for administrators who want to see what information about their own infrastructure is publicly available.
For power users who require more in-depth information, DNSRecon can be configured to use API keys for services like Shodan, which provides a wealth of information about internet-connected devices. However, this is an optional feature, and the core functionality of the tool will always remain free and passive.
-----
## Features ## Features
- **Passive Reconnaissance**: Gathers data without direct contact with target infrastructure. * **Passive Reconnaissance**: Gathers data without direct contact with target infrastructure.
- **In-Memory Graph Analysis**: Uses NetworkX for efficient relationship mapping. * **In-Memory Graph Analysis**: Uses NetworkX for efficient relationship mapping.
- **Real-Time Visualization**: The graph updates dynamically as the scan progresses. * **Real-Time Visualization**: The graph updates dynamically as the scan progresses.
- **Forensic Logging**: A complete audit trail of all reconnaissance activities is maintained. * **Forensic Logging**: A complete audit trail of all reconnaissance activities is maintained.
- **Confidence Scoring**: Relationships are weighted based on the reliability of the data source. * **Confidence Scoring**: Relationships are weighted based on the reliability of the data source.
- **Session Management**: Supports concurrent user sessions with isolated scanner instances. * **Session Management**: Supports concurrent user sessions with isolated scanner instances.
* **Extensible Provider Architecture**: Easily add new data sources to expand the tool's capabilities.
* **Web-Based UI**: An intuitive and interactive web interface for managing scans and visualizing results.
## Installation -----
## Technical Architecture
DNSRecon is a web-based application built with a modern technology stack:
* **Backend**: The backend is a **Flask** application that provides a REST API for the frontend and manages the scanning process.
* **Scanning Engine**: The core scanning engine is a multi-threaded Python application that uses a provider-based architecture to query different data sources.
* **Session Management**: **Redis** is used for session management, allowing for concurrent user sessions with isolated scanner instances.
* **Data Storage**: The application uses an in-memory graph to store and analyze the relationships between different pieces of information. The graph is built using the **NetworkX** library.
* **Frontend**: The frontend is a single-page application that uses JavaScript to interact with the backend API and visualize the graph.
-----
## Data Sources
DNSRecon queries the following data sources:
* **DNS**: Standard DNS lookups (A, AAAA, CNAME, MX, NS, SOA, TXT).
* **crt.sh**: A certificate transparency log that provides information about SSL/TLS certificates.
* **Shodan**: A search engine for internet-connected devices (requires an API key).
-----
## Installation and Setup
### Prerequisites ### Prerequisites
- Python 3.8 or higher * Python 3.8 or higher
- A modern web browser with JavaScript enabled * A modern web browser with JavaScript enabled
- (Recommended) A Linux host for running the application and the optional DNS cache. * A Linux host for running the application
### 1\. Clone the Project ### 1\. Clone the Project
```bash ```bash
git clone https://github.com/your-repo/dnsrecon.git git clone https://git.cc24.dev/mstoeck3/dnsrecon
cd dnsrecon cd dnsrecon
``` ```
@@ -44,156 +74,64 @@ source venv/bin/activate
pip install -r requirements.txt pip install -r requirements.txt
``` ```
### 3\. (Optional but Recommended) Set up a Local DNS Caching Resolver The `requirements.txt` file contains the following dependencies:
Running a local DNS caching resolver can significantly speed up DNS queries and reduce your network footprint. Heres how to set up `unbound` on a Debian-based Linux distribution (like Ubuntu). * Flask
* networkx
* requests
* python-dateutil
* Werkzeug
* urllib3
* dnspython
* gunicorn
* redis
* python-dotenv
**a. Install Unbound:** ### 3\. Configure the Application
DNSRecon is configured using a `.env` file. You can copy the provided example file and edit it to suit your needs:
```bash ```bash
sudo apt update cp .env.example .env
sudo apt install unbound -y
``` ```
**b. Configure Unbound:** The following environment variables are available for configuration:
Create a new configuration file for DNSRecon:
```bash | Variable | Description | Default |
sudo nano /etc/unbound/unbound.conf.d/dnsrecon.conf | :--- | :--- | :--- |
``` | `SHODAN_API_KEY` | Your Shodan API key. | |
| `FLASK_SECRET_KEY`| A strong, random secret key for session security. | `your-very-secret-and-random-key-here` |
| `FLASK_HOST` | The host address for the Flask application. | `127.0.0.1` |
| `FLASK_PORT` | The port for the Flask application. | `5000` |
| `FLASK_DEBUG` | Enable or disable Flask's debug mode. | `True` |
| `FLASK_PERMANENT_SESSION_LIFETIME_HOURS`| How long a user's session in the browser lasts (in hours). | `2` |
| `SESSION_TIMEOUT_MINUTES` | How long inactive scanner data is stored in Redis (in minutes). | `60` |
| `DEFAULT_RECURSION_DEPTH` | The default number of levels to recurse when scanning. | `2` |
| `DEFAULT_TIMEOUT` | Default timeout for provider API requests in seconds. | `30` |
| `MAX_CONCURRENT_REQUESTS`| The number of concurrent provider requests to make. | `5` |
| `LARGE_ENTITY_THRESHOLD`| The number of results from a provider that triggers the "large entity" grouping. | `100` |
| `MAX_RETRIES_PER_TARGET`| The number of times to retry a target if a provider fails. | `8` |
| `CACHE_EXPIRY_HOURS`| How long cached provider responses are stored (in hours). | `12` |
Add the following content to the file: -----
``` ## Running the Application
server:
# Listen on localhost for all users
interface: 127.0.0.1
access-control: 0.0.0.0/0 refuse
access-control: 127.0.0.0/8 allow
# Enable prefetching of popular items For development, you can run the application using the following command:
prefetch: yes
```
**c. Restart Unbound and set it as the default resolver:**
```bash
sudo systemctl restart unbound
sudo systemctl enable unbound
```
To use this resolver for your system, you may need to update your network settings to point to `127.0.0.1` as your DNS server.
**d. Update DNSProvider to use the local resolver:**
In `dnsrecon/providers/dns_provider.py`, you can explicitly set the resolver's nameservers in the `__init__` method:
```python
# dnsrecon/providers/dns_provider.py
class DNSProvider(BaseProvider):
def __init__(self, session_config=None):
"""Initialize DNS provider with session-specific configuration."""
super().__init__(...)
# Configure DNS resolver
self.resolver = dns.resolver.Resolver()
self.resolver.nameservers = ['127.0.0.1'] # Use local caching resolver
self.resolver.timeout = 5
self.resolver.lifetime = 10
```
## Usage (Development)
### 1\. Start the Application
```bash ```bash
python app.py python app.py
``` ```
### 2\. Open Your Browser For production, it is recommended to use a more robust server, such as Gunicorn:
Navigate to `http://127.0.0.1:5000`.
### 3\. Basic Reconnaissance Workflow
1. **Enter Target Domain**: Input a domain like `example.com`.
2. **Select Recursion Depth**: Depth 2 is recommended for most investigations.
3. **Start Reconnaissance**: Click "Start Reconnaissance" to begin.
4. **Monitor Progress**: Watch the real-time graph build as relationships are discovered.
5. **Analyze and Export**: Interact with the graph and download the results when the scan is complete.
## Production Deployment
To deploy DNSRecon in a production environment, follow these steps:
### 1\. Use a Production WSGI Server
Do not use the built-in Flask development server for production. Use a WSGI server like **Gunicorn**:
```bash ```bash
pip install gunicorn
gunicorn --workers 4 --bind 0.0.0.0:5000 app:app gunicorn --workers 4 --bind 0.0.0.0:5000 app:app
``` ```
### 2\. Configure Environment Variables -----
Set the following environment variables for a secure and configurable deployment: ## Systemd Service
```bash
# Generate a strong, random secret key
export SECRET_KEY='your-super-secret-and-random-key'
# Set Flask to production mode
export FLASK_ENV='production'
export FLASK_DEBUG=False
# API keys (optional, but recommended for full functionality)
export SHODAN_API_KEY="your_shodan_key"
```
### 3\. Use a Reverse Proxy
Set up a reverse proxy like **Nginx** to sit in front of the Gunicorn server. This provides several benefits, including:
- **TLS/SSL Termination**: Securely handle HTTPS traffic.
- **Load Balancing**: Distribute traffic across multiple application instances.
- **Serving Static Files**: Efficiently serve CSS and JavaScript files.
**Example Nginx Configuration:**
```nginx
server {
listen 80;
server_name your_domain.com;
location / {
return 301 https://$host$request_uri;
}
}
server {
listen 443 ssl;
server_name your_domain.com;
# SSL cert configuration
ssl_certificate /etc/letsencrypt/live/your_domain.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/your_domain.com/privkey.pem;
location / {
proxy_pass http://127.0.0.1:5000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
location /static {
alias /path/to/your/dnsrecon/static;
expires 30d;
}
}
```
## Autostart with systemd
To run DNSRecon as a service that starts automatically on boot, you can use `systemd`. To run DNSRecon as a service that starts automatically on boot, you can use `systemd`.
@@ -245,12 +183,77 @@ You can check the status of the service at any time with:
sudo systemctl status dnsrecon.service sudo systemctl status dnsrecon.service
``` ```
## Security Considerations -----
- **API Keys**: API keys are stored in memory for the duration of a user session and are not written to disk. ## Updating the Application
- **Rate Limiting**: DNSRecon includes built-in rate limiting to be respectful to data sources.
- **Local Use**: The application is designed for local or trusted network use and does not have built-in authentication. **Do not expose it directly to the internet without proper security controls.** To update the application, you should first pull the latest changes from the git repository. Then, you will need to wipe the Redis database and the local cache to ensure that you are using the latest data.
### 1\. Update the Code
```bash
git pull
```
### 2\. Wipe the Redis Database
```bash
redis-cli FLUSHALL
```
### 3\. Wipe the Local Cache
```bash
rm -rf cache/*
```
### 4\. Restart the Service
```bash
sudo systemctl restart dnsrecon.service
```
-----
## Extensibility
DNSRecon is designed to be extensible, and adding new providers is a straightforward process. To add a new provider, you will need to create a new Python file in the `providers` directory that inherits from the `BaseProvider` class. The new provider will need to implement the following methods:
* `get_name()`: Return the name of the provider.
* `get_display_name()`: Return a display-friendly name for the provider.
* `requires_api_key()`: Return `True` if the provider requires an API key.
* `get_eligibility()`: Return a dictionary indicating whether the provider can query domains and/or IPs.
* `is_available()`: Return `True` if the provider is available (e.g., if an API key is configured).
* `query_domain(domain)`: Query the provider for information about a domain.
* `query_ip(ip)`: Query the provider for information about an IP address.
-----
## Unique Capabilities and Limitations
### Unique Capabilities
* **Graph-Based Analysis**: The use of a graph-based data model allows for a more intuitive and powerful analysis of the relationships between different pieces of information.
* **Real-Time Visualization**: The real-time visualization of the graph provides immediate feedback and allows for a more interactive and engaging analysis experience.
* **Session Management**: The session management feature allows multiple users to use the application concurrently without interfering with each other's work.
### Limitations
* **Passive-Only by Default**: While the passive-only approach is a key feature of the tool, it also means that the information it can gather is limited to what is publicly available.
* **No Active Scanning**: The tool does not perform any active scanning, such as port scanning or vulnerability scanning.
-----
## License ## License
This project is licensed under the terms of the license agreement found in the `LICENSE` file. This project is licensed under the terms of the **BSD-3-Clause** license.
Copyright (c) 2025 mstoeck3.
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

605
app.py
View File

@@ -3,53 +3,60 @@
""" """
Flask application entry point for DNSRecon web interface. Flask application entry point for DNSRecon web interface.
Provides REST API endpoints and serves the web interface with user session support. Provides REST API endpoints and serves the web interface with user session support.
FIXED: Enhanced WebSocket integration with proper connection management.
""" """
import json
import traceback import traceback
from flask import Flask, render_template, request, jsonify, send_file, session from flask import Flask, render_template, request, jsonify, send_file, session
from datetime import datetime, timezone, timedelta from datetime import datetime, timezone, timedelta
import io import io
import os
from core.session_manager import session_manager from core.session_manager import session_manager
from flask_socketio import SocketIO
from config import config from config import config
from core.graph_manager import NodeType from core.graph_manager import NodeType
from utils.helpers import is_valid_target from utils.helpers import is_valid_target
from utils.export_manager import export_manager
from decimal import Decimal
app = Flask(__name__) app = Flask(__name__)
# Use centralized configuration for Flask settings socketio = SocketIO(app, cors_allowed_origins="*")
app.config['SECRET_KEY'] = config.flask_secret_key app.config['SECRET_KEY'] = config.flask_secret_key
app.config['PERMANENT_SESSION_LIFETIME'] = timedelta(hours=config.flask_permanent_session_lifetime_hours) app.config['PERMANENT_SESSION_LIFETIME'] = timedelta(hours=config.flask_permanent_session_lifetime_hours)
def get_user_scanner(): def get_user_scanner():
""" """
Retrieves the scanner for the current session, or creates a new FIXED: Retrieves the scanner for the current session with proper socketio management.
session and scanner if one doesn't exist.
""" """
# Get current Flask session info for debugging
current_flask_session_id = session.get('dnsrecon_session_id') current_flask_session_id = session.get('dnsrecon_session_id')
# Try to get existing session
if current_flask_session_id: if current_flask_session_id:
existing_scanner = session_manager.get_session(current_flask_session_id) existing_scanner = session_manager.get_session(current_flask_session_id)
if existing_scanner: if existing_scanner:
# FIXED: Ensure socketio is properly maintained
existing_scanner.socketio = socketio
print(f"✓ Retrieved existing scanner for session {current_flask_session_id[:8]}... with socketio restored")
return current_flask_session_id, existing_scanner return current_flask_session_id, existing_scanner
# Create new session if none exists # FIXED: Register socketio connection when creating new session
print("Creating new session as none was found...") new_session_id = session_manager.create_session(socketio)
new_session_id = session_manager.create_session()
new_scanner = session_manager.get_session(new_session_id) new_scanner = session_manager.get_session(new_session_id)
if not new_scanner: if not new_scanner:
raise Exception("Failed to create new scanner session") raise Exception("Failed to create new scanner session")
# Store in Flask session # FIXED: Ensure new scanner has socketio reference and register the connection
new_scanner.socketio = socketio
session_manager.register_socketio_connection(new_session_id, socketio)
session['dnsrecon_session_id'] = new_session_id session['dnsrecon_session_id'] = new_session_id
session.permanent = True session.permanent = True
print(f"✓ Created new scanner for session {new_session_id[:8]}... with socketio registered")
return new_session_id, new_scanner return new_session_id, new_scanner
@app.route('/') @app.route('/')
def index(): def index():
"""Serve the main web interface.""" """Serve the main web interface."""
@@ -59,11 +66,8 @@ def index():
@app.route('/api/scan/start', methods=['POST']) @app.route('/api/scan/start', methods=['POST'])
def start_scan(): def start_scan():
""" """
Start a new reconnaissance scan. Creates a new isolated scanner if FIXED: Starts a new reconnaissance scan with proper socketio management.
clear_graph is true, otherwise adds to the existing one.
""" """
print("=== API: /api/scan/start called ===")
try: try:
data = request.get_json() data = request.get_json()
if not data or 'target' not in data: if not data or 'target' not in data:
@@ -72,47 +76,36 @@ def start_scan():
target = data['target'].strip() target = data['target'].strip()
max_depth = data.get('max_depth', config.default_recursion_depth) max_depth = data.get('max_depth', config.default_recursion_depth)
clear_graph = data.get('clear_graph', True) clear_graph = data.get('clear_graph', True)
force_rescan_target = data.get('force_rescan_target', None) # **FIX**: Get the new parameter force_rescan_target = data.get('force_rescan_target', None)
print(f"Parsed - target: '{target}', max_depth: {max_depth}, clear_graph: {clear_graph}, force_rescan: {force_rescan_target}")
# Validation
if not target: if not target:
return jsonify({'success': False, 'error': 'Target cannot be empty'}), 400 return jsonify({'success': False, 'error': 'Target cannot be empty'}), 400
if not is_valid_target(target): if not is_valid_target(target):
return jsonify({'success': False, 'error': 'Invalid target format. Please enter a valid domain or IP address.'}), 400 return jsonify({'success': False, 'error': 'Invalid target format.'}), 400
if not isinstance(max_depth, int) or not 1 <= max_depth <= 5: if not isinstance(max_depth, int) or not 1 <= max_depth <= 5:
return jsonify({'success': False, 'error': 'Max depth must be an integer between 1 and 5'}), 400 return jsonify({'success': False, 'error': 'Max depth must be an integer between 1 and 5'}), 400
user_session_id, scanner = None, None
if clear_graph:
print("Clear graph requested: Creating a new, isolated scanner session.")
old_session_id = session.get('dnsrecon_session_id')
if old_session_id:
session_manager.terminate_session(old_session_id)
user_session_id = session_manager.create_session()
session['dnsrecon_session_id'] = user_session_id
session.permanent = True
scanner = session_manager.get_session(user_session_id)
else:
print("Adding to existing graph: Reusing the current scanner session.")
user_session_id, scanner = get_user_scanner() user_session_id, scanner = get_user_scanner()
if not scanner: if not scanner:
return jsonify({'success': False, 'error': 'Failed to get or create a scanner instance.'}), 500 return jsonify({'success': False, 'error': 'Failed to get scanner instance.'}), 500
print(f"Using scanner {id(scanner)} in session {user_session_id}") # FIXED: Ensure scanner has socketio reference and is registered
scanner.socketio = socketio
session_manager.register_socketio_connection(user_session_id, socketio)
print(f"🚀 Starting scan for {target} with socketio enabled and registered")
success = scanner.start_scan(target, max_depth, clear_graph=clear_graph, force_rescan_target=force_rescan_target) # **FIX**: Pass the new parameter success = scanner.start_scan(target, max_depth, clear_graph=clear_graph, force_rescan_target=force_rescan_target)
if success: if success:
# Update session with socketio-enabled scanner
session_manager.update_session_scanner(user_session_id, scanner)
return jsonify({ return jsonify({
'success': True, 'success': True,
'message': 'Scan started successfully', 'message': 'Reconnaissance scan started successfully',
'scan_id': scanner.logger.session_id, 'scan_id': scanner.logger.session_id,
'user_session_id': user_session_id, 'user_session_id': user_session_id
}) })
else: else:
return jsonify({ return jsonify({
@@ -121,187 +114,201 @@ def start_scan():
}), 409 }), 409
except Exception as e: except Exception as e:
print(f"ERROR: Exception in start_scan endpoint: {e}")
traceback.print_exc() traceback.print_exc()
return jsonify({'success': False, 'error': f'Internal server error: {str(e)}'}), 500 return jsonify({'success': False, 'error': f'Internal server error: {str(e)}'}), 500
@app.route('/api/scan/stop', methods=['POST']) @app.route('/api/scan/stop', methods=['POST'])
def stop_scan(): def stop_scan():
"""Stop the current scan with immediate GUI feedback.""" """Stop the current scan."""
print("=== API: /api/scan/stop called ===")
try: try:
# Get user-specific scanner
user_session_id, scanner = get_user_scanner() user_session_id, scanner = get_user_scanner()
print(f"Stopping scan for session: {user_session_id}")
if not scanner: if not scanner:
return jsonify({ return jsonify({'success': False, 'error': 'No scanner found for session'}), 404
'success': False,
'error': 'No scanner found for session'
}), 404
# Ensure session ID is set
if not scanner.session_id: if not scanner.session_id:
scanner.session_id = user_session_id scanner.session_id = user_session_id
# Use the stop mechanism # FIXED: Ensure scanner has socketio reference
success = scanner.stop_scan() scanner.socketio = socketio
session_manager.register_socketio_connection(user_session_id, socketio)
# Also set the Redis stop signal directly for extra reliability scanner.stop_scan()
session_manager.set_stop_signal(user_session_id) session_manager.set_stop_signal(user_session_id)
# Force immediate status update
session_manager.update_scanner_status(user_session_id, 'stopped') session_manager.update_scanner_status(user_session_id, 'stopped')
# Update the full scanner state
session_manager.update_session_scanner(user_session_id, scanner) session_manager.update_session_scanner(user_session_id, scanner)
print(f"Stop scan completed. Success: {success}, Scanner status: {scanner.status}")
return jsonify({ return jsonify({
'success': True, 'success': True,
'message': 'Scan stop requested - termination initiated', 'message': 'Scan stop requested',
'user_session_id': user_session_id, 'user_session_id': user_session_id
'scanner_status': scanner.status,
'stop_method': 'cross_process'
}) })
except Exception as e: except Exception as e:
print(f"ERROR: Exception in stop_scan endpoint: {e}")
traceback.print_exc() traceback.print_exc()
return jsonify({ return jsonify({'success': False, 'error': f'Internal server error: {str(e)}'}), 500
'success': False,
'error': f'Internal server error: {str(e)}'
}), 500
@app.route('/api/scan/status', methods=['GET']) @socketio.on('connect')
def handle_connect():
"""
FIXED: Handle WebSocket connection with proper session management.
"""
print(f'✓ WebSocket client connected: {request.sid}')
# Try to restore existing session connection
current_flask_session_id = session.get('dnsrecon_session_id')
if current_flask_session_id:
# Register this socketio connection for the existing session
session_manager.register_socketio_connection(current_flask_session_id, socketio)
print(f'✓ Registered WebSocket for existing session: {current_flask_session_id[:8]}...')
# Immediately send current status to new connection
get_scan_status()
@socketio.on('disconnect')
def handle_disconnect():
"""
FIXED: Handle WebSocket disconnection gracefully.
"""
print(f'✗ WebSocket client disconnected: {request.sid}')
# Note: We don't immediately remove the socketio connection from session_manager
# because the user might reconnect. The cleanup will happen during session cleanup.
@socketio.on('get_status')
def get_scan_status(): def get_scan_status():
"""Get current scan status with error handling.""" """
FIXED: Get current scan status and emit real-time update with proper error handling.
"""
try: try:
# Get user-specific scanner
user_session_id, scanner = get_user_scanner() user_session_id, scanner = get_user_scanner()
if not scanner: if not scanner:
# Return default idle status if no scanner status = {
return jsonify({
'success': True,
'status': {
'status': 'idle', 'status': 'idle',
'target_domain': None, 'target_domain': None,
'current_depth': 0, 'current_depth': 0,
'max_depth': 0, 'max_depth': 0,
'current_indicator': '',
'total_indicators_found': 0,
'indicators_processed': 0,
'progress_percentage': 0.0, 'progress_percentage': 0.0,
'enabled_providers': [], 'user_session_id': user_session_id,
'graph_statistics': {}, 'graph': {'nodes': [], 'edges': [], 'statistics': {'node_count': 0, 'edge_count': 0}}
'user_session_id': user_session_id
} }
}) print(f"📡 Emitting idle status for session {user_session_id[:8] if user_session_id else 'none'}...")
else:
# Ensure session ID is set
if not scanner.session_id: if not scanner.session_id:
scanner.session_id = user_session_id scanner.session_id = user_session_id
# FIXED: Ensure scanner has socketio reference for future updates
scanner.socketio = socketio
session_manager.register_socketio_connection(user_session_id, socketio)
status = scanner.get_scan_status() status = scanner.get_scan_status()
status['user_session_id'] = user_session_id status['user_session_id'] = user_session_id
# Additional debug info print(f"📡 Emitting status update: {status['status']} - "
status['debug_info'] = { f"Nodes: {len(status.get('graph', {}).get('nodes', []))}, "
'scanner_object_id': id(scanner), f"Edges: {len(status.get('graph', {}).get('edges', []))}")
'session_id_set': bool(scanner.session_id),
'has_scan_thread': bool(scanner.scan_thread and scanner.scan_thread.is_alive())
}
return jsonify({ # Update session with socketio-enabled scanner
'success': True, session_manager.update_session_scanner(user_session_id, scanner)
'status': status
}) socketio.emit('scan_update', status)
except Exception as e: except Exception as e:
print(f"ERROR: Exception in get_scan_status endpoint: {e}")
traceback.print_exc() traceback.print_exc()
return jsonify({ error_status = {
'success': False,
'error': f'Internal server error: {str(e)}',
'fallback_status': {
'status': 'error', 'status': 'error',
'target_domain': None, 'message': 'Failed to get status',
'current_depth': 0, 'graph': {'nodes': [], 'edges': [], 'statistics': {'node_count': 0, 'edge_count': 0}}
'max_depth': 0,
'progress_percentage': 0.0
} }
}), 500 print(f"⚠️ Error getting status, emitting error status")
socketio.emit('scan_update', error_status)
@app.route('/api/graph', methods=['GET']) @app.route('/api/graph', methods=['GET'])
def get_graph_data(): def get_graph_data():
"""Get current graph data with error handling.""" """Get current graph data."""
try: try:
# Get user-specific scanner
user_session_id, scanner = get_user_scanner() user_session_id, scanner = get_user_scanner()
if not scanner: empty_graph = {
# Return empty graph if no scanner 'nodes': [], 'edges': [],
return jsonify({
'success': True,
'graph': {
'nodes': [],
'edges': [],
'statistics': {
'node_count': 0,
'edge_count': 0,
'creation_time': datetime.now(timezone.utc).isoformat(),
'last_modified': datetime.now(timezone.utc).isoformat()
}
},
'user_session_id': user_session_id
})
graph_data = scanner.get_graph_data()
return jsonify({
'success': True,
'graph': graph_data,
'user_session_id': user_session_id
})
except Exception as e:
print(f"ERROR: Exception in get_graph_data endpoint: {e}")
traceback.print_exc()
return jsonify({
'success': False,
'error': f'Internal server error: {str(e)}',
'fallback_graph': {
'nodes': [],
'edges': [],
'statistics': {'node_count': 0, 'edge_count': 0} 'statistics': {'node_count': 0, 'edge_count': 0}
} }
if not scanner:
return jsonify({'success': True, 'graph': empty_graph, 'user_session_id': user_session_id})
# FIXED: Ensure scanner has socketio reference
scanner.socketio = socketio
session_manager.register_socketio_connection(user_session_id, socketio)
graph_data = scanner.get_graph_data() or empty_graph
return jsonify({'success': True, 'graph': graph_data, 'user_session_id': user_session_id})
except Exception as e:
traceback.print_exc()
return jsonify({
'success': False, 'error': f'Internal server error: {str(e)}',
'fallback_graph': {'nodes': [], 'edges': [], 'statistics': {}}
}), 500 }), 500
@app.route('/api/graph/large-entity/extract', methods=['POST'])
def extract_from_large_entity():
"""Extract a node from a large entity."""
try:
data = request.get_json()
large_entity_id = data.get('large_entity_id')
node_id = data.get('node_id')
if not large_entity_id or not node_id:
return jsonify({'success': False, 'error': 'Missing required parameters'}), 400
user_session_id, scanner = get_user_scanner()
if not scanner:
return jsonify({'success': False, 'error': 'No active session found'}), 404
# FIXED: Ensure scanner has socketio reference
scanner.socketio = socketio
session_manager.register_socketio_connection(user_session_id, socketio)
success = scanner.extract_node_from_large_entity(large_entity_id, node_id)
if success:
session_manager.update_session_scanner(user_session_id, scanner)
return jsonify({'success': True, 'message': f'Node {node_id} extracted successfully.'})
else:
return jsonify({'success': False, 'error': f'Failed to extract node {node_id}.'}), 500
except Exception as e:
traceback.print_exc()
return jsonify({'success': False, 'error': f'Internal server error: {str(e)}'}), 500
@app.route('/api/graph/node/<node_id>', methods=['DELETE']) @app.route('/api/graph/node/<node_id>', methods=['DELETE'])
def delete_graph_node(node_id): def delete_graph_node(node_id):
"""Delete a node from the graph for the current user session.""" """Delete a node from the graph."""
try: try:
user_session_id, scanner = get_user_scanner() user_session_id, scanner = get_user_scanner()
if not scanner: if not scanner:
return jsonify({'success': False, 'error': 'No active session found'}), 404 return jsonify({'success': False, 'error': 'No active session found'}), 404
# FIXED: Ensure scanner has socketio reference
scanner.socketio = socketio
session_manager.register_socketio_connection(user_session_id, socketio)
success = scanner.graph.remove_node(node_id) success = scanner.graph.remove_node(node_id)
if success: if success:
# Persist the change
session_manager.update_session_scanner(user_session_id, scanner) session_manager.update_session_scanner(user_session_id, scanner)
return jsonify({'success': True, 'message': f'Node {node_id} deleted successfully.'}) return jsonify({'success': True, 'message': f'Node {node_id} deleted successfully.'})
else: else:
return jsonify({'success': False, 'error': f'Node {node_id} not found in graph.'}), 404 return jsonify({'success': False, 'error': f'Node {node_id} not found.'}), 404
except Exception as e: except Exception as e:
print(f"ERROR: Exception in delete_graph_node endpoint: {e}")
traceback.print_exc() traceback.print_exc()
return jsonify({'success': False, 'error': f'Internal server error: {str(e)}'}), 500 return jsonify({'success': False, 'error': f'Internal server error: {str(e)}'}), 500
@@ -318,11 +325,14 @@ def revert_graph_action():
if not scanner: if not scanner:
return jsonify({'success': False, 'error': 'No active session found'}), 404 return jsonify({'success': False, 'error': 'No active session found'}), 404
# FIXED: Ensure scanner has socketio reference
scanner.socketio = socketio
session_manager.register_socketio_connection(user_session_id, socketio)
action_type = data['type'] action_type = data['type']
action_data = data['data'] action_data = data['data']
if action_type == 'delete': if action_type == 'delete':
# Re-add the node
node_to_add = action_data.get('node') node_to_add = action_data.get('node')
if node_to_add: if node_to_add:
scanner.graph.add_node( scanner.graph.add_node(
@@ -333,56 +343,66 @@ def revert_graph_action():
metadata=node_to_add.get('metadata') metadata=node_to_add.get('metadata')
) )
# Re-add the edges
edges_to_add = action_data.get('edges', []) edges_to_add = action_data.get('edges', [])
for edge in edges_to_add: for edge in edges_to_add:
# Add edge only if both nodes exist to prevent errors
if scanner.graph.graph.has_node(edge['from']) and scanner.graph.graph.has_node(edge['to']): if scanner.graph.graph.has_node(edge['from']) and scanner.graph.graph.has_node(edge['to']):
scanner.graph.add_edge( scanner.graph.add_edge(
source_id=edge['from'], source_id=edge['from'], target_id=edge['to'],
target_id=edge['to'],
relationship_type=edge['metadata']['relationship_type'], relationship_type=edge['metadata']['relationship_type'],
confidence_score=edge['metadata']['confidence_score'], confidence_score=edge['metadata']['confidence_score'],
source_provider=edge['metadata']['source_provider'], source_provider=edge['metadata']['source_provider'],
raw_data=edge.get('raw_data', {}) raw_data=edge.get('raw_data', {})
) )
# Persist the change
session_manager.update_session_scanner(user_session_id, scanner) session_manager.update_session_scanner(user_session_id, scanner)
return jsonify({'success': True, 'message': 'Delete action reverted successfully.'}) return jsonify({'success': True, 'message': 'Delete action reverted successfully.'})
return jsonify({'success': False, 'error': f'Unknown revert action type: {action_type}'}), 400 return jsonify({'success': False, 'error': f'Unknown revert action type: {action_type}'}), 400
except Exception as e: except Exception as e:
print(f"ERROR: Exception in revert_graph_action endpoint: {e}")
traceback.print_exc() traceback.print_exc()
return jsonify({'success': False, 'error': f'Internal server error: {str(e)}'}), 500 return jsonify({'success': False, 'error': f'Internal server error: {str(e)}'}), 500
@app.route('/api/export', methods=['GET']) @app.route('/api/export', methods=['GET'])
def export_results(): def export_results():
"""Export complete scan results as downloadable JSON for the user session.""" """Export scan results as a JSON file with improved error handling."""
try: try:
# Get user-specific scanner
user_session_id, scanner = get_user_scanner() user_session_id, scanner = get_user_scanner()
# Get complete results if not scanner:
results = scanner.export_results() return jsonify({'success': False, 'error': 'No active scanner session found'}), 404
# Add session information to export # FIXED: Ensure scanner has socketio reference
results['export_metadata'] = { scanner.socketio = socketio
'user_session_id': user_session_id, session_manager.register_socketio_connection(user_session_id, socketio)
'export_timestamp': datetime.now(timezone.utc).isoformat(),
'export_type': 'user_session_results'
}
# Create filename with timestamp # Get export data using the new export manager
timestamp = datetime.now(timezone.utc).strftime('%Y%m%d_%H%M%S') try:
target = scanner.current_target or 'unknown' results = export_manager.export_scan_results(scanner)
filename = f"dnsrecon_{target}_{timestamp}_{user_session_id[:8]}.json" except Exception as e:
return jsonify({'success': False, 'error': f'Failed to gather export data: {str(e)}'}), 500
# Create in-memory file # Add user session metadata
json_data = json.dumps(results, indent=2, ensure_ascii=False) results['export_metadata']['user_session_id'] = user_session_id
results['export_metadata']['forensic_integrity'] = 'maintained'
# Generate filename
filename = export_manager.generate_filename(
target=scanner.current_target or 'unknown',
export_type='json'
)
# Serialize with export manager
try:
json_data = export_manager.serialize_to_json(results)
except Exception as e:
return jsonify({
'success': False,
'error': f'JSON serialization failed: {str(e)}'
}), 500
# Create file object
file_obj = io.BytesIO(json_data.encode('utf-8')) file_obj = io.BytesIO(json_data.encode('utf-8'))
return send_file( return send_file(
@@ -393,70 +413,98 @@ def export_results():
) )
except Exception as e: except Exception as e:
print(f"ERROR: Exception in export_results endpoint: {e}")
traceback.print_exc() traceback.print_exc()
return jsonify({ return jsonify({
'success': False, 'success': False,
'error': f'Export failed: {str(e)}' 'error': f'Export failed: {str(e)}',
'error_type': type(e).__name__
}), 500 }), 500
@app.route('/api/export/targets', methods=['GET'])
@app.route('/api/providers', methods=['GET']) def export_targets():
def get_providers(): """Export all discovered targets as a TXT file."""
"""Get information about available providers for the user session."""
try: try:
# Get user-specific scanner
user_session_id, scanner = get_user_scanner() user_session_id, scanner = get_user_scanner()
if not scanner:
return jsonify({'success': False, 'error': 'No active scanner session found'}), 404
if scanner: # FIXED: Ensure scanner has socketio reference
completed_tasks = scanner.indicators_completed scanner.socketio = socketio
enqueued_tasks = len(scanner.task_queue) session_manager.register_socketio_connection(user_session_id, socketio)
print(f"DEBUG: Tasks - Completed: {completed_tasks}, Enqueued: {enqueued_tasks}")
else:
print("DEBUG: No active scanner session found.")
provider_info = scanner.get_provider_info() # Use export manager for targets export
targets_txt = export_manager.export_targets_list(scanner)
return jsonify({ # Generate filename using export manager
'success': True, filename = export_manager.generate_filename(
'providers': provider_info, target=scanner.current_target or 'unknown',
'user_session_id': user_session_id export_type='targets'
}) )
file_obj = io.BytesIO(targets_txt.encode('utf-8'))
return send_file(
file_obj,
as_attachment=True,
download_name=filename,
mimetype='text/plain'
)
except Exception as e: except Exception as e:
print(f"ERROR: Exception in get_providers endpoint: {e}")
traceback.print_exc() traceback.print_exc()
return jsonify({ return jsonify({'success': False, 'error': f'Export failed: {str(e)}'}), 500
'success': False,
'error': f'Internal server error: {str(e)}'
}), 500
@app.route('/api/export/summary', methods=['GET'])
def export_summary():
"""Export an executive summary as a TXT file."""
try:
user_session_id, scanner = get_user_scanner()
if not scanner:
return jsonify({'success': False, 'error': 'No active scanner session found'}), 404
# FIXED: Ensure scanner has socketio reference
scanner.socketio = socketio
session_manager.register_socketio_connection(user_session_id, socketio)
# Use export manager for summary generation
summary_txt = export_manager.generate_executive_summary(scanner)
# Generate filename using export manager
filename = export_manager.generate_filename(
target=scanner.current_target or 'unknown',
export_type='summary'
)
file_obj = io.BytesIO(summary_txt.encode('utf-8'))
return send_file(
file_obj,
as_attachment=True,
download_name=filename,
mimetype='text/plain'
)
except Exception as e:
traceback.print_exc()
return jsonify({'success': False, 'error': f'Export failed: {str(e)}'}), 500
@app.route('/api/config/api-keys', methods=['POST']) @app.route('/api/config/api-keys', methods=['POST'])
def set_api_keys(): def set_api_keys():
""" """Set API keys for the current session."""
Set API keys for providers for the user session only.
"""
try: try:
data = request.get_json() data = request.get_json()
if data is None: if data is None:
return jsonify({ return jsonify({'success': False, 'error': 'No API keys provided'}), 400
'success': False,
'error': 'No API keys provided'
}), 400
# Get user-specific scanner and config
user_session_id, scanner = get_user_scanner() user_session_id, scanner = get_user_scanner()
session_config = scanner.config session_config = scanner.config
# FIXED: Ensure scanner has socketio reference
scanner.socketio = socketio
session_manager.register_socketio_connection(user_session_id, socketio)
updated_providers = [] updated_providers = []
# Iterate over the API keys provided in the request data
for provider_name, api_key in data.items(): for provider_name, api_key in data.items():
# This allows us to both set and clear keys. The config
# handles enabling/disabling based on if the key is empty.
api_key_value = str(api_key or '').strip() api_key_value = str(api_key or '').strip()
success = session_config.set_api_key(provider_name.lower(), api_key_value) success = session_config.set_api_key(provider_name.lower(), api_key_value)
@@ -464,63 +512,146 @@ def set_api_keys():
updated_providers.append(provider_name) updated_providers.append(provider_name)
if updated_providers: if updated_providers:
# Reinitialize scanner providers to apply the new keys
scanner._initialize_providers() scanner._initialize_providers()
# Persist the updated scanner object back to the user's session
session_manager.update_session_scanner(user_session_id, scanner) session_manager.update_session_scanner(user_session_id, scanner)
return jsonify({ return jsonify({
'success': True, 'success': True,
'message': f'API keys updated for session {user_session_id}: {", ".join(updated_providers)}', 'message': f'API keys updated for: {", ".join(updated_providers)}',
'updated_providers': updated_providers,
'user_session_id': user_session_id 'user_session_id': user_session_id
}) })
else: else:
return jsonify({ return jsonify({'success': False, 'error': 'No valid API keys were provided.'}), 400
'success': False,
'error': 'No valid API keys were provided or provider names were incorrect.'
}), 400
except Exception as e: except Exception as e:
print(f"ERROR: Exception in set_api_keys endpoint: {e}")
traceback.print_exc() traceback.print_exc()
return jsonify({'success': False, 'error': f'Internal server error: {str(e)}'}), 500
@app.route('/api/providers', methods=['GET'])
def get_providers():
"""Get enhanced information about available providers including API key sources."""
try:
user_session_id, scanner = get_user_scanner()
base_provider_info = scanner.get_provider_info()
# FIXED: Ensure scanner has socketio reference
scanner.socketio = socketio
session_manager.register_socketio_connection(user_session_id, socketio)
# Enhance provider info with API key source information
enhanced_provider_info = {}
for provider_name, info in base_provider_info.items():
enhanced_info = dict(info) # Copy base info
if info['requires_api_key']:
# Determine API key source and configuration status
api_key = scanner.config.get_api_key(provider_name)
backend_api_key = os.getenv(f'{provider_name.upper()}_API_KEY')
if backend_api_key:
# API key configured via backend/environment
enhanced_info.update({
'api_key_configured': True,
'api_key_source': 'backend',
'api_key_help': f'API key configured via environment variable {provider_name.upper()}_API_KEY'
})
elif api_key:
# API key configured via web interface
enhanced_info.update({
'api_key_configured': True,
'api_key_source': 'frontend',
'api_key_help': f'API key set via web interface (session-only)'
})
else:
# No API key configured
enhanced_info.update({
'api_key_configured': False,
'api_key_source': None,
'api_key_help': f'Requires API key to enable {info["display_name"]} integration'
})
else:
# Provider doesn't require API key
enhanced_info.update({
'api_key_configured': True, # Always "configured" for non-API providers
'api_key_source': None,
'api_key_help': None
})
enhanced_provider_info[provider_name] = enhanced_info
return jsonify({ return jsonify({
'success': False, 'success': True,
'error': f'Internal server error: {str(e)}' 'providers': enhanced_provider_info,
}), 500 'user_session_id': user_session_id
})
except Exception as e:
traceback.print_exc()
return jsonify({'success': False, 'error': f'Internal server error: {str(e)}'}), 500
@app.route('/api/config/providers', methods=['POST'])
def configure_providers():
"""Configure provider settings (enable/disable)."""
try:
data = request.get_json()
if data is None:
return jsonify({'success': False, 'error': 'No provider settings provided'}), 400
user_session_id, scanner = get_user_scanner()
session_config = scanner.config
# FIXED: Ensure scanner has socketio reference
scanner.socketio = socketio
session_manager.register_socketio_connection(user_session_id, socketio)
updated_providers = []
for provider_name, settings in data.items():
provider_name_clean = provider_name.lower().strip()
if 'enabled' in settings:
# Update the enabled state in session config
session_config.enabled_providers[provider_name_clean] = settings['enabled']
updated_providers.append(provider_name_clean)
if updated_providers:
# Reinitialize providers with new settings
scanner._initialize_providers()
session_manager.update_session_scanner(user_session_id, scanner)
return jsonify({
'success': True,
'message': f'Provider settings updated for: {", ".join(updated_providers)}',
'user_session_id': user_session_id
})
else:
return jsonify({'success': False, 'error': 'No valid provider settings were provided.'}), 400
except Exception as e:
traceback.print_exc()
return jsonify({'success': False, 'error': f'Internal server error: {str(e)}'}), 500
@app.errorhandler(404) @app.errorhandler(404)
def not_found(error): def not_found(error):
"""Handle 404 errors.""" """Handle 404 errors."""
return jsonify({ return jsonify({'success': False, 'error': 'Endpoint not found'}), 404
'success': False,
'error': 'Endpoint not found'
}), 404
@app.errorhandler(500) @app.errorhandler(500)
def internal_error(error): def internal_error(error):
"""Handle 500 errors.""" """Handle 500 errors."""
print(f"ERROR: 500 Internal Server Error: {error}")
traceback.print_exc() traceback.print_exc()
return jsonify({ return jsonify({'success': False, 'error': 'Internal server error'}), 500
'success': False,
'error': 'Internal server error'
}), 500
if __name__ == '__main__': if __name__ == '__main__':
print("Starting DNSRecon Flask application with user session support...")
# Load configuration from environment
config.load_from_env() config.load_from_env()
print("🚀 Starting DNSRecon with enhanced WebSocket support...")
# Start Flask application print(f" Host: {config.flask_host}")
print(f"Starting server on {config.flask_host}:{config.flask_port}") print(f" Port: {config.flask_port}")
app.run( print(f" Debug: {config.flask_debug}")
host=config.flask_host, print(" WebSocket: Enhanced connection management enabled")
port=config.flask_port, socketio.run(app, host=config.flask_host, port=config.flask_port, debug=config.flask_debug)
debug=config.flask_debug,
threaded=True
)

File diff suppressed because one or more lines are too long

View File

@@ -1 +0,0 @@
{"domain":"api.piped.mikoshi.de","first_cached":"2025-09-14T22:39:13.556737+00:00","last_upstream_query":"2025-09-15T15:40:40.243081+00:00","upstream_query_count":2,"certificates":[{"issuer_ca_id":295819,"issuer_name":"C=US, O=Let's Encrypt, CN=E6","common_name":"api.piped.mikoshi.de","name_value":"api.piped.mikoshi.de","id":20189195635,"entry_timestamp":"2025-08-08T00:03:32.697","not_before":"2025-08-07T23:05:02","not_after":"2025-11-05T23:05:01","serial_number":"057a2344f2f0cff0a83bba587eb7326b4145","result_count":2},{"issuer_ca_id":295819,"issuer_name":"C=US, O=Let's Encrypt, CN=E6","common_name":"api.piped.mikoshi.de","name_value":"api.piped.mikoshi.de","id":20189195721,"entry_timestamp":"2025-08-08T00:03:32.49","not_before":"2025-08-07T23:05:02","not_after":"2025-11-05T23:05:01","serial_number":"057a2344f2f0cff0a83bba587eb7326b4145","result_count":2},{"issuer_ca_id":295819,"issuer_name":"C=US, O=Let's Encrypt, CN=E6","common_name":"api.piped.mikoshi.de","name_value":"api.piped.mikoshi.de","id":20060635277,"entry_timestamp":"2025-08-02T00:01:30.128","not_before":"2025-08-01T23:02:57","not_after":"2025-10-30T23:02:56","serial_number":"05a33355cd549118b90ec6c7219b2e283059","result_count":2},{"issuer_ca_id":295819,"issuer_name":"C=US, O=Let's Encrypt, CN=E6","common_name":"api.piped.mikoshi.de","name_value":"api.piped.mikoshi.de","id":20060633958,"entry_timestamp":"2025-08-02T00:01:27.809","not_before":"2025-08-01T23:02:57","not_after":"2025-10-30T23:02:56","serial_number":"05a33355cd549118b90ec6c7219b2e283059","result_count":2},{"issuer_ca_id":295819,"issuer_name":"C=US, O=Let's Encrypt, CN=E6","common_name":"api.piped.mikoshi.de","name_value":"api.piped.mikoshi.de","id":19929361217,"entry_timestamp":"2025-07-27T00:01:57.423","not_before":"2025-07-26T23:03:27","not_after":"2025-10-24T23:03:26","serial_number":"068f68538c5e6483213c6bdff93070960e6a","result_count":2},{"issuer_ca_id":295819,"issuer_name":"C=US, O=Let's Encrypt, CN=E6","common_name":"api.piped.mikoshi.de","name_value":"api.piped.mikoshi.de","id":19929361084,"entry_timestamp":"2025-07-27T00:01:57.128","not_before":"2025-07-26T23:03:27","not_after":"2025-10-24T23:03:26","serial_number":"068f68538c5e6483213c6bdff93070960e6a","result_count":2},{"issuer_ca_id":295810,"issuer_name":"C=US, O=Let's Encrypt, CN=E5","common_name":"api.piped.mikoshi.de","name_value":"api.piped.mikoshi.de","id":19803755935,"entry_timestamp":"2025-07-21T00:00:47.697","not_before":"2025-07-20T23:02:17","not_after":"2025-10-18T23:02:16","serial_number":"054cc0b2449a9ce1ce82324d844a1d4795f5","result_count":2},{"issuer_ca_id":295810,"issuer_name":"C=US, O=Let's Encrypt, CN=E5","common_name":"api.piped.mikoshi.de","name_value":"api.piped.mikoshi.de","id":19803753732,"entry_timestamp":"2025-07-21T00:00:47.407","not_before":"2025-07-20T23:02:17","not_after":"2025-10-18T23:02:16","serial_number":"054cc0b2449a9ce1ce82324d844a1d4795f5","result_count":2},{"issuer_ca_id":295810,"issuer_name":"C=US, O=Let's Encrypt, CN=E5","common_name":"api.piped.mikoshi.de","name_value":"api.piped.mikoshi.de","id":19668414027,"entry_timestamp":"2025-07-15T00:00:49.06","not_before":"2025-07-14T23:02:16","not_after":"2025-10-12T23:02:15","serial_number":"06ee7d4154b5a296e1cbefe4df2f6bfeba81","result_count":2},{"issuer_ca_id":295810,"issuer_name":"C=US, O=Let's Encrypt, CN=E5","common_name":"api.piped.mikoshi.de","name_value":"api.piped.mikoshi.de","id":19668413763,"entry_timestamp":"2025-07-15T00:00:46.299","not_before":"2025-07-14T23:02:16","not_after":"2025-10-12T23:02:15","serial_number":"06ee7d4154b5a296e1cbefe4df2f6bfeba81","result_count":2},{"issuer_ca_id":295819,"issuer_name":"C=US, O=Let's Encrypt, CN=E6","common_name":"api.piped.mikoshi.de","name_value":"api.piped.mikoshi.de","id":19523855233,"entry_timestamp":"2025-07-08T06:30:53.184","not_before":"2025-07-08T05:32:22","not_after":"2025-10-06T05:32:21","serial_number":"05956787611c0bc853c699866a6bc839eb89","result_count":2},{"issuer_ca_id":295819,"issuer_name":"C=US, O=Let's Encrypt, CN=E6","common_name":"api.piped.mikoshi.de","name_value":"api.piped.mikoshi.de","id":19523854846,"entry_timestamp":"2025-07-08T06:30:52.835","not_before":"2025-07-08T05:32:22","not_after":"2025-10-06T05:32:21","serial_number":"05956787611c0bc853c699866a6bc839eb89","result_count":2}]}

View File

@@ -1 +0,0 @@
{"domain":"app.fleischkombinat-ost.de","first_cached":"2025-09-14T21:11:17.304989+00:00","last_upstream_query":"2025-09-15T09:15:09.273000+00:00","upstream_query_count":2,"certificates":[{"issuer_ca_id":295819,"issuer_name":"C=US, O=Let's Encrypt, CN=E6","common_name":"app.fleischkombinat-ost.de","name_value":"app.fleischkombinat-ost.de","id":19374493240,"entry_timestamp":"2025-07-01T14:09:36.354","not_before":"2025-07-01T13:11:00","not_after":"2025-09-29T13:10:59","serial_number":"0693231ff5e3212cabc2588e38b5d8337528","result_count":2},{"issuer_ca_id":295819,"issuer_name":"C=US, O=Let's Encrypt, CN=E6","common_name":"app.fleischkombinat-ost.de","name_value":"app.fleischkombinat-ost.de","id":19374489847,"entry_timestamp":"2025-07-01T14:09:30.117","not_before":"2025-07-01T13:11:00","not_after":"2025-09-29T13:10:59","serial_number":"0693231ff5e3212cabc2588e38b5d8337528","result_count":2}]}

File diff suppressed because one or more lines are too long

View File

@@ -1 +0,0 @@
{"domain":"c210lb.kasserver.com","first_cached":"2025-09-15T11:49:15.879325+00:00","last_upstream_query":"2025-09-15T11:49:15.879328+00:00","upstream_query_count":1,"certificates":[{"issuer_ca_id":295810,"issuer_name":"C=US, O=Let's Encrypt, CN=E5","common_name":"test.c210lb.kasserver.com","name_value":"test.c210lb.kasserver.com\nwww.test.c210lb.kasserver.com","id":16080758209,"entry_timestamp":"2024-12-12T09:28:08.296","not_before":"2024-12-12T08:29:37","not_after":"2025-03-12T08:29:36","serial_number":"04d8425c5834ecd8914f58bb80e86bcae4a4","result_count":3},{"issuer_ca_id":295810,"issuer_name":"C=US, O=Let's Encrypt, CN=E5","common_name":"test.c210lb.kasserver.com","name_value":"test.c210lb.kasserver.com\nwww.test.c210lb.kasserver.com","id":15724227115,"entry_timestamp":"2024-12-12T09:28:07.974","not_before":"2024-12-12T08:29:37","not_after":"2025-03-12T08:29:36","serial_number":"04d8425c5834ecd8914f58bb80e86bcae4a4","result_count":3}]}

View File

@@ -1 +0,0 @@
{"domain":"c214lb.kasserver.com","first_cached":"2025-09-15T11:50:40.061642+00:00","last_upstream_query":"2025-09-15T11:50:40.061644+00:00","upstream_query_count":1,"certificates":[{"issuer_ca_id":295810,"issuer_name":"C=US, O=Let's Encrypt, CN=E5","common_name":"test.c214lb.kasserver.com","name_value":"test.c214lb.kasserver.com\nwww.test.c214lb.kasserver.com","id":16070500096,"entry_timestamp":"2024-12-11T14:25:06.88","not_before":"2024-12-11T13:26:36","not_after":"2025-03-11T13:26:35","serial_number":"047e10af0f4b68375cc37572f400322f1339","result_count":3},{"issuer_ca_id":295810,"issuer_name":"C=US, O=Let's Encrypt, CN=E5","common_name":"test.c214lb.kasserver.com","name_value":"test.c214lb.kasserver.com\nwww.test.c214lb.kasserver.com","id":15713437449,"entry_timestamp":"2024-12-11T14:25:06.342","not_before":"2024-12-11T13:26:36","not_after":"2025-03-11T13:26:35","serial_number":"047e10af0f4b68375cc37572f400322f1339","result_count":3}]}

File diff suppressed because one or more lines are too long

View File

@@ -1 +0,0 @@
{"domain":"cc24.mikoshi.de","first_cached":"2025-09-15T15:35:01.674879+00:00","last_upstream_query":"2025-09-15T15:35:01.674884+00:00","upstream_query_count":1,"certificates":[{"issuer_ca_id":295815,"issuer_name":"C=US, O=Let's Encrypt, CN=R11","common_name":"cc24.mikoshi.de","name_value":"cc24.mikoshi.de","id":20275888640,"entry_timestamp":"2025-08-12T00:10:43.67","not_before":"2025-08-11T23:12:11","not_after":"2025-11-09T23:12:10","serial_number":"062bf40cddf77b5bb2efcc8d4394466e2f1b","result_count":2},{"issuer_ca_id":295815,"issuer_name":"C=US, O=Let's Encrypt, CN=R11","common_name":"cc24.mikoshi.de","name_value":"cc24.mikoshi.de","id":20275882615,"entry_timestamp":"2025-08-12T00:10:41.383","not_before":"2025-08-11T23:12:11","not_after":"2025-11-09T23:12:10","serial_number":"062bf40cddf77b5bb2efcc8d4394466e2f1b","result_count":2},{"issuer_ca_id":295815,"issuer_name":"C=US, O=Let's Encrypt, CN=R11","common_name":"cc24.mikoshi.de","name_value":"cc24.mikoshi.de","id":18987170126,"entry_timestamp":"2025-06-13T00:07:54.264","not_before":"2025-06-12T23:09:23","not_after":"2025-09-10T23:09:22","serial_number":"06146db771c214ec7474cb203b6ab75c21ae","result_count":2},{"issuer_ca_id":295815,"issuer_name":"C=US, O=Let's Encrypt, CN=R11","common_name":"cc24.mikoshi.de","name_value":"cc24.mikoshi.de","id":18987169887,"entry_timestamp":"2025-06-13T00:07:53.982","not_before":"2025-06-12T23:09:23","not_after":"2025-09-10T23:09:22","serial_number":"06146db771c214ec7474cb203b6ab75c21ae","result_count":2},{"issuer_ca_id":295815,"issuer_name":"C=US, O=Let's Encrypt, CN=R11","common_name":"cc24.mikoshi.de","name_value":"cc24.mikoshi.de","id":17831548102,"entry_timestamp":"2025-04-14T00:19:47.297","not_before":"2025-04-13T23:21:14","not_after":"2025-07-12T23:21:13","serial_number":"05d1504b6ed3a888b7577090d0f45a5e1f6e","result_count":2},{"issuer_ca_id":295815,"issuer_name":"C=US, O=Let's Encrypt, CN=R11","common_name":"cc24.mikoshi.de","name_value":"cc24.mikoshi.de","id":17831584469,"entry_timestamp":"2025-04-14T00:19:45.047","not_before":"2025-04-13T23:21:14","not_after":"2025-07-12T23:21:13","serial_number":"05d1504b6ed3a888b7577090d0f45a5e1f6e","result_count":2},{"issuer_ca_id":295814,"issuer_name":"C=US, O=Let's Encrypt, CN=R10","common_name":"cc24.mikoshi.de","name_value":"cc24.mikoshi.de","id":17170817151,"entry_timestamp":"2025-02-13T00:02:39.94","not_before":"2025-02-12T23:04:09","not_after":"2025-05-13T23:04:08","serial_number":"03b5b2d8ad135f1cf98224c917b797d0d844","result_count":2},{"issuer_ca_id":295814,"issuer_name":"C=US, O=Let's Encrypt, CN=R10","common_name":"cc24.mikoshi.de","name_value":"cc24.mikoshi.de","id":16704121260,"entry_timestamp":"2025-02-13T00:02:39.313","not_before":"2025-02-12T23:04:09","not_after":"2025-05-13T23:04:08","serial_number":"03b5b2d8ad135f1cf98224c917b797d0d844","result_count":2},{"issuer_ca_id":295815,"issuer_name":"C=US, O=Let's Encrypt, CN=R11","common_name":"cc24.mikoshi.de","name_value":"cc24.mikoshi.de","id":16672548148,"entry_timestamp":"2025-02-11T11:09:43.173","not_before":"2025-02-11T10:11:12","not_after":"2025-05-12T10:11:11","serial_number":"035ed55d94e5d12e255be2412e4035be70c9","result_count":2},{"issuer_ca_id":295815,"issuer_name":"C=US, O=Let's Encrypt, CN=R11","common_name":"cc24.mikoshi.de","name_value":"cc24.mikoshi.de","id":16672548664,"entry_timestamp":"2025-02-11T11:09:42.207","not_before":"2025-02-11T10:11:12","not_after":"2025-05-12T10:11:11","serial_number":"035ed55d94e5d12e255be2412e4035be70c9","result_count":2}]}

View File

@@ -1 +0,0 @@
{"domain":"cloud.aibkurpark.de","first_cached":"2025-09-14T22:46:40.289218+00:00","last_upstream_query":"2025-09-15T15:41:52.573914+00:00","upstream_query_count":2,"certificates":[{"issuer_ca_id":295814,"issuer_name":"C=US, O=Let's Encrypt, CN=R10","common_name":"cloud.aibkurpark.de","name_value":"cloud.aibkurpark.de","id":20275873234,"entry_timestamp":"2025-08-12T00:10:04.8","not_before":"2025-08-11T23:11:34","not_after":"2025-11-09T23:11:33","serial_number":"0502f324ff45ca5c652de0f798011836a079","result_count":2},{"issuer_ca_id":295814,"issuer_name":"C=US, O=Let's Encrypt, CN=R10","common_name":"cloud.aibkurpark.de","name_value":"cloud.aibkurpark.de","id":20275861222,"entry_timestamp":"2025-08-12T00:10:04.577","not_before":"2025-08-11T23:11:34","not_after":"2025-11-09T23:11:33","serial_number":"0502f324ff45ca5c652de0f798011836a079","result_count":2},{"issuer_ca_id":295814,"issuer_name":"C=US, O=Let's Encrypt, CN=R10","common_name":"cloud.aibkurpark.de","name_value":"cloud.aibkurpark.de","id":18987158394,"entry_timestamp":"2025-06-13T00:07:19.317","not_before":"2025-06-12T23:08:44","not_after":"2025-09-10T23:08:43","serial_number":"051a486ebf950f3ccc46e6da6bc68a6477cc","result_count":2},{"issuer_ca_id":295814,"issuer_name":"C=US, O=Let's Encrypt, CN=R10","common_name":"cloud.aibkurpark.de","name_value":"cloud.aibkurpark.de","id":18987157465,"entry_timestamp":"2025-06-13T00:07:15.025","not_before":"2025-06-12T23:08:44","not_after":"2025-09-10T23:08:43","serial_number":"051a486ebf950f3ccc46e6da6bc68a6477cc","result_count":2},{"issuer_ca_id":295814,"issuer_name":"C=US, O=Let's Encrypt, CN=R10","common_name":"cloud.aibkurpark.de","name_value":"cloud.aibkurpark.de","id":17831539356,"entry_timestamp":"2025-04-14T00:19:09.511","not_before":"2025-04-13T23:20:39","not_after":"2025-07-12T23:20:38","serial_number":"05d6f819ef2fc26e17ae6bdc186dc1f83610","result_count":2},{"issuer_ca_id":295814,"issuer_name":"C=US, O=Let's Encrypt, CN=R10","common_name":"cloud.aibkurpark.de","name_value":"cloud.aibkurpark.de","id":17831579073,"entry_timestamp":"2025-04-14T00:19:09.182","not_before":"2025-04-13T23:20:39","not_after":"2025-07-12T23:20:38","serial_number":"05d6f819ef2fc26e17ae6bdc186dc1f83610","result_count":2},{"issuer_ca_id":295814,"issuer_name":"C=US, O=Let's Encrypt, CN=R10","common_name":"cloud.aibkurpark.de","name_value":"cloud.aibkurpark.de","id":17170816053,"entry_timestamp":"2025-02-13T00:02:33.08","not_before":"2025-02-12T23:04:01","not_after":"2025-05-13T23:04:00","serial_number":"0457fefa87af5335359d49883ebe4b6c2f22","result_count":2},{"issuer_ca_id":295814,"issuer_name":"C=US, O=Let's Encrypt, CN=R10","common_name":"cloud.aibkurpark.de","name_value":"cloud.aibkurpark.de","id":16704122042,"entry_timestamp":"2025-02-13T00:02:31.914","not_before":"2025-02-12T23:04:01","not_after":"2025-05-13T23:04:00","serial_number":"0457fefa87af5335359d49883ebe4b6c2f22","result_count":2},{"issuer_ca_id":295814,"issuer_name":"C=US, O=Let's Encrypt, CN=R10","common_name":"cloud.aibkurpark.de","name_value":"cloud.aibkurpark.de","id":17122421412,"entry_timestamp":"2025-02-09T15:23:02.809","not_before":"2025-02-09T14:24:32","not_after":"2025-05-10T14:24:31","serial_number":"0338963c04daad7c5c311c00a3b6c8999e36","result_count":2},{"issuer_ca_id":295814,"issuer_name":"C=US, O=Let's Encrypt, CN=R10","common_name":"cloud.aibkurpark.de","name_value":"cloud.aibkurpark.de","id":16635575756,"entry_timestamp":"2025-02-09T15:23:02.704","not_before":"2025-02-09T14:24:32","not_after":"2025-05-10T14:24:31","serial_number":"0338963c04daad7c5c311c00a3b6c8999e36","result_count":2},{"issuer_ca_id":183267,"issuer_name":"C=US, O=Let's Encrypt, CN=R3","common_name":"cloud.aibkurpark.de","name_value":"cloud.aibkurpark.de","id":11633733632,"entry_timestamp":"2024-01-03T19:39:23.66","not_before":"2024-01-03T18:39:23","not_after":"2024-04-02T18:39:22","serial_number":"040656c602c0e9460d045b95c5972319d195","result_count":2},{"issuer_ca_id":183267,"issuer_name":"C=US, O=Let's Encrypt, CN=R3","common_name":"cloud.aibkurpark.de","name_value":"cloud.aibkurpark.de","id":11610236633,"entry_timestamp":"2024-01-03T19:39:23.48","not_before":"2024-01-03T18:39:23","not_after":"2024-04-02T18:39:22","serial_number":"040656c602c0e9460d045b95c5972319d195","result_count":2},{"issuer_ca_id":183267,"issuer_name":"C=US, O=Let's Encrypt, CN=R3","common_name":"cloud.aibkurpark.de","name_value":"cloud.aibkurpark.de","id":10998276570,"entry_timestamp":"2023-11-04T20:08:52.9","not_before":"2023-11-04T19:08:52","not_after":"2024-02-02T19:08:51","serial_number":"03d6d33fb298a3b24e240893175dc0606f11","result_count":2},{"issuer_ca_id":183267,"issuer_name":"C=US, O=Let's Encrypt, CN=R3","common_name":"cloud.aibkurpark.de","name_value":"cloud.aibkurpark.de","id":10998275332,"entry_timestamp":"2023-11-04T20:08:52.78","not_before":"2023-11-04T19:08:52","not_after":"2024-02-02T19:08:51","serial_number":"03d6d33fb298a3b24e240893175dc0606f11","result_count":2}]}

View File

@@ -1 +0,0 @@
{"domain":"cloud.cc24.dev","first_cached":"2025-09-14T21:36:46.109884+00:00","last_upstream_query":"2025-09-14T21:36:46.109891+00:00","upstream_query_count":1,"certificates":[{"issuer_ca_id":295815,"issuer_name":"C=US, O=Let's Encrypt, CN=R11","common_name":"cloud.cc24.dev","name_value":"cloud.cc24.dev","id":20275852221,"entry_timestamp":"2025-08-12T00:08:47.671","not_before":"2025-08-11T23:10:16","not_after":"2025-11-09T23:10:15","serial_number":"0531b80da7039a455eb889201f8e62ba8cc9","result_count":2},{"issuer_ca_id":295815,"issuer_name":"C=US, O=Let's Encrypt, CN=R11","common_name":"cloud.cc24.dev","name_value":"cloud.cc24.dev","id":20275837420,"entry_timestamp":"2025-08-12T00:08:47.014","not_before":"2025-08-11T23:10:16","not_after":"2025-11-09T23:10:15","serial_number":"0531b80da7039a455eb889201f8e62ba8cc9","result_count":2},{"issuer_ca_id":295815,"issuer_name":"C=US, O=Let's Encrypt, CN=R11","common_name":"cloud.cc24.dev","name_value":"cloud.cc24.dev","id":18987132752,"entry_timestamp":"2025-06-13T00:06:00.445","not_before":"2025-06-12T23:07:30","not_after":"2025-09-10T23:07:29","serial_number":"066841f1e247045c3bb244d599955addbc66","result_count":2},{"issuer_ca_id":295815,"issuer_name":"C=US, O=Let's Encrypt, CN=R11","common_name":"cloud.cc24.dev","name_value":"cloud.cc24.dev","id":18987133145,"entry_timestamp":"2025-06-13T00:06:00.158","not_before":"2025-06-12T23:07:30","not_after":"2025-09-10T23:07:29","serial_number":"066841f1e247045c3bb244d599955addbc66","result_count":2},{"issuer_ca_id":295815,"issuer_name":"C=US, O=Let's Encrypt, CN=R11","common_name":"cloud.cc24.dev","name_value":"cloud.cc24.dev","id":17831462233,"entry_timestamp":"2025-04-14T00:17:56.109","not_before":"2025-04-13T23:19:24","not_after":"2025-07-12T23:19:23","serial_number":"051efd08e5e21db1fe47698ba7cb273c05b7","result_count":2},{"issuer_ca_id":295815,"issuer_name":"C=US, O=Let's Encrypt, CN=R11","common_name":"cloud.cc24.dev","name_value":"cloud.cc24.dev","id":17831396685,"entry_timestamp":"2025-04-14T00:17:54.708","not_before":"2025-04-13T23:19:24","not_after":"2025-07-12T23:19:23","serial_number":"051efd08e5e21db1fe47698ba7cb273c05b7","result_count":2},{"issuer_ca_id":295814,"issuer_name":"C=US, O=Let's Encrypt, CN=R10","common_name":"cloud.cc24.dev","name_value":"cloud.cc24.dev","id":17170810540,"entry_timestamp":"2025-02-13T00:02:07.841","not_before":"2025-02-12T23:03:37","not_after":"2025-05-13T23:03:36","serial_number":"03fe022033cd38b75215385397375a1a3741","result_count":2},{"issuer_ca_id":295814,"issuer_name":"C=US, O=Let's Encrypt, CN=R10","common_name":"cloud.cc24.dev","name_value":"cloud.cc24.dev","id":16704105434,"entry_timestamp":"2025-02-13T00:02:07.708","not_before":"2025-02-12T23:03:37","not_after":"2025-05-13T23:03:36","serial_number":"03fe022033cd38b75215385397375a1a3741","result_count":2},{"issuer_ca_id":295815,"issuer_name":"C=US, O=Let's Encrypt, CN=R11","common_name":"cloud.cc24.dev","name_value":"cloud.cc24.dev","id":17122390503,"entry_timestamp":"2025-02-09T15:21:20.386","not_before":"2025-02-09T14:22:49","not_after":"2025-05-10T14:22:48","serial_number":"031fcf4e1368ddbc276836806c2d3df6c376","result_count":2},{"issuer_ca_id":295815,"issuer_name":"C=US, O=Let's Encrypt, CN=R11","common_name":"cloud.cc24.dev","name_value":"cloud.cc24.dev","id":16635540435,"entry_timestamp":"2025-02-09T15:21:19.831","not_before":"2025-02-09T14:22:49","not_after":"2025-05-10T14:22:48","serial_number":"031fcf4e1368ddbc276836806c2d3df6c376","result_count":2}]}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -1 +0,0 @@
{"domain":"console.s3.cc24.dev","first_cached":"2025-09-14T21:33:25.149502+00:00","last_upstream_query":"2025-09-14T21:33:25.149505+00:00","upstream_query_count":1,"certificates":[{"issuer_ca_id":295819,"issuer_name":"C=US, O=Let's Encrypt, CN=E6","common_name":"console.s3.cc24.dev","name_value":"console.s3.cc24.dev","id":20287575466,"entry_timestamp":"2025-08-12T12:55:37.077","not_before":"2025-08-12T11:57:05","not_after":"2025-11-10T11:57:04","serial_number":"066bdfa83088f8d7e67284da94dd5d122ed6","result_count":2},{"issuer_ca_id":295819,"issuer_name":"C=US, O=Let's Encrypt, CN=E6","common_name":"console.s3.cc24.dev","name_value":"console.s3.cc24.dev","id":20287575457,"entry_timestamp":"2025-08-12T12:55:36.75","not_before":"2025-08-12T11:57:05","not_after":"2025-11-10T11:57:04","serial_number":"066bdfa83088f8d7e67284da94dd5d122ed6","result_count":2}]}

View File

@@ -1 +0,0 @@
{"domain":"coturn.mikoshi.de","first_cached":"2025-09-14T22:37:33.747891+00:00","last_upstream_query":"2025-09-15T15:40:16.119867+00:00","upstream_query_count":2,"certificates":[{"issuer_ca_id":295810,"issuer_name":"C=US, O=Let's Encrypt, CN=E5","common_name":"coturn.mikoshi.de","name_value":"coturn.mikoshi.de","id":19208664152,"entry_timestamp":"2025-06-23T18:46:24.952","not_before":"2025-06-23T17:47:50","not_after":"2025-09-21T17:47:49","serial_number":"06d2bfd2d049388cf81d75548de9029700a8","result_count":2},{"issuer_ca_id":295810,"issuer_name":"C=US, O=Let's Encrypt, CN=E5","common_name":"coturn.mikoshi.de","name_value":"coturn.mikoshi.de","id":19208662980,"entry_timestamp":"2025-06-23T18:46:20.96","not_before":"2025-06-23T17:47:50","not_after":"2025-09-21T17:47:49","serial_number":"06d2bfd2d049388cf81d75548de9029700a8","result_count":2},{"issuer_ca_id":295819,"issuer_name":"C=US, O=Let's Encrypt, CN=E6","common_name":"coturn.mikoshi.de","name_value":"coturn.mikoshi.de","id":17345025382,"entry_timestamp":"2025-03-23T14:41:31.643","not_before":"2025-03-23T13:43:01","not_after":"2025-06-21T13:43:00","serial_number":"06245dcee4d40047ccbe0b4eac028e25edbe","result_count":2},{"issuer_ca_id":295819,"issuer_name":"C=US, O=Let's Encrypt, CN=E6","common_name":"coturn.mikoshi.de","name_value":"coturn.mikoshi.de","id":17345311273,"entry_timestamp":"2025-03-23T14:41:31.261","not_before":"2025-03-23T13:43:01","not_after":"2025-06-21T13:43:00","serial_number":"06245dcee4d40047ccbe0b4eac028e25edbe","result_count":2}]}

View File

@@ -1 +0,0 @@
{"domain":"coturn.ms-it-services.de","first_cached":"2025-09-14T21:03:44.169328+00:00","last_upstream_query":"2025-09-15T19:08:39.390556+00:00","upstream_query_count":3,"certificates":[{"issuer_ca_id":295819,"issuer_name":"C=US, O=Let's Encrypt, CN=E6","common_name":"coturn.ms-it-services.de","name_value":"coturn.ms-it-services.de","id":14781803935,"entry_timestamp":"2024-10-03T09:53:12.473","not_before":"2024-10-03T08:54:42","not_after":"2025-01-01T08:54:41","serial_number":"0395c04e522a2715eebcb7fc4ffb3da1fdba","result_count":2},{"issuer_ca_id":295819,"issuer_name":"C=US, O=Let's Encrypt, CN=E6","common_name":"coturn.ms-it-services.de","name_value":"coturn.ms-it-services.de","id":14781794097,"entry_timestamp":"2024-10-03T09:53:12.142","not_before":"2024-10-03T08:54:42","not_after":"2025-01-01T08:54:41","serial_number":"0395c04e522a2715eebcb7fc4ffb3da1fdba","result_count":2},{"issuer_ca_id":295819,"issuer_name":"C=US, O=Let's Encrypt, CN=E6","common_name":"coturn.ms-it-services.de","name_value":"coturn.ms-it-services.de","id":14773518990,"entry_timestamp":"2024-10-02T19:20:49.687","not_before":"2024-10-02T18:22:19","not_after":"2024-12-31T18:22:18","serial_number":"04f26242ac1b2ac659ac2e19ae2522ce3274","result_count":2},{"issuer_ca_id":295819,"issuer_name":"C=US, O=Let's Encrypt, CN=E6","common_name":"coturn.ms-it-services.de","name_value":"coturn.ms-it-services.de","id":14773501988,"entry_timestamp":"2024-10-02T19:20:49.356","not_before":"2024-10-02T18:22:19","not_after":"2024-12-31T18:22:18","serial_number":"04f26242ac1b2ac659ac2e19ae2522ce3274","result_count":2}]}

View File

@@ -1 +0,0 @@
{"domain":"dd10032.kasserver.com","first_cached":"2025-09-15T11:49:39.835993+00:00","last_upstream_query":"2025-09-15T11:49:39.835996+00:00","upstream_query_count":1,"certificates":[{"issuer_ca_id":295810,"issuer_name":"C=US, O=Let's Encrypt, CN=E5","common_name":"wernertest.dd10032.kasserver.com","name_value":"wernertest.dd10032.kasserver.com\nwww.wernertest.dd10032.kasserver.com","id":19900983152,"entry_timestamp":"2025-07-25T15:08:27.328","not_before":"2025-07-25T14:09:55","not_after":"2025-10-23T14:09:54","serial_number":"053bbb3a5a38ad78a0298a2d7de184471db7","result_count":3},{"issuer_ca_id":295810,"issuer_name":"C=US, O=Let's Encrypt, CN=E5","common_name":"wernertest.dd10032.kasserver.com","name_value":"wernertest.dd10032.kasserver.com\nwww.wernertest.dd10032.kasserver.com","id":19900983133,"entry_timestamp":"2025-07-25T15:08:25.843","not_before":"2025-07-25T14:09:55","not_after":"2025-10-23T14:09:54","serial_number":"053bbb3a5a38ad78a0298a2d7de184471db7","result_count":3},{"issuer_ca_id":295819,"issuer_name":"C=US, O=Let's Encrypt, CN=E6","common_name":"wernertest.dd10032.kasserver.com","name_value":"wernertest.dd10032.kasserver.com\nwww.wernertest.dd10032.kasserver.com","id":18625008970,"entry_timestamp":"2025-05-26T02:06:09.384","not_before":"2025-05-26T01:07:39","not_after":"2025-08-24T01:07:38","serial_number":"05b1920c57feb37d80ab28e0a745fd4e5711","result_count":3},{"issuer_ca_id":295819,"issuer_name":"C=US, O=Let's Encrypt, CN=E6","common_name":"wernertest.dd10032.kasserver.com","name_value":"wernertest.dd10032.kasserver.com\nwww.wernertest.dd10032.kasserver.com","id":18625008687,"entry_timestamp":"2025-05-26T02:06:09.149","not_before":"2025-05-26T01:07:39","not_after":"2025-08-24T01:07:38","serial_number":"05b1920c57feb37d80ab28e0a745fd4e5711","result_count":3},{"issuer_ca_id":295810,"issuer_name":"C=US, O=Let's Encrypt, CN=E5","common_name":"wernertest.dd10032.kasserver.com","name_value":"wernertest.dd10032.kasserver.com\nwww.wernertest.dd10032.kasserver.com","id":17676635727,"entry_timestamp":"2025-03-18T15:24:41.197","not_before":"2025-03-18T14:26:10","not_after":"2025-06-16T14:26:09","serial_number":"05f4a3810f24e3916e04d2b092c864e92b04","result_count":3},{"issuer_ca_id":295810,"issuer_name":"C=US, O=Let's Encrypt, CN=E5","common_name":"wernertest.dd10032.kasserver.com","name_value":"wernertest.dd10032.kasserver.com\nwww.wernertest.dd10032.kasserver.com","id":17214728959,"entry_timestamp":"2025-03-18T15:24:40.996","not_before":"2025-03-18T14:26:10","not_after":"2025-06-16T14:26:09","serial_number":"05f4a3810f24e3916e04d2b092c864e92b04","result_count":3}]}

View File

@@ -1 +0,0 @@
{"domain":"dd15000.kasserver.com","first_cached":"2025-09-15T11:49:51.832307+00:00","last_upstream_query":"2025-09-15T11:49:51.832313+00:00","upstream_query_count":1,"certificates":[{"issuer_ca_id":16418,"issuer_name":"C=US, O=Let's Encrypt, CN=Let's Encrypt Authority X3","common_name":"litera.dd15000.kasserver.com","name_value":"litera.dd15000.kasserver.com\nwww.litera.dd15000.kasserver.com","id":17806830,"entry_timestamp":"2016-05-03T09:27:49.724","not_before":"2016-05-03T08:28:00","not_after":"2016-08-01T08:28:00","serial_number":"030cb7992941a2b2860858446a989170f2db","result_count":3}]}

View File

@@ -1 +0,0 @@
{"domain":"dd17120.kasserver.com","first_cached":"2025-09-15T11:50:52.134823+00:00","last_upstream_query":"2025-09-15T11:50:52.134826+00:00","upstream_query_count":1,"certificates":[{"issuer_ca_id":183267,"issuer_name":"C=US, O=Let's Encrypt, CN=R3","common_name":"letest.dd17120.kasserver.com","name_value":"letest.dd17120.kasserver.com\nwww.letest.dd17120.kasserver.com","id":3820560694,"entry_timestamp":"2020-12-23T15:35:32.403","not_before":"2020-12-23T14:35:32","not_after":"2021-03-23T14:35:32","serial_number":"04c92961dbb2d095ce5690f41ab75431abed","result_count":3},{"issuer_ca_id":183267,"issuer_name":"C=US, O=Let's Encrypt, CN=R3","common_name":"letest.dd17120.kasserver.com","name_value":"letest.dd17120.kasserver.com\nwww.letest.dd17120.kasserver.com","id":3820561611,"entry_timestamp":"2020-12-23T15:35:32.275","not_before":"2020-12-23T14:35:32","not_after":"2021-03-23T14:35:32","serial_number":"04c92961dbb2d095ce5690f41ab75431abed","result_count":3},{"issuer_ca_id":183267,"issuer_name":"C=US, O=Let's Encrypt, CN=R3","common_name":"letest.dd17120.kasserver.com","name_value":"letest.dd17120.kasserver.com\nwww.letest.dd17120.kasserver.com","id":3820541026,"entry_timestamp":"2020-12-23T15:29:20.032","not_before":"2020-12-23T14:29:19","not_after":"2021-03-23T14:29:19","serial_number":"03446bb8f1a87b4f0cb40fd1030125240eed","result_count":3},{"issuer_ca_id":183267,"issuer_name":"C=US, O=Let's Encrypt, CN=R3","common_name":"letest.dd17120.kasserver.com","name_value":"letest.dd17120.kasserver.com\nwww.letest.dd17120.kasserver.com","id":3820541140,"entry_timestamp":"2020-12-23T15:29:19.847","not_before":"2020-12-23T14:29:19","not_after":"2021-03-23T14:29:19","serial_number":"03446bb8f1a87b4f0cb40fd1030125240eed","result_count":3},{"issuer_ca_id":183267,"issuer_name":"C=US, O=Let's Encrypt, CN=R3","common_name":"letest.dd17120.kasserver.com","name_value":"letest.dd17120.kasserver.com\nwww.letest.dd17120.kasserver.com","id":3820538580,"entry_timestamp":"2020-12-23T15:28:46.532","not_before":"2020-12-23T14:28:46","not_after":"2021-03-23T14:28:46","serial_number":"03c3eb90d764b2c2a0ac04beed2e876f03e1","result_count":3},{"issuer_ca_id":183267,"issuer_name":"C=US, O=Let's Encrypt, CN=R3","common_name":"letest.dd17120.kasserver.com","name_value":"letest.dd17120.kasserver.com\nwww.letest.dd17120.kasserver.com","id":3820538531,"entry_timestamp":"2020-12-23T15:28:46.312","not_before":"2020-12-23T14:28:46","not_after":"2021-03-23T14:28:46","serial_number":"03c3eb90d764b2c2a0ac04beed2e876f03e1","result_count":3},{"issuer_ca_id":183267,"issuer_name":"C=US, O=Let's Encrypt, CN=R3","common_name":"letest.dd17120.kasserver.com","name_value":"letest.dd17120.kasserver.com\nwww.letest.dd17120.kasserver.com","id":3820537101,"entry_timestamp":"2020-12-23T15:28:12.742","not_before":"2020-12-23T14:28:12","not_after":"2021-03-23T14:28:12","serial_number":"034cd7432ae3dba0e76509de60666d58f1e4","result_count":3},{"issuer_ca_id":183267,"issuer_name":"C=US, O=Let's Encrypt, CN=R3","common_name":"letest.dd17120.kasserver.com","name_value":"letest.dd17120.kasserver.com\nwww.letest.dd17120.kasserver.com","id":3820537306,"entry_timestamp":"2020-12-23T15:28:12.459","not_before":"2020-12-23T14:28:12","not_after":"2021-03-23T14:28:12","serial_number":"034cd7432ae3dba0e76509de60666d58f1e4","result_count":3}]}

View File

@@ -1 +0,0 @@
{"domain":"dd18904.kasserver.com","first_cached":"2025-09-15T11:49:03.689534+00:00","last_upstream_query":"2025-09-15T11:49:03.689540+00:00","upstream_query_count":1,"certificates":[{"issuer_ca_id":183267,"issuer_name":"C=US, O=Let's Encrypt, CN=R3","common_name":"thomas.dd18904.kasserver.com","name_value":"thomas.dd18904.kasserver.com\nwww.thomas.dd18904.kasserver.com","id":6766495494,"entry_timestamp":"2022-05-20T07:44:34.589","not_before":"2022-05-20T06:44:34","not_after":"2022-08-18T06:44:33","serial_number":"046fc2606fb3d5e6438be8586ff20e296e8e","result_count":3},{"issuer_ca_id":183267,"issuer_name":"C=US, O=Let's Encrypt, CN=R3","common_name":"thomas.dd18904.kasserver.com","name_value":"thomas.dd18904.kasserver.com\nwww.thomas.dd18904.kasserver.com","id":6766489032,"entry_timestamp":"2022-05-20T07:44:34.335","not_before":"2022-05-20T06:44:34","not_after":"2022-08-18T06:44:33","serial_number":"046fc2606fb3d5e6438be8586ff20e296e8e","result_count":3},{"issuer_ca_id":183267,"issuer_name":"C=US, O=Let's Encrypt, CN=R3","common_name":"thomas.dd18904.kasserver.com","name_value":"thomas.dd18904.kasserver.com\nwww.thomas.dd18904.kasserver.com","id":6766485621,"entry_timestamp":"2022-05-20T07:42:24.52","not_before":"2022-05-20T06:42:24","not_after":"2022-08-18T06:42:23","serial_number":"03a52deebc041d7b6b4246ec8fc0455345a8","result_count":3},{"issuer_ca_id":183267,"issuer_name":"C=US, O=Let's Encrypt, CN=R3","common_name":"thomas.dd18904.kasserver.com","name_value":"thomas.dd18904.kasserver.com\nwww.thomas.dd18904.kasserver.com","id":6766485609,"entry_timestamp":"2022-05-20T07:42:24.413","not_before":"2022-05-20T06:42:24","not_after":"2022-08-18T06:42:23","serial_number":"03a52deebc041d7b6b4246ec8fc0455345a8","result_count":3}]}

View File

@@ -1 +0,0 @@
{"domain":"dd19536.kasserver.com","first_cached":"2025-09-15T11:47:57.902219+00:00","last_upstream_query":"2025-09-15T11:47:57.902224+00:00","upstream_query_count":1,"certificates":[{"issuer_ca_id":295815,"issuer_name":"C=US, O=Let's Encrypt, CN=R11","common_name":"login.jitsi.dd19536.kasserver.com","name_value":"login.jitsi.dd19536.kasserver.com\nwww.login.jitsi.dd19536.kasserver.com","id":14154546767,"entry_timestamp":"2024-08-12T05:52:06.917","not_before":"2024-08-12T04:53:36","not_after":"2024-11-10T04:53:35","serial_number":"04fca7ec58a44a09702875c5d2c6c9d6401b","result_count":3},{"issuer_ca_id":295815,"issuer_name":"C=US, O=Let's Encrypt, CN=R11","common_name":"login.jitsi.dd19536.kasserver.com","name_value":"login.jitsi.dd19536.kasserver.com\nwww.login.jitsi.dd19536.kasserver.com","id":14108590090,"entry_timestamp":"2024-08-12T05:52:06.531","not_before":"2024-08-12T04:53:36","not_after":"2024-11-10T04:53:35","serial_number":"04fca7ec58a44a09702875c5d2c6c9d6401b","result_count":3}]}

View File

@@ -1 +0,0 @@
{"domain":"dd24432.kasserver.com","first_cached":"2025-09-15T11:51:28.290098+00:00","last_upstream_query":"2025-09-15T11:51:28.290102+00:00","upstream_query_count":1,"certificates":[{"issuer_ca_id":16418,"issuer_name":"C=US, O=Let's Encrypt, CN=Let's Encrypt Authority X3","common_name":"test1.dd24432.kasserver.com","name_value":"test1.dd24432.kasserver.com\nwww.test1.dd24432.kasserver.com","id":157863863,"entry_timestamp":"2017-06-20T11:17:00.314","not_before":"2017-06-20T10:17:00","not_after":"2017-09-18T10:17:00","serial_number":"03c833715204594e6946b183652f0be2055e","result_count":3}]}

View File

@@ -1 +0,0 @@
{"domain":"dd27030.kasserver.com","first_cached":"2025-09-15T11:48:39.556778+00:00","last_upstream_query":"2025-09-15T11:48:39.556783+00:00","upstream_query_count":1,"certificates":[{"issuer_ca_id":295810,"issuer_name":"C=US, O=Let's Encrypt, CN=E5","common_name":"wernertest.dd27030.kasserver.com","name_value":"wernertest.dd27030.kasserver.com\nwww.wernertest.dd27030.kasserver.com","id":17324952949,"entry_timestamp":"2025-03-19T12:30:16.583","not_before":"2025-03-19T11:31:44","not_after":"2025-06-17T11:31:43","serial_number":"0686091c483d6c1a55f241d41c29523fc3f0","result_count":3},{"issuer_ca_id":295810,"issuer_name":"C=US, O=Let's Encrypt, CN=E5","common_name":"wernertest.dd27030.kasserver.com","name_value":"wernertest.dd27030.kasserver.com\nwww.wernertest.dd27030.kasserver.com","id":17314228622,"entry_timestamp":"2025-03-19T12:30:14.317","not_before":"2025-03-19T11:31:44","not_after":"2025-06-17T11:31:43","serial_number":"0686091c483d6c1a55f241d41c29523fc3f0","result_count":3}]}

View File

@@ -1 +0,0 @@
{"domain":"dd27120.kasserver.com","first_cached":"2025-09-15T11:47:51.800693+00:00","last_upstream_query":"2025-09-15T11:47:51.800697+00:00","upstream_query_count":1,"certificates":[{"issuer_ca_id":16418,"issuer_name":"C=US, O=Let's Encrypt, CN=Let's Encrypt Authority X3","common_name":"otrs2.dd27120.kasserver.com","name_value":"otrs2.dd27120.kasserver.com\nwww.otrs2.dd27120.kasserver.com","id":1476617768,"entry_timestamp":"2019-05-09T10:40:20.848","not_before":"2019-05-09T09:40:19","not_after":"2019-08-07T09:40:19","serial_number":"0342616d062ef6933a703e4de279da4e38b6","result_count":3},{"issuer_ca_id":16418,"issuer_name":"C=US, O=Let's Encrypt, CN=Let's Encrypt Authority X3","common_name":"otrs2.dd27120.kasserver.com","name_value":"otrs2.dd27120.kasserver.com\nwww.otrs2.dd27120.kasserver.com","id":1458597695,"entry_timestamp":"2019-05-09T10:40:20.006","not_before":"2019-05-09T09:40:19","not_after":"2019-08-07T09:40:19","serial_number":"0342616d062ef6933a703e4de279da4e38b6","result_count":3},{"issuer_ca_id":16418,"issuer_name":"C=US, O=Let's Encrypt, CN=Let's Encrypt Authority X3","common_name":"otrs2.dd27120.kasserver.com","name_value":"otrs2.dd27120.kasserver.com\nwww.otrs2.dd27120.kasserver.com","id":1476589088,"entry_timestamp":"2019-05-09T10:17:27.514","not_before":"2019-05-09T09:17:26","not_after":"2019-08-07T09:17:26","serial_number":"0398319827847d1df54260d7273cd5ea6d5c","result_count":3},{"issuer_ca_id":16418,"issuer_name":"C=US, O=Let's Encrypt, CN=Let's Encrypt Authority X3","common_name":"otrs2.dd27120.kasserver.com","name_value":"otrs2.dd27120.kasserver.com\nwww.otrs2.dd27120.kasserver.com","id":1457806572,"entry_timestamp":"2019-05-09T10:17:26.68","not_before":"2019-05-09T09:17:26","not_after":"2019-08-07T09:17:26","serial_number":"0398319827847d1df54260d7273cd5ea6d5c","result_count":3}]}

View File

@@ -1 +0,0 @@
{"domain":"dd27932.kasserver.com","first_cached":"2025-09-15T11:48:51.718464+00:00","last_upstream_query":"2025-09-15T11:48:51.718468+00:00","upstream_query_count":1,"certificates":[{"issuer_ca_id":16418,"issuer_name":"C=US, O=Let's Encrypt, CN=Let's Encrypt Authority X3","common_name":"switest.dd27932.kasserver.com","name_value":"switest.dd27932.kasserver.com\nwww.switest.dd27932.kasserver.com","id":99317583,"entry_timestamp":"2017-03-05T01:00:32.21","not_before":"2017-03-05T00:01:00","not_after":"2017-06-03T00:01:00","serial_number":"03e0f1fb8ff2a8a742ee45c2da39e4bd68ed","result_count":3},{"issuer_ca_id":16418,"issuer_name":"C=US, O=Let's Encrypt, CN=Let's Encrypt Authority X3","common_name":"switest.dd27932.kasserver.com","name_value":"switest.dd27932.kasserver.com\nwww.switest.dd27932.kasserver.com","id":69451932,"entry_timestamp":"2016-12-21T10:01:06.051","not_before":"2016-12-21T09:01:00","not_after":"2017-03-21T09:01:00","serial_number":"03a4f79d5ed3c6661f6f2c430a1a1546e0d8","result_count":3}]}

View File

@@ -1 +0,0 @@
{"domain":"dd28826.kasserver.com","first_cached":"2025-09-15T11:50:28.011163+00:00","last_upstream_query":"2025-09-15T11:50:28.011167+00:00","upstream_query_count":1,"certificates":[{"issuer_ca_id":16418,"issuer_name":"C=US, O=Let's Encrypt, CN=Let's Encrypt Authority X3","common_name":"161gs86116.dd28826.kasserver.com","name_value":"161gs86116.dd28826.kasserver.com\nwww.161gs86116.dd28826.kasserver.com","id":138535930,"entry_timestamp":"2017-05-15T11:15:13.509","not_before":"2017-05-15T10:15:00","not_after":"2017-08-13T10:15:00","serial_number":"03bca24f2de29889f514c04523a1f8945136","result_count":3},{"issuer_ca_id":16418,"issuer_name":"C=US, O=Let's Encrypt, CN=Let's Encrypt Authority X3","common_name":"161gs86116.dd28826.kasserver.com","name_value":"161gs86116.dd28826.kasserver.com\nwww.161gs86116.dd28826.kasserver.com","id":40903630,"entry_timestamp":"2016-10-07T12:00:36.009","not_before":"2016-10-07T11:01:00","not_after":"2017-01-05T11:01:00","serial_number":"0385d74f0a39572de61c2b7765c94d848c82","result_count":3},{"issuer_ca_id":16418,"issuer_name":"C=US, O=Let's Encrypt, CN=Let's Encrypt Authority X3","common_name":"161gs86116.dd28826.kasserver.com","name_value":"161gs86116.dd28826.kasserver.com\nwww.161gs86116.dd28826.kasserver.com","id":40901166,"entry_timestamp":"2016-10-07T11:54:34.702","not_before":"2016-10-07T10:55:00","not_after":"2017-01-05T10:55:00","serial_number":"039ef12598cb7aaf33c04d4c90983b0829fe","result_count":3}]}

File diff suppressed because one or more lines are too long

View File

@@ -1 +0,0 @@
{"domain":"dd39314.kasserver.com","first_cached":"2025-09-15T11:47:59.899335+00:00","last_upstream_query":"2025-09-15T11:47:59.899339+00:00","upstream_query_count":1,"certificates":[{"issuer_ca_id":16418,"issuer_name":"C=US, O=Let's Encrypt, CN=Let's Encrypt Authority X3","common_name":"http2.dd39314.kasserver.com","name_value":"http2.dd39314.kasserver.com\nwww.http2.dd39314.kasserver.com","id":35834556,"entry_timestamp":"2016-09-27T11:27:08.538","not_before":"2016-09-27T10:27:00","not_after":"2016-12-26T10:27:00","serial_number":"03024be246b9452e3e5e7dbed7e502a1ee16","result_count":3}]}

File diff suppressed because one or more lines are too long

View File

@@ -1 +0,0 @@
{"domain":"dd44624.kasserver.com","first_cached":"2025-09-15T11:50:16.030946+00:00","last_upstream_query":"2025-09-15T11:50:16.030952+00:00","upstream_query_count":1,"certificates":[{"issuer_ca_id":16418,"issuer_name":"C=US, O=Let's Encrypt, CN=Let's Encrypt Authority X3","common_name":"aitest.dd44624.kasserver.com","name_value":"aitest.dd44624.kasserver.com\nwww.aitest.dd44624.kasserver.com","id":2366400329,"entry_timestamp":"2020-01-21T09:28:49.996","not_before":"2020-01-21T08:28:49","not_after":"2020-04-20T08:28:49","serial_number":"0319ee129ecf09b2a08a98d6cd7d92062efe","result_count":3},{"issuer_ca_id":16418,"issuer_name":"C=US, O=Let's Encrypt, CN=Let's Encrypt Authority X3","common_name":"aitest.dd44624.kasserver.com","name_value":"aitest.dd44624.kasserver.com\nwww.aitest.dd44624.kasserver.com","id":2355073809,"entry_timestamp":"2020-01-21T09:28:49.389","not_before":"2020-01-21T08:28:49","not_after":"2020-04-20T08:28:49","serial_number":"0319ee129ecf09b2a08a98d6cd7d92062efe","result_count":3}]}

View File

@@ -1 +0,0 @@
{"domain":"dd46900.kasserver.com","first_cached":"2025-09-15T11:49:27.811675+00:00","last_upstream_query":"2025-09-15T11:49:27.811679+00:00","upstream_query_count":1,"certificates":[{"issuer_ca_id":295819,"issuer_name":"C=US, O=Let's Encrypt, CN=E6","common_name":"wernertest.dd46900.kasserver.com","name_value":"wernertest.dd46900.kasserver.com\nwww.wernertest.dd46900.kasserver.com","id":19891708696,"entry_timestamp":"2025-07-25T04:48:43.91","not_before":"2025-07-25T03:50:12","not_after":"2025-10-23T03:50:11","serial_number":"06ab9c27b7c779ee95cb82b66f985d87601c","result_count":3},{"issuer_ca_id":295819,"issuer_name":"C=US, O=Let's Encrypt, CN=E6","common_name":"wernertest.dd46900.kasserver.com","name_value":"wernertest.dd46900.kasserver.com\nwww.wernertest.dd46900.kasserver.com","id":19891706706,"entry_timestamp":"2025-07-25T04:48:42.387","not_before":"2025-07-25T03:50:12","not_after":"2025-10-23T03:50:11","serial_number":"06ab9c27b7c779ee95cb82b66f985d87601c","result_count":3},{"issuer_ca_id":295810,"issuer_name":"C=US, O=Let's Encrypt, CN=E5","common_name":"wernertest.dd46900.kasserver.com","name_value":"wernertest.dd46900.kasserver.com\nwww.wernertest.dd46900.kasserver.com","id":18618700336,"entry_timestamp":"2025-05-25T17:22:29.664","not_before":"2025-05-25T16:23:59","not_after":"2025-08-23T16:23:58","serial_number":"05abb39369b76694a079e1109a93e616bf18","result_count":3},{"issuer_ca_id":295810,"issuer_name":"C=US, O=Let's Encrypt, CN=E5","common_name":"wernertest.dd46900.kasserver.com","name_value":"wernertest.dd46900.kasserver.com\nwww.wernertest.dd46900.kasserver.com","id":18618704556,"entry_timestamp":"2025-05-25T17:22:29.449","not_before":"2025-05-25T16:23:59","not_after":"2025-08-23T16:23:58","serial_number":"05abb39369b76694a079e1109a93e616bf18","result_count":3},{"issuer_ca_id":295819,"issuer_name":"C=US, O=Let's Encrypt, CN=E6","common_name":"wernertest.dd46900.kasserver.com","name_value":"wernertest.dd46900.kasserver.com\nwww.wernertest.dd46900.kasserver.com","id":17676537327,"entry_timestamp":"2025-03-18T15:18:10.621","not_before":"2025-03-18T14:19:39","not_after":"2025-06-16T14:19:38","serial_number":"0610cb215ef16b2619af24f76349e349939c","result_count":3},{"issuer_ca_id":295819,"issuer_name":"C=US, O=Let's Encrypt, CN=E6","common_name":"wernertest.dd46900.kasserver.com","name_value":"wernertest.dd46900.kasserver.com\nwww.wernertest.dd46900.kasserver.com","id":17230420365,"entry_timestamp":"2025-03-18T15:18:09.941","not_before":"2025-03-18T14:19:39","not_after":"2025-06-16T14:19:38","serial_number":"0610cb215ef16b2619af24f76349e349939c","result_count":3}]}

View File

@@ -1 +0,0 @@
{"domain":"dd55600.kasserver.com","first_cached":"2025-09-15T11:47:55.878914+00:00","last_upstream_query":"2025-09-15T11:47:55.878918+00:00","upstream_query_count":1,"certificates":[{"issuer_ca_id":295819,"issuer_name":"C=US, O=Let's Encrypt, CN=E6","common_name":"letest.dd55600.kasserver.com","name_value":"letest.dd55600.kasserver.com\nwww.letest.dd55600.kasserver.com","id":20031222371,"entry_timestamp":"2025-07-31T13:43:52.442","not_before":"2025-07-31T12:45:20","not_after":"2025-10-29T12:45:19","serial_number":"06eb0a6229e52eabee01d67ad7a999665794","result_count":3},{"issuer_ca_id":295819,"issuer_name":"C=US, O=Let's Encrypt, CN=E6","common_name":"letest.dd55600.kasserver.com","name_value":"letest.dd55600.kasserver.com\nwww.letest.dd55600.kasserver.com","id":20031228125,"entry_timestamp":"2025-07-31T13:43:50.126","not_before":"2025-07-31T12:45:20","not_after":"2025-10-29T12:45:19","serial_number":"06eb0a6229e52eabee01d67ad7a999665794","result_count":3}]}

View File

@@ -1 +0,0 @@
{"domain":"deck0.mikoshi.de","first_cached":"2025-09-15T15:38:47.110406+00:00","last_upstream_query":"2025-09-15T15:38:47.110410+00:00","upstream_query_count":1,"certificates":[{"issuer_ca_id":295815,"issuer_name":"C=US, O=Let's Encrypt, CN=R11","common_name":"deck0.mikoshi.de","name_value":"deck0.mikoshi.de","id":20275849021,"entry_timestamp":"2025-08-12T00:08:09.613","not_before":"2025-08-11T23:09:39","not_after":"2025-11-09T23:09:38","serial_number":"05785ec3742887857667078bfa75b21eda78","result_count":2},{"issuer_ca_id":295815,"issuer_name":"C=US, O=Let's Encrypt, CN=R11","common_name":"deck0.mikoshi.de","name_value":"deck0.mikoshi.de","id":20275847401,"entry_timestamp":"2025-08-12T00:08:09.412","not_before":"2025-08-11T23:09:39","not_after":"2025-11-09T23:09:38","serial_number":"05785ec3742887857667078bfa75b21eda78","result_count":2},{"issuer_ca_id":295815,"issuer_name":"C=US, O=Let's Encrypt, CN=R11","common_name":"deck0.mikoshi.de","name_value":"deck0.mikoshi.de","id":18987122782,"entry_timestamp":"2025-06-13T00:05:25.356","not_before":"2025-06-12T23:06:50","not_after":"2025-09-10T23:06:49","serial_number":"051c77c6054cfd6720e600ff7f5a9a42b40f","result_count":2},{"issuer_ca_id":295815,"issuer_name":"C=US, O=Let's Encrypt, CN=R11","common_name":"deck0.mikoshi.de","name_value":"deck0.mikoshi.de","id":18987120711,"entry_timestamp":"2025-06-13T00:05:21.025","not_before":"2025-06-12T23:06:50","not_after":"2025-09-10T23:06:49","serial_number":"051c77c6054cfd6720e600ff7f5a9a42b40f","result_count":2},{"issuer_ca_id":295814,"issuer_name":"C=US, O=Let's Encrypt, CN=R10","common_name":"deck0.mikoshi.de","name_value":"deck0.mikoshi.de","id":17831463793,"entry_timestamp":"2025-04-14T00:17:17.936","not_before":"2025-04-13T23:18:47","not_after":"2025-07-12T23:18:46","serial_number":"0652fad83eb95b52eb2a47457872b0408fef","result_count":2},{"issuer_ca_id":295814,"issuer_name":"C=US, O=Let's Encrypt, CN=R10","common_name":"deck0.mikoshi.de","name_value":"deck0.mikoshi.de","id":17831393060,"entry_timestamp":"2025-04-14T00:17:17.692","not_before":"2025-04-13T23:18:47","not_after":"2025-07-12T23:18:46","serial_number":"0652fad83eb95b52eb2a47457872b0408fef","result_count":2},{"issuer_ca_id":295815,"issuer_name":"C=US, O=Let's Encrypt, CN=R11","common_name":"deck0.mikoshi.de","name_value":"deck0.mikoshi.de","id":16704809501,"entry_timestamp":"2025-02-13T00:02:01.475","not_before":"2025-02-12T23:03:29","not_after":"2025-05-13T23:03:28","serial_number":"03336511cc977e31ed4534ee782a8b856e03","result_count":2},{"issuer_ca_id":295815,"issuer_name":"C=US, O=Let's Encrypt, CN=R11","common_name":"deck0.mikoshi.de","name_value":"deck0.mikoshi.de","id":16704111156,"entry_timestamp":"2025-02-13T00:01:59.346","not_before":"2025-02-12T23:03:29","not_after":"2025-05-13T23:03:28","serial_number":"03336511cc977e31ed4534ee782a8b856e03","result_count":2},{"issuer_ca_id":295814,"issuer_name":"C=US, O=Let's Encrypt, CN=R10","common_name":"deck0.mikoshi.de","name_value":"deck0.mikoshi.de","id":17122385653,"entry_timestamp":"2025-02-09T15:20:45.345","not_before":"2025-02-09T14:22:14","not_after":"2025-05-10T14:22:13","serial_number":"04b3ee603f5f877a0acbb32ff5e68570fc4e","result_count":2},{"issuer_ca_id":295814,"issuer_name":"C=US, O=Let's Encrypt, CN=R10","common_name":"deck0.mikoshi.de","name_value":"deck0.mikoshi.de","id":16636455622,"entry_timestamp":"2025-02-09T15:20:45.058","not_before":"2025-02-09T14:22:14","not_after":"2025-05-10T14:22:13","serial_number":"04b3ee603f5f877a0acbb32ff5e68570fc4e","result_count":2}]}

View File

@@ -1 +0,0 @@
{"domain":"deck.mikoshi.de","first_cached":"2025-09-15T15:37:15.209223+00:00","last_upstream_query":"2025-09-15T15:37:15.209226+00:00","upstream_query_count":1,"certificates":[{"issuer_ca_id":295814,"issuer_name":"C=US, O=Let's Encrypt, CN=R10","common_name":"deck.mikoshi.de","name_value":"deck.mikoshi.de","id":20296619407,"entry_timestamp":"2025-08-13T00:04:28.809","not_before":"2025-08-12T23:05:56","not_after":"2025-11-10T23:05:55","serial_number":"068288286ab2af41b51f2a6f0e4c6d6343ed","result_count":2},{"issuer_ca_id":295814,"issuer_name":"C=US, O=Let's Encrypt, CN=R10","common_name":"deck.mikoshi.de","name_value":"deck.mikoshi.de","id":20296618002,"entry_timestamp":"2025-08-13T00:04:26.633","not_before":"2025-08-12T23:05:56","not_after":"2025-11-10T23:05:55","serial_number":"068288286ab2af41b51f2a6f0e4c6d6343ed","result_count":2},{"issuer_ca_id":295814,"issuer_name":"C=US, O=Let's Encrypt, CN=R10","common_name":"deck.mikoshi.de","name_value":"deck.mikoshi.de","id":19007501639,"entry_timestamp":"2025-06-14T00:02:02.957","not_before":"2025-06-13T23:03:32","not_after":"2025-09-11T23:03:31","serial_number":"065d212df70f76cc2d2e5fb1cd3372785d45","result_count":2},{"issuer_ca_id":295814,"issuer_name":"C=US, O=Let's Encrypt, CN=R10","common_name":"deck.mikoshi.de","name_value":"deck.mikoshi.de","id":19007529630,"entry_timestamp":"2025-06-14T00:02:02.71","not_before":"2025-06-13T23:03:32","not_after":"2025-09-11T23:03:31","serial_number":"065d212df70f76cc2d2e5fb1cd3372785d45","result_count":2},{"issuer_ca_id":295815,"issuer_name":"C=US, O=Let's Encrypt, CN=R11","common_name":"deck.mikoshi.de","name_value":"deck.mikoshi.de","id":17831396750,"entry_timestamp":"2025-04-14T00:16:41.797","not_before":"2025-04-13T23:18:10","not_after":"2025-07-12T23:18:09","serial_number":"063db5541056907cd7d1a6dd6b90337970cf","result_count":2},{"issuer_ca_id":295815,"issuer_name":"C=US, O=Let's Encrypt, CN=R11","common_name":"deck.mikoshi.de","name_value":"deck.mikoshi.de","id":17831377445,"entry_timestamp":"2025-04-14T00:16:41.02","not_before":"2025-04-13T23:18:10","not_after":"2025-07-12T23:18:09","serial_number":"063db5541056907cd7d1a6dd6b90337970cf","result_count":2},{"issuer_ca_id":295814,"issuer_name":"C=US, O=Let's Encrypt, CN=R10","common_name":"deck.mikoshi.de","name_value":"deck.mikoshi.de","id":16704809458,"entry_timestamp":"2025-02-13T00:01:53.117","not_before":"2025-02-12T23:03:22","not_after":"2025-05-13T23:03:21","serial_number":"04dd85a6d9cafec66b0b7ca3753191d347fa","result_count":2},{"issuer_ca_id":295814,"issuer_name":"C=US, O=Let's Encrypt, CN=R10","common_name":"deck.mikoshi.de","name_value":"deck.mikoshi.de","id":16704110323,"entry_timestamp":"2025-02-13T00:01:52.905","not_before":"2025-02-12T23:03:22","not_after":"2025-05-13T23:03:21","serial_number":"04dd85a6d9cafec66b0b7ca3753191d347fa","result_count":2},{"issuer_ca_id":295814,"issuer_name":"C=US, O=Let's Encrypt, CN=R10","common_name":"deck.mikoshi.de","name_value":"deck.mikoshi.de","id":16636696795,"entry_timestamp":"2025-02-09T15:20:11.318","not_before":"2025-02-09T14:21:40","not_after":"2025-05-10T14:21:39","serial_number":"043f12b3e0be22dd52133924bbb5c1ded954","result_count":2},{"issuer_ca_id":295814,"issuer_name":"C=US, O=Let's Encrypt, CN=R10","common_name":"deck.mikoshi.de","name_value":"deck.mikoshi.de","id":16635534286,"entry_timestamp":"2025-02-09T15:20:10.545","not_before":"2025-02-09T14:21:40","not_after":"2025-05-10T14:21:39","serial_number":"043f12b3e0be22dd52133924bbb5c1ded954","result_count":2}]}

View File

@@ -1 +0,0 @@
{"domain":"dev.mikoshi.de","first_cached":"2025-09-15T15:39:15.810886+00:00","last_upstream_query":"2025-09-15T15:39:15.810888+00:00","upstream_query_count":1,"certificates":[{"issuer_ca_id":295814,"issuer_name":"C=US, O=Let's Encrypt, CN=R10","common_name":"dev.mikoshi.de","name_value":"dev.mikoshi.de","id":20275786291,"entry_timestamp":"2025-08-12T00:05:23.212","not_before":"2025-08-11T23:06:52","not_after":"2025-11-09T23:06:51","serial_number":"062b3368dce240f65370e3fcf5b868f3cb16","result_count":2},{"issuer_ca_id":295814,"issuer_name":"C=US, O=Let's Encrypt, CN=R10","common_name":"dev.mikoshi.de","name_value":"dev.mikoshi.de","id":20275788995,"entry_timestamp":"2025-08-12T00:05:22.899","not_before":"2025-08-11T23:06:52","not_after":"2025-11-09T23:06:51","serial_number":"062b3368dce240f65370e3fcf5b868f3cb16","result_count":2},{"issuer_ca_id":295814,"issuer_name":"C=US, O=Let's Encrypt, CN=R10","common_name":"dev.mikoshi.de","name_value":"dev.mikoshi.de","id":18987037224,"entry_timestamp":"2025-06-13T00:03:00.049","not_before":"2025-06-12T23:04:25","not_after":"2025-09-10T23:04:24","serial_number":"05dac28fc29cc4ffa07ebb5d652b5d3c220d","result_count":2},{"issuer_ca_id":295814,"issuer_name":"C=US, O=Let's Encrypt, CN=R10","common_name":"dev.mikoshi.de","name_value":"dev.mikoshi.de","id":18987083431,"entry_timestamp":"2025-06-13T00:02:56.025","not_before":"2025-06-12T23:04:25","not_after":"2025-09-10T23:04:24","serial_number":"05dac28fc29cc4ffa07ebb5d652b5d3c220d","result_count":2},{"issuer_ca_id":295814,"issuer_name":"C=US, O=Let's Encrypt, CN=R10","common_name":"dev.mikoshi.de","name_value":"dev.mikoshi.de","id":17831380009,"entry_timestamp":"2025-04-14T00:13:37.609","not_before":"2025-04-13T23:15:06","not_after":"2025-07-12T23:15:05","serial_number":"05acf9ab2ed9a117ef386d05d6cfae3ed258","result_count":2},{"issuer_ca_id":295814,"issuer_name":"C=US, O=Let's Encrypt, CN=R10","common_name":"dev.mikoshi.de","name_value":"dev.mikoshi.de","id":17831368386,"entry_timestamp":"2025-04-14T00:13:36.704","not_before":"2025-04-13T23:15:06","not_after":"2025-07-12T23:15:05","serial_number":"05acf9ab2ed9a117ef386d05d6cfae3ed258","result_count":2},{"issuer_ca_id":295815,"issuer_name":"C=US, O=Let's Encrypt, CN=R11","common_name":"dev.mikoshi.de","name_value":"dev.mikoshi.de","id":17170799512,"entry_timestamp":"2025-02-13T00:01:03.867","not_before":"2025-02-12T23:02:33","not_after":"2025-05-13T23:02:32","serial_number":"04324a24cab88153022dd4a82cd03a1d5bec","result_count":2},{"issuer_ca_id":295815,"issuer_name":"C=US, O=Let's Encrypt, CN=R11","common_name":"dev.mikoshi.de","name_value":"dev.mikoshi.de","id":16705238915,"entry_timestamp":"2025-02-13T00:01:03.58","not_before":"2025-02-12T23:02:33","not_after":"2025-05-13T23:02:32","serial_number":"04324a24cab88153022dd4a82cd03a1d5bec","result_count":2},{"issuer_ca_id":295815,"issuer_name":"C=US, O=Let's Encrypt, CN=R11","common_name":"dev.mikoshi.de","name_value":"dev.mikoshi.de","id":16635493913,"entry_timestamp":"2025-02-09T15:16:09.908","not_before":"2025-02-09T14:17:39","not_after":"2025-05-10T14:17:38","serial_number":"03567895f69539097a4621b1b2f68c04f75c","result_count":2},{"issuer_ca_id":295815,"issuer_name":"C=US, O=Let's Encrypt, CN=R11","common_name":"dev.mikoshi.de","name_value":"dev.mikoshi.de","id":16635494768,"entry_timestamp":"2025-02-09T15:16:09.457","not_before":"2025-02-09T14:17:39","not_after":"2025-05-10T14:17:38","serial_number":"03567895f69539097a4621b1b2f68c04f75c","result_count":2}]}

View File

@@ -1 +0,0 @@
{"domain":"dnsrecon.cc24.dev","first_cached":"2025-09-14T21:33:58.773156+00:00","last_upstream_query":"2025-09-14T21:33:58.773159+00:00","upstream_query_count":1,"certificates":[{"issuer_ca_id":295809,"issuer_name":"C=US, O=Let's Encrypt, CN=E8","common_name":"dnsrecon.cc24.dev","name_value":"dnsrecon.cc24.dev","id":20965278266,"entry_timestamp":"2025-09-12T09:49:23.247","not_before":"2025-09-12T08:50:53","not_after":"2025-12-11T08:50:52","serial_number":"060fbe619a364febd85aebccb1c6fcf7153f","result_count":2},{"issuer_ca_id":295809,"issuer_name":"C=US, O=Let's Encrypt, CN=E8","common_name":"dnsrecon.cc24.dev","name_value":"dnsrecon.cc24.dev","id":20965277886,"entry_timestamp":"2025-09-12T09:49:23.039","not_before":"2025-09-12T08:50:53","not_after":"2025-12-11T08:50:52","serial_number":"060fbe619a364febd85aebccb1c6fcf7153f","result_count":2}]}

File diff suppressed because one or more lines are too long

View File

@@ -1 +0,0 @@
{"domain":"electrum.mikoshi.de","first_cached":"2025-09-15T15:35:50.844792+00:00","last_upstream_query":"2025-09-15T15:35:50.844796+00:00","upstream_query_count":1,"certificates":[{"issuer_ca_id":295815,"issuer_name":"C=US, O=Let's Encrypt, CN=R11","common_name":"electrum.mikoshi.de","name_value":"electrum.mikoshi.de","id":20275738086,"entry_timestamp":"2025-08-12T00:01:00.455","not_before":"2025-08-11T23:02:29","not_after":"2025-11-09T23:02:28","serial_number":"0607acd92d2e4ed2c21a0fd8879b4fcc1da6","result_count":2},{"issuer_ca_id":295815,"issuer_name":"C=US, O=Let's Encrypt, CN=R11","common_name":"electrum.mikoshi.de","name_value":"electrum.mikoshi.de","id":20275720683,"entry_timestamp":"2025-08-12T00:01:00.121","not_before":"2025-08-11T23:02:29","not_after":"2025-11-09T23:02:28","serial_number":"0607acd92d2e4ed2c21a0fd8879b4fcc1da6","result_count":2},{"issuer_ca_id":295814,"issuer_name":"C=US, O=Let's Encrypt, CN=R10","common_name":"electrum.mikoshi.de","name_value":"electrum.mikoshi.de","id":18987049091,"entry_timestamp":"2025-06-13T00:00:34.9","not_before":"2025-06-12T23:02:04","not_after":"2025-09-10T23:02:03","serial_number":"05b5b53d270451a0c1287c9aad800bf21a5b","result_count":2},{"issuer_ca_id":295814,"issuer_name":"C=US, O=Let's Encrypt, CN=R10","common_name":"electrum.mikoshi.de","name_value":"electrum.mikoshi.de","id":18987049255,"entry_timestamp":"2025-06-13T00:00:34.45","not_before":"2025-06-12T23:02:04","not_after":"2025-09-10T23:02:03","serial_number":"05b5b53d270451a0c1287c9aad800bf21a5b","result_count":2},{"issuer_ca_id":295814,"issuer_name":"C=US, O=Let's Encrypt, CN=R10","common_name":"electrum.mikoshi.de","name_value":"electrum.mikoshi.de","id":17831223577,"entry_timestamp":"2025-04-14T00:03:09.379","not_before":"2025-04-13T23:04:37","not_after":"2025-07-12T23:04:36","serial_number":"06f83ec1efdf5ec3387c8f241234448b1618","result_count":2},{"issuer_ca_id":295814,"issuer_name":"C=US, O=Let's Encrypt, CN=R10","common_name":"electrum.mikoshi.de","name_value":"electrum.mikoshi.de","id":17831306766,"entry_timestamp":"2025-04-14T00:03:07.489","not_before":"2025-04-13T23:04:37","not_after":"2025-07-12T23:04:36","serial_number":"06f83ec1efdf5ec3387c8f241234448b1618","result_count":2},{"issuer_ca_id":295815,"issuer_name":"C=US, O=Let's Encrypt, CN=R11","common_name":"electrum.mikoshi.de","name_value":"electrum.mikoshi.de","id":17170790341,"entry_timestamp":"2025-02-13T00:00:15.841","not_before":"2025-02-12T23:01:45","not_after":"2025-05-13T23:01:44","serial_number":"0400d022ec8e2ded90606b9276eef71a1664","result_count":2},{"issuer_ca_id":295815,"issuer_name":"C=US, O=Let's Encrypt, CN=R11","common_name":"electrum.mikoshi.de","name_value":"electrum.mikoshi.de","id":16704088726,"entry_timestamp":"2025-02-13T00:00:15.527","not_before":"2025-02-12T23:01:45","not_after":"2025-05-13T23:01:44","serial_number":"0400d022ec8e2ded90606b9276eef71a1664","result_count":2},{"issuer_ca_id":295814,"issuer_name":"C=US, O=Let's Encrypt, CN=R10","common_name":"electrum.mikoshi.de","name_value":"electrum.mikoshi.de","id":16635426761,"entry_timestamp":"2025-02-09T15:12:05.797","not_before":"2025-02-09T14:13:35","not_after":"2025-05-10T14:13:34","serial_number":"045de320229498cb69676d307ec9467fa83e","result_count":2},{"issuer_ca_id":295814,"issuer_name":"C=US, O=Let's Encrypt, CN=R10","common_name":"electrum.mikoshi.de","name_value":"electrum.mikoshi.de","id":16635425561,"entry_timestamp":"2025-02-09T15:12:05.539","not_before":"2025-02-09T14:13:35","not_after":"2025-05-10T14:13:34","serial_number":"045de320229498cb69676d307ec9467fa83e","result_count":2}]}

File diff suppressed because one or more lines are too long

View File

@@ -1 +0,0 @@
{"domain":"fleischkombinat-ost.de","first_cached":"2025-09-14T21:11:00.028593+00:00","last_upstream_query":"2025-09-15T09:15:04.796648+00:00","upstream_query_count":2,"certificates":[{"issuer_ca_id":295819,"issuer_name":"C=US, O=Let's Encrypt, CN=E6","common_name":"app.fleischkombinat-ost.de","name_value":"app.fleischkombinat-ost.de","id":19374493240,"entry_timestamp":"2025-07-01T14:09:36.354","not_before":"2025-07-01T13:11:00","not_after":"2025-09-29T13:10:59","serial_number":"0693231ff5e3212cabc2588e38b5d8337528","result_count":2},{"issuer_ca_id":295819,"issuer_name":"C=US, O=Let's Encrypt, CN=E6","common_name":"app.fleischkombinat-ost.de","name_value":"app.fleischkombinat-ost.de","id":19374489847,"entry_timestamp":"2025-07-01T14:09:30.117","not_before":"2025-07-01T13:11:00","not_after":"2025-09-29T13:10:59","serial_number":"0693231ff5e3212cabc2588e38b5d8337528","result_count":2},{"issuer_ca_id":295810,"issuer_name":"C=US, O=Let's Encrypt, CN=E5","common_name":"fleischkombinat-ost.de","name_value":"fleischkombinat-ost.de","id":19374378473,"entry_timestamp":"2025-07-01T14:01:50.593","not_before":"2025-07-01T13:03:20","not_after":"2025-09-29T13:03:19","serial_number":"06315dfed8c93d1497c26b21c448857b6f2c","result_count":2},{"issuer_ca_id":295810,"issuer_name":"C=US, O=Let's Encrypt, CN=E5","common_name":"fleischkombinat-ost.de","name_value":"fleischkombinat-ost.de","id":19374376791,"entry_timestamp":"2025-07-01T14:01:50.385","not_before":"2025-07-01T13:03:20","not_after":"2025-09-29T13:03:19","serial_number":"06315dfed8c93d1497c26b21c448857b6f2c","result_count":2},{"issuer_ca_id":158800,"issuer_name":"C=AT, O=ZeroSSL, CN=ZeroSSL RSA Domain Secure Site CA","common_name":"*.fleischkombinat-ost.de","name_value":"*.fleischkombinat-ost.de\nfleischkombinat-ost.de","id":19369530786,"entry_timestamp":"2025-07-01T09:12:02.496","not_before":"2025-07-01T00:00:00","not_after":"2025-09-29T23:59:59","serial_number":"07c51a2c164b3a6c5769b0e03a9f4085","result_count":3},{"issuer_ca_id":158800,"issuer_name":"C=AT, O=ZeroSSL, CN=ZeroSSL RSA Domain Secure Site CA","common_name":"*.fleischkombinat-ost.de","name_value":"*.fleischkombinat-ost.de\nfleischkombinat-ost.de","id":19369530780,"entry_timestamp":"2025-07-01T09:12:01.04","not_before":"2025-07-01T00:00:00","not_after":"2025-09-29T23:59:59","serial_number":"07c51a2c164b3a6c5769b0e03a9f4085","result_count":3}]}

File diff suppressed because one or more lines are too long

View File

@@ -1 +0,0 @@
{"domain":"forum.cc24.dev","first_cached":"2025-09-14T21:37:55.208070+00:00","last_upstream_query":"2025-09-14T21:37:55.208073+00:00","upstream_query_count":1,"certificates":[{"issuer_ca_id":295815,"issuer_name":"C=US, O=Let's Encrypt, CN=R11","common_name":"forum.cc24.dev","name_value":"forum.cc24.dev","id":20275855672,"entry_timestamp":"2025-08-12T00:09:25.872","not_before":"2025-08-11T23:10:53","not_after":"2025-11-09T23:10:52","serial_number":"05e7fa80df3e45a7ecec44d25dafad0904e5","result_count":2},{"issuer_ca_id":295815,"issuer_name":"C=US, O=Let's Encrypt, CN=R11","common_name":"forum.cc24.dev","name_value":"forum.cc24.dev","id":20275850214,"entry_timestamp":"2025-08-12T00:09:23.776","not_before":"2025-08-11T23:10:53","not_after":"2025-11-09T23:10:52","serial_number":"05e7fa80df3e45a7ecec44d25dafad0904e5","result_count":2},{"issuer_ca_id":295814,"issuer_name":"C=US, O=Let's Encrypt, CN=R10","common_name":"forum.cc24.dev","name_value":"forum.cc24.dev","id":18987146858,"entry_timestamp":"2025-06-13T00:06:40.302","not_before":"2025-06-12T23:08:03","not_after":"2025-09-10T23:08:02","serial_number":"055efe65125ee83f14545a2f5d99590e635f","result_count":2},{"issuer_ca_id":295814,"issuer_name":"C=US, O=Let's Encrypt, CN=R10","common_name":"forum.cc24.dev","name_value":"forum.cc24.dev","id":18987145127,"entry_timestamp":"2025-06-13T00:06:34.097","not_before":"2025-06-12T23:08:03","not_after":"2025-09-10T23:08:02","serial_number":"055efe65125ee83f14545a2f5d99590e635f","result_count":2},{"issuer_ca_id":295814,"issuer_name":"C=US, O=Let's Encrypt, CN=R10","common_name":"forum.cc24.dev","name_value":"forum.cc24.dev","id":17831472866,"entry_timestamp":"2025-04-14T00:18:33.004","not_before":"2025-04-13T23:20:02","not_after":"2025-07-12T23:20:01","serial_number":"064fefe879ff5e732ce6c6a63f1e911db568","result_count":2},{"issuer_ca_id":295814,"issuer_name":"C=US, O=Let's Encrypt, CN=R10","common_name":"forum.cc24.dev","name_value":"forum.cc24.dev","id":17831402949,"entry_timestamp":"2025-04-14T00:18:32.224","not_before":"2025-04-13T23:20:02","not_after":"2025-07-12T23:20:01","serial_number":"064fefe879ff5e732ce6c6a63f1e911db568","result_count":2},{"issuer_ca_id":295815,"issuer_name":"C=US, O=Let's Encrypt, CN=R11","common_name":"forum.cc24.dev","name_value":"forum.cc24.dev","id":17170813968,"entry_timestamp":"2025-02-13T00:02:16.332","not_before":"2025-02-12T23:03:44","not_after":"2025-05-13T23:03:43","serial_number":"036e8e11288b54228648cab399477ea43c56","result_count":2},{"issuer_ca_id":295815,"issuer_name":"C=US, O=Let's Encrypt, CN=R11","common_name":"forum.cc24.dev","name_value":"forum.cc24.dev","id":16705244862,"entry_timestamp":"2025-02-13T00:02:14.119","not_before":"2025-02-12T23:03:44","not_after":"2025-05-13T23:03:43","serial_number":"036e8e11288b54228648cab399477ea43c56","result_count":2},{"issuer_ca_id":295815,"issuer_name":"C=US, O=Let's Encrypt, CN=R11","common_name":"forum.cc24.dev","name_value":"forum.cc24.dev","id":17122401304,"entry_timestamp":"2025-02-09T15:21:53.869","not_before":"2025-02-09T14:23:23","not_after":"2025-05-10T14:23:22","serial_number":"03e0928358e7636b3cc59a7dbc3b188bd7ca","result_count":2},{"issuer_ca_id":295815,"issuer_name":"C=US, O=Let's Encrypt, CN=R11","common_name":"forum.cc24.dev","name_value":"forum.cc24.dev","id":16636457115,"entry_timestamp":"2025-02-09T15:21:53.738","not_before":"2025-02-09T14:23:23","not_after":"2025-05-10T14:23:22","serial_number":"03e0928358e7636b3cc59a7dbc3b188bd7ca","result_count":2}]}

File diff suppressed because one or more lines are too long

View File

@@ -1 +0,0 @@
{"domain":"git.mikoshi.de","first_cached":"2025-09-14T22:41:53.620008+00:00","last_upstream_query":"2025-09-15T15:34:53.671880+00:00","upstream_query_count":2,"certificates":[{"issuer_ca_id":295817,"issuer_name":"C=US, O=Let's Encrypt, CN=R13","common_name":"git.mikoshi.de","name_value":"git.mikoshi.de","id":20885174925,"entry_timestamp":"2025-09-09T00:00:36.192","not_before":"2025-09-08T23:02:04","not_after":"2025-12-07T23:02:03","serial_number":"0615e6baefd21c126c2cdddf6dcb2507d56f","result_count":2},{"issuer_ca_id":295817,"issuer_name":"C=US, O=Let's Encrypt, CN=R13","common_name":"git.mikoshi.de","name_value":"git.mikoshi.de","id":20885174361,"entry_timestamp":"2025-09-09T00:00:34.086","not_before":"2025-09-08T23:02:04","not_after":"2025-12-07T23:02:03","serial_number":"0615e6baefd21c126c2cdddf6dcb2507d56f","result_count":2},{"issuer_ca_id":295814,"issuer_name":"C=US, O=Let's Encrypt, CN=R10","common_name":"git.mikoshi.de","name_value":"git.mikoshi.de","id":19559742374,"entry_timestamp":"2025-07-10T00:00:34.37","not_before":"2025-07-09T23:02:04","not_after":"2025-10-07T23:02:03","serial_number":"06d9b4e5782769647aa336db245fff31f620","result_count":2},{"issuer_ca_id":295814,"issuer_name":"C=US, O=Let's Encrypt, CN=R10","common_name":"git.mikoshi.de","name_value":"git.mikoshi.de","id":19559742305,"entry_timestamp":"2025-07-10T00:00:34.165","not_before":"2025-07-09T23:02:04","not_after":"2025-10-07T23:02:03","serial_number":"06d9b4e5782769647aa336db245fff31f620","result_count":2},{"issuer_ca_id":295815,"issuer_name":"C=US, O=Let's Encrypt, CN=R11","common_name":"git.mikoshi.de","name_value":"git.mikoshi.de","id":18325953073,"entry_timestamp":"2025-05-10T12:59:59.883","not_before":"2025-05-10T12:01:29","not_after":"2025-08-08T12:01:28","serial_number":"06b8ea37731e6560b6c67edbefbacfd4105c","result_count":2},{"issuer_ca_id":295815,"issuer_name":"C=US, O=Let's Encrypt, CN=R11","common_name":"git.mikoshi.de","name_value":"git.mikoshi.de","id":18325952875,"entry_timestamp":"2025-05-10T12:59:59.504","not_before":"2025-05-10T12:01:29","not_after":"2025-08-08T12:01:28","serial_number":"06b8ea37731e6560b6c67edbefbacfd4105c","result_count":2},{"issuer_ca_id":295815,"issuer_name":"C=US, O=Let's Encrypt, CN=R11","common_name":"git.mikoshi.de","name_value":"git.mikoshi.de","id":17831317349,"entry_timestamp":"2025-04-14T00:13:00.421","not_before":"2025-04-13T23:14:28","not_after":"2025-07-12T23:14:27","serial_number":"056bf6f5e9efb81381e56fbd6e28c32f4f90","result_count":2},{"issuer_ca_id":295815,"issuer_name":"C=US, O=Let's Encrypt, CN=R11","common_name":"git.mikoshi.de","name_value":"git.mikoshi.de","id":17831304428,"entry_timestamp":"2025-04-14T00:12:58.339","not_before":"2025-04-13T23:14:28","not_after":"2025-07-12T23:14:27","serial_number":"056bf6f5e9efb81381e56fbd6e28c32f4f90","result_count":2},{"issuer_ca_id":295815,"issuer_name":"C=US, O=Let's Encrypt, CN=R11","common_name":"git.mikoshi.de","name_value":"git.mikoshi.de","id":17170797746,"entry_timestamp":"2025-02-13T00:00:56.931","not_before":"2025-02-12T23:02:26","not_after":"2025-05-13T23:02:25","serial_number":"03b7b4c4c6233e74e3ad23a7bb2e455fcc3f","result_count":2},{"issuer_ca_id":295815,"issuer_name":"C=US, O=Let's Encrypt, CN=R11","common_name":"git.mikoshi.de","name_value":"git.mikoshi.de","id":16705238631,"entry_timestamp":"2025-02-13T00:00:56.689","not_before":"2025-02-12T23:02:26","not_after":"2025-05-13T23:02:25","serial_number":"03b7b4c4c6233e74e3ad23a7bb2e455fcc3f","result_count":2},{"issuer_ca_id":295814,"issuer_name":"C=US, O=Let's Encrypt, CN=R10","common_name":"git.mikoshi.de","name_value":"git.mikoshi.de","id":17122277510,"entry_timestamp":"2025-02-09T15:15:36.076","not_before":"2025-02-09T14:17:05","not_after":"2025-05-10T14:17:04","serial_number":"0404f208620f990403046876d32991e8f320","result_count":2},{"issuer_ca_id":295814,"issuer_name":"C=US, O=Let's Encrypt, CN=R10","common_name":"git.mikoshi.de","name_value":"git.mikoshi.de","id":16635498764,"entry_timestamp":"2025-02-09T15:15:35.493","not_before":"2025-02-09T14:17:05","not_after":"2025-05-10T14:17:04","serial_number":"0404f208620f990403046876d32991e8f320","result_count":2}]}

File diff suppressed because one or more lines are too long

View File

@@ -1 +0,0 @@
{"domain":"hoarder.cc24.dev","first_cached":"2025-09-14T21:33:21.961821+00:00","last_upstream_query":"2025-09-14T21:33:21.961824+00:00","upstream_query_count":1,"certificates":[{"issuer_ca_id":295814,"issuer_name":"C=US, O=Let's Encrypt, CN=R10","common_name":"hoarder.cc24.dev","name_value":"hoarder.cc24.dev","id":17651896110,"entry_timestamp":"2025-04-03T19:39:13.874","not_before":"2025-04-03T18:40:43","not_after":"2025-07-02T18:40:42","serial_number":"062e2d17ef9c31ca560ab40299e0e00701c0","result_count":2},{"issuer_ca_id":295814,"issuer_name":"C=US, O=Let's Encrypt, CN=R10","common_name":"hoarder.cc24.dev","name_value":"hoarder.cc24.dev","id":17610697718,"entry_timestamp":"2025-04-03T19:39:13.522","not_before":"2025-04-03T18:40:43","not_after":"2025-07-02T18:40:42","serial_number":"062e2d17ef9c31ca560ab40299e0e00701c0","result_count":2}]}

View File

@@ -1 +0,0 @@
{"domain":"hub.cc24.dev","first_cached":"2025-09-14T21:33:48.364903+00:00","last_upstream_query":"2025-09-14T21:33:48.364908+00:00","upstream_query_count":1,"certificates":[{"issuer_ca_id":295810,"issuer_name":"C=US, O=Let's Encrypt, CN=E5","common_name":"hub.cc24.dev","name_value":"hub.cc24.dev","id":20317572962,"entry_timestamp":"2025-08-14T00:02:25.791","not_before":"2025-08-13T23:03:55","not_after":"2025-11-11T23:03:54","serial_number":"05ee38e8ae7bff4c5c414784e2c64d933b7a","result_count":2},{"issuer_ca_id":295810,"issuer_name":"C=US, O=Let's Encrypt, CN=E5","common_name":"hub.cc24.dev","name_value":"hub.cc24.dev","id":20317572564,"entry_timestamp":"2025-08-14T00:02:25.581","not_before":"2025-08-13T23:03:55","not_after":"2025-11-11T23:03:54","serial_number":"05ee38e8ae7bff4c5c414784e2c64d933b7a","result_count":2},{"issuer_ca_id":295819,"issuer_name":"C=US, O=Let's Encrypt, CN=E6","common_name":"hub.cc24.dev","name_value":"hub.cc24.dev","id":20189230503,"entry_timestamp":"2025-08-08T00:05:51.4","not_before":"2025-08-07T23:07:21","not_after":"2025-11-05T23:07:20","serial_number":"0502ddbfff49d3df12f3a15ba33ad895ccf1","result_count":2},{"issuer_ca_id":295819,"issuer_name":"C=US, O=Let's Encrypt, CN=E6","common_name":"hub.cc24.dev","name_value":"hub.cc24.dev","id":20189230585,"entry_timestamp":"2025-08-08T00:05:51.234","not_before":"2025-08-07T23:07:21","not_after":"2025-11-05T23:07:20","serial_number":"0502ddbfff49d3df12f3a15ba33ad895ccf1","result_count":2},{"issuer_ca_id":295819,"issuer_name":"C=US, O=Let's Encrypt, CN=E6","common_name":"hub.cc24.dev","name_value":"hub.cc24.dev","id":20060643580,"entry_timestamp":"2025-08-02T00:02:15.895","not_before":"2025-08-01T23:03:45","not_after":"2025-10-30T23:03:44","serial_number":"05c750b95573daa27e1a55a8803a2e6d21ad","result_count":2},{"issuer_ca_id":295819,"issuer_name":"C=US, O=Let's Encrypt, CN=E6","common_name":"hub.cc24.dev","name_value":"hub.cc24.dev","id":20060643807,"entry_timestamp":"2025-08-02T00:02:15.683","not_before":"2025-08-01T23:03:45","not_after":"2025-10-30T23:03:44","serial_number":"05c750b95573daa27e1a55a8803a2e6d21ad","result_count":2},{"issuer_ca_id":295819,"issuer_name":"C=US, O=Let's Encrypt, CN=E6","common_name":"hub.cc24.dev","name_value":"hub.cc24.dev","id":19929376671,"entry_timestamp":"2025-07-27T00:02:55.144","not_before":"2025-07-26T23:04:22","not_after":"2025-10-24T23:04:21","serial_number":"052c4fe632cf76d0306310cfb9faecc224ba","result_count":2},{"issuer_ca_id":295819,"issuer_name":"C=US, O=Let's Encrypt, CN=E6","common_name":"hub.cc24.dev","name_value":"hub.cc24.dev","id":19929375724,"entry_timestamp":"2025-07-27T00:02:52.759","not_before":"2025-07-26T23:04:22","not_after":"2025-10-24T23:04:21","serial_number":"052c4fe632cf76d0306310cfb9faecc224ba","result_count":2},{"issuer_ca_id":295819,"issuer_name":"C=US, O=Let's Encrypt, CN=E6","common_name":"hub.cc24.dev","name_value":"hub.cc24.dev","id":19803769083,"entry_timestamp":"2025-07-21T00:01:15.171","not_before":"2025-07-20T23:02:40","not_after":"2025-10-18T23:02:39","serial_number":"05e9927e9ea80c233e8a9502f11e4958cd06","result_count":2},{"issuer_ca_id":295819,"issuer_name":"C=US, O=Let's Encrypt, CN=E6","common_name":"hub.cc24.dev","name_value":"hub.cc24.dev","id":19803778513,"entry_timestamp":"2025-07-21T00:01:10.987","not_before":"2025-07-20T23:02:40","not_after":"2025-10-18T23:02:39","serial_number":"05e9927e9ea80c233e8a9502f11e4958cd06","result_count":2},{"issuer_ca_id":295810,"issuer_name":"C=US, O=Let's Encrypt, CN=E5","common_name":"hub.cc24.dev","name_value":"hub.cc24.dev","id":19665369127,"entry_timestamp":"2025-07-14T21:15:11.092","not_before":"2025-07-14T20:16:38","not_after":"2025-10-12T20:16:37","serial_number":"069e06aa4855496ab6b766889d6b45135d4e","result_count":2},{"issuer_ca_id":295810,"issuer_name":"C=US, O=Let's Encrypt, CN=E5","common_name":"hub.cc24.dev","name_value":"hub.cc24.dev","id":19665373526,"entry_timestamp":"2025-07-14T21:15:08.866","not_before":"2025-07-14T20:16:38","not_after":"2025-10-12T20:16:37","serial_number":"069e06aa4855496ab6b766889d6b45135d4e","result_count":2}]}

View File

@@ -1 +0,0 @@
{"domain":"ip.mikoshi.de","first_cached":"2025-09-15T15:35:38.687945+00:00","last_upstream_query":"2025-09-15T15:35:38.687948+00:00","upstream_query_count":1,"certificates":[{"issuer_ca_id":295815,"issuer_name":"C=US, O=Let's Encrypt, CN=R11","common_name":"ip.mikoshi.de","name_value":"ip.mikoshi.de","id":20275799673,"entry_timestamp":"2025-08-12T00:06:09.895","not_before":"2025-08-11T23:07:39","not_after":"2025-11-09T23:07:38","serial_number":"05abe97c54f28c570ed093f2c2064d2bd909","result_count":2},{"issuer_ca_id":295815,"issuer_name":"C=US, O=Let's Encrypt, CN=R11","common_name":"ip.mikoshi.de","name_value":"ip.mikoshi.de","id":20275798755,"entry_timestamp":"2025-08-12T00:06:09.726","not_before":"2025-08-11T23:07:39","not_after":"2025-11-09T23:07:38","serial_number":"05abe97c54f28c570ed093f2c2064d2bd909","result_count":2},{"issuer_ca_id":295814,"issuer_name":"C=US, O=Let's Encrypt, CN=R10","common_name":"ip.mikoshi.de","name_value":"ip.mikoshi.de","id":18987090979,"entry_timestamp":"2025-06-13T00:03:33.968","not_before":"2025-06-12T23:05:03","not_after":"2025-09-10T23:05:02","serial_number":"05861ba42c1b941a781e56836a1286805486","result_count":2},{"issuer_ca_id":295814,"issuer_name":"C=US, O=Let's Encrypt, CN=R10","common_name":"ip.mikoshi.de","name_value":"ip.mikoshi.de","id":18987090443,"entry_timestamp":"2025-06-13T00:03:33.547","not_before":"2025-06-12T23:05:03","not_after":"2025-09-10T23:05:02","serial_number":"05861ba42c1b941a781e56836a1286805486","result_count":2},{"issuer_ca_id":295814,"issuer_name":"C=US, O=Let's Encrypt, CN=R10","common_name":"ip.mikoshi.de","name_value":"ip.mikoshi.de","id":17831378289,"entry_timestamp":"2025-04-14T00:14:14.055","not_before":"2025-04-13T23:15:43","not_after":"2025-07-12T23:15:42","serial_number":"05e8a5d6c84779035ff19c804b3eb98d997a","result_count":2},{"issuer_ca_id":295814,"issuer_name":"C=US, O=Let's Encrypt, CN=R10","common_name":"ip.mikoshi.de","name_value":"ip.mikoshi.de","id":17831323161,"entry_timestamp":"2025-04-14T00:14:13.821","not_before":"2025-04-13T23:15:43","not_after":"2025-07-12T23:15:42","serial_number":"05e8a5d6c84779035ff19c804b3eb98d997a","result_count":2},{"issuer_ca_id":295814,"issuer_name":"C=US, O=Let's Encrypt, CN=R10","common_name":"ip.mikoshi.de","name_value":"ip.mikoshi.de","id":17170801048,"entry_timestamp":"2025-02-13T00:01:10.43","not_before":"2025-02-12T23:02:40","not_after":"2025-05-13T23:02:39","serial_number":"03af85f30dcc4dbca816456437ccc8760356","result_count":2},{"issuer_ca_id":295814,"issuer_name":"C=US, O=Let's Encrypt, CN=R10","common_name":"ip.mikoshi.de","name_value":"ip.mikoshi.de","id":16704107826,"entry_timestamp":"2025-02-13T00:01:10.264","not_before":"2025-02-12T23:02:40","not_after":"2025-05-13T23:02:39","serial_number":"03af85f30dcc4dbca816456437ccc8760356","result_count":2},{"issuer_ca_id":295814,"issuer_name":"C=US, O=Let's Encrypt, CN=R10","common_name":"ip.mikoshi.de","name_value":"ip.mikoshi.de","id":17122289078,"entry_timestamp":"2025-02-09T15:16:43.147","not_before":"2025-02-09T14:18:12","not_after":"2025-05-10T14:18:11","serial_number":"03ef24688a55744de221b025bac45c4898c5","result_count":2},{"issuer_ca_id":295814,"issuer_name":"C=US, O=Let's Encrypt, CN=R10","common_name":"ip.mikoshi.de","name_value":"ip.mikoshi.de","id":16635485733,"entry_timestamp":"2025-02-09T15:16:43.019","not_before":"2025-02-09T14:18:12","not_after":"2025-05-10T14:18:11","serial_number":"03ef24688a55744de221b025bac45c4898c5","result_count":2}]}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -1 +0,0 @@
{"domain":"kvmtest2.kasserver.com","first_cached":"2025-09-15T11:48:15.510962+00:00","last_upstream_query":"2025-09-15T11:48:15.510965+00:00","upstream_query_count":1,"certificates":[{"issuer_ca_id":183267,"issuer_name":"C=US, O=Let's Encrypt, CN=R3","common_name":"nextcloud.kvmtest2.kasserver.com","name_value":"nextcloud.kvmtest2.kasserver.com\nwww.nextcloud.kvmtest2.kasserver.com","id":11872742578,"entry_timestamp":"2024-01-26T08:07:49.508","not_before":"2024-01-26T07:07:49","not_after":"2024-04-25T07:07:48","serial_number":"033a4ebc78836fabf49336d55237d61606b1","result_count":3},{"issuer_ca_id":183267,"issuer_name":"C=US, O=Let's Encrypt, CN=R3","common_name":"nextcloud.kvmtest2.kasserver.com","name_value":"nextcloud.kvmtest2.kasserver.com\nwww.nextcloud.kvmtest2.kasserver.com","id":11872748114,"entry_timestamp":"2024-01-26T08:07:49.316","not_before":"2024-01-26T07:07:49","not_after":"2024-04-25T07:07:48","serial_number":"033a4ebc78836fabf49336d55237d61606b1","result_count":3},{"issuer_ca_id":183267,"issuer_name":"C=US, O=Let's Encrypt, CN=R3","common_name":"nextcloud.kvmtest2.kasserver.com","name_value":"nextcloud.kvmtest2.kasserver.com\nwww.nextcloud.kvmtest2.kasserver.com","id":11867647719,"entry_timestamp":"2024-01-25T21:52:18.981","not_before":"2024-01-25T20:52:18","not_after":"2024-04-24T20:52:17","serial_number":"03e7aa261a2cd46d7de1f7a140b4a798eb21","result_count":3},{"issuer_ca_id":183267,"issuer_name":"C=US, O=Let's Encrypt, CN=R3","common_name":"nextcloud.kvmtest2.kasserver.com","name_value":"nextcloud.kvmtest2.kasserver.com\nwww.nextcloud.kvmtest2.kasserver.com","id":11867647704,"entry_timestamp":"2024-01-25T21:52:18.671","not_before":"2024-01-25T20:52:18","not_after":"2024-04-24T20:52:17","serial_number":"03e7aa261a2cd46d7de1f7a140b4a798eb21","result_count":3},{"issuer_ca_id":183267,"issuer_name":"C=US, O=Let's Encrypt, CN=R3","common_name":"nextcloud.kvmtest2.kasserver.com","name_value":"nextcloud.kvmtest2.kasserver.com\nwww.nextcloud.kvmtest2.kasserver.com","id":11864252076,"entry_timestamp":"2024-01-25T14:44:38.589","not_before":"2024-01-25T13:44:38","not_after":"2024-04-24T13:44:37","serial_number":"03542eac1a93d9a614ab26535b70ea26a6a5","result_count":3},{"issuer_ca_id":183267,"issuer_name":"C=US, O=Let's Encrypt, CN=R3","common_name":"nextcloud.kvmtest2.kasserver.com","name_value":"nextcloud.kvmtest2.kasserver.com\nwww.nextcloud.kvmtest2.kasserver.com","id":11864248841,"entry_timestamp":"2024-01-25T14:44:38.505","not_before":"2024-01-25T13:44:38","not_after":"2024-04-24T13:44:37","serial_number":"03542eac1a93d9a614ab26535b70ea26a6a5","result_count":3},{"issuer_ca_id":183267,"issuer_name":"C=US, O=Let's Encrypt, CN=R3","common_name":"nextcloud.kvmtest2.kasserver.com","name_value":"nextcloud.kvmtest2.kasserver.com\nwww.nextcloud.kvmtest2.kasserver.com","id":11853852174,"entry_timestamp":"2024-01-24T14:39:08.051","not_before":"2024-01-24T13:39:06","not_after":"2024-04-23T13:39:05","serial_number":"047335e6361f4c5477b088ff8cd2719d4d9a","result_count":3},{"issuer_ca_id":183267,"issuer_name":"C=US, O=Let's Encrypt, CN=R3","common_name":"nextcloud.kvmtest2.kasserver.com","name_value":"nextcloud.kvmtest2.kasserver.com\nwww.nextcloud.kvmtest2.kasserver.com","id":11853852409,"entry_timestamp":"2024-01-24T14:39:07.46","not_before":"2024-01-24T13:39:06","not_after":"2024-04-23T13:39:05","serial_number":"047335e6361f4c5477b088ff8cd2719d4d9a","result_count":3}]}

View File

@@ -1 +0,0 @@
{"domain":"kvmthkr.kasserver.com","first_cached":"2025-09-15T11:50:03.952251+00:00","last_upstream_query":"2025-09-15T11:50:03.952256+00:00","upstream_query_count":1,"certificates":[{"issuer_ca_id":105484,"issuer_name":"C=GB, ST=Greater Manchester, L=Salford, O=Sectigo Limited, CN=Sectigo ECC Domain Validation Secure Server CA","common_name":"ec.kvmthkr.kasserver.com","name_value":"ec.kvmthkr.kasserver.com\nwww.ec.kvmthkr.kasserver.com","id":14939726486,"entry_timestamp":"2024-10-15T07:02:39.33","not_before":"2024-10-15T00:00:00","not_after":"2024-11-14T23:59:59","serial_number":"6827c362ad3905799d6a865b0f1f60f8","result_count":3},{"issuer_ca_id":105484,"issuer_name":"C=GB, ST=Greater Manchester, L=Salford, O=Sectigo Limited, CN=Sectigo ECC Domain Validation Secure Server CA","common_name":"ec.kvmthkr.kasserver.com","name_value":"ec.kvmthkr.kasserver.com\nwww.ec.kvmthkr.kasserver.com","id":14939726540,"entry_timestamp":"2024-10-15T07:02:38.057","not_before":"2024-10-15T00:00:00","not_after":"2024-11-14T23:59:59","serial_number":"6827c362ad3905799d6a865b0f1f60f8","result_count":3}]}

View File

@@ -1 +0,0 @@
{"domain":"kvmu12s1.kasserver.com","first_cached":"2025-09-15T11:51:04.220452+00:00","last_upstream_query":"2025-09-15T11:51:04.220456+00:00","upstream_query_count":1,"certificates":[{"issuer_ca_id":183267,"issuer_name":"C=US, O=Let's Encrypt, CN=R3","common_name":"nextcloud.kvmu12s1.kasserver.com","name_value":"nextcloud.kvmu12s1.kasserver.com\nwww.nextcloud.kvmu12s1.kasserver.com","id":10586150052,"entry_timestamp":"2023-09-15T10:36:49.311","not_before":"2023-09-15T09:36:48","not_after":"2023-12-14T09:36:47","serial_number":"045dedd31035da18a73d26fe8a4f963f6eef","result_count":3},{"issuer_ca_id":183267,"issuer_name":"C=US, O=Let's Encrypt, CN=R3","common_name":"nextcloud.kvmu12s1.kasserver.com","name_value":"nextcloud.kvmu12s1.kasserver.com\nwww.nextcloud.kvmu12s1.kasserver.com","id":10577792024,"entry_timestamp":"2023-09-15T10:36:49.018","not_before":"2023-09-15T09:36:48","not_after":"2023-12-14T09:36:47","serial_number":"045dedd31035da18a73d26fe8a4f963f6eef","result_count":3},{"issuer_ca_id":183267,"issuer_name":"C=US, O=Let's Encrypt, CN=R3","common_name":"nextcloud.kvmu12s1.kasserver.com","name_value":"nextcloud.kvmu12s1.kasserver.com\nwww.nextcloud.kvmu12s1.kasserver.com","id":9948906308,"entry_timestamp":"2023-07-14T08:26:39.958","not_before":"2023-07-14T07:26:39","not_after":"2023-10-12T07:26:38","serial_number":"035e2fe150728c3a351990f06dab0a9b29b7","result_count":3},{"issuer_ca_id":183267,"issuer_name":"C=US, O=Let's Encrypt, CN=R3","common_name":"nextcloud.kvmu12s1.kasserver.com","name_value":"nextcloud.kvmu12s1.kasserver.com\nwww.nextcloud.kvmu12s1.kasserver.com","id":9905731790,"entry_timestamp":"2023-07-14T08:26:39.811","not_before":"2023-07-14T07:26:39","not_after":"2023-10-12T07:26:38","serial_number":"035e2fe150728c3a351990f06dab0a9b29b7","result_count":3}]}

File diff suppressed because one or more lines are too long

View File

@@ -1 +0,0 @@
{"domain":"llm.mikoshi.de","first_cached":"2025-09-15T15:40:09.181904+00:00","last_upstream_query":"2025-09-15T15:40:09.181907+00:00","upstream_query_count":1,"certificates":[{"issuer_ca_id":295814,"issuer_name":"C=US, O=Let's Encrypt, CN=R10","common_name":"llm.mikoshi.de","name_value":"llm.mikoshi.de","id":19995849024,"entry_timestamp":"2025-07-30T00:02:19.725","not_before":"2025-07-29T23:03:47","not_after":"2025-10-27T23:03:46","serial_number":"05335d7df5f076bd039bf6148fe11ebfd86d","result_count":2},{"issuer_ca_id":295814,"issuer_name":"C=US, O=Let's Encrypt, CN=R10","common_name":"llm.mikoshi.de","name_value":"llm.mikoshi.de","id":19995848373,"entry_timestamp":"2025-07-30T00:02:17.527","not_before":"2025-07-29T23:03:47","not_after":"2025-10-27T23:03:46","serial_number":"05335d7df5f076bd039bf6148fe11ebfd86d","result_count":2},{"issuer_ca_id":295815,"issuer_name":"C=US, O=Let's Encrypt, CN=R11","common_name":"llm.mikoshi.de","name_value":"llm.mikoshi.de","id":18720891589,"entry_timestamp":"2025-05-31T00:01:22.576","not_before":"2025-05-30T23:02:49","not_after":"2025-08-28T23:02:48","serial_number":"064967b3c615cbb4a7f8690b4ee7ed3ab2c2","result_count":2},{"issuer_ca_id":295815,"issuer_name":"C=US, O=Let's Encrypt, CN=R11","common_name":"llm.mikoshi.de","name_value":"llm.mikoshi.de","id":18720891502,"entry_timestamp":"2025-05-31T00:01:20.192","not_before":"2025-05-30T23:02:49","not_after":"2025-08-28T23:02:48","serial_number":"064967b3c615cbb4a7f8690b4ee7ed3ab2c2","result_count":2},{"issuer_ca_id":295815,"issuer_name":"C=US, O=Let's Encrypt, CN=R11","common_name":"llm.mikoshi.de","name_value":"llm.mikoshi.de","id":17870870943,"entry_timestamp":"2025-03-31T19:43:16.66","not_before":"2025-03-31T18:44:46","not_after":"2025-06-29T18:44:45","serial_number":"05da28c4ebc6a250cb83e37fa4bc54b85508","result_count":2},{"issuer_ca_id":295815,"issuer_name":"C=US, O=Let's Encrypt, CN=R11","common_name":"llm.mikoshi.de","name_value":"llm.mikoshi.de","id":17539939653,"entry_timestamp":"2025-03-31T19:43:16.406","not_before":"2025-03-31T18:44:46","not_after":"2025-06-29T18:44:45","serial_number":"05da28c4ebc6a250cb83e37fa4bc54b85508","result_count":2}]}

File diff suppressed because one or more lines are too long

View File

@@ -1 +0,0 @@
{"domain":"matrix.mikoshi.de","first_cached":"2025-09-15T15:40:28.068782+00:00","last_upstream_query":"2025-09-15T15:40:28.068785+00:00","upstream_query_count":1,"certificates":[{"issuer_ca_id":295814,"issuer_name":"C=US, O=Let's Encrypt, CN=R10","common_name":"matrix.mikoshi.de","name_value":"matrix.mikoshi.de","id":17170805427,"entry_timestamp":"2025-02-13T00:01:24.095","not_before":"2025-02-12T23:02:53","not_after":"2025-05-13T23:02:52","serial_number":"0340c3ca26c1ab1678dd4c8885208ac93818","result_count":2},{"issuer_ca_id":295814,"issuer_name":"C=US, O=Let's Encrypt, CN=R10","common_name":"matrix.mikoshi.de","name_value":"matrix.mikoshi.de","id":16704107881,"entry_timestamp":"2025-02-13T00:01:23.078","not_before":"2025-02-12T23:02:53","not_after":"2025-05-13T23:02:52","serial_number":"0340c3ca26c1ab1678dd4c8885208ac93818","result_count":2},{"issuer_ca_id":295814,"issuer_name":"C=US, O=Let's Encrypt, CN=R10","common_name":"matrix.mikoshi.de","name_value":"matrix.mikoshi.de","id":17122315423,"entry_timestamp":"2025-02-09T15:17:51.214","not_before":"2025-02-09T14:19:20","not_after":"2025-05-10T14:19:19","serial_number":"03e088e499d2b5e10132f28674a00990313a","result_count":2},{"issuer_ca_id":295814,"issuer_name":"C=US, O=Let's Encrypt, CN=R10","common_name":"matrix.mikoshi.de","name_value":"matrix.mikoshi.de","id":16635517598,"entry_timestamp":"2025-02-09T15:17:50.818","not_before":"2025-02-09T14:19:20","not_after":"2025-05-10T14:19:19","serial_number":"03e088e499d2b5e10132f28674a00990313a","result_count":2}]}

View File

@@ -1 +0,0 @@
{"domain":"mempool.mikoshi.de","first_cached":"2025-09-15T15:37:03.196760+00:00","last_upstream_query":"2025-09-15T15:37:03.196764+00:00","upstream_query_count":1,"certificates":[{"issuer_ca_id":295814,"issuer_name":"C=US, O=Let's Encrypt, CN=R10","common_name":"mempool.mikoshi.de","name_value":"mempool.mikoshi.de","id":20275766421,"entry_timestamp":"2025-08-12T00:03:06.545","not_before":"2025-08-11T23:04:33","not_after":"2025-11-09T23:04:32","serial_number":"05db41917aa6146ca29cc3a918e57bfa2dcf","result_count":2},{"issuer_ca_id":295814,"issuer_name":"C=US, O=Let's Encrypt, CN=R10","common_name":"mempool.mikoshi.de","name_value":"mempool.mikoshi.de","id":20275769957,"entry_timestamp":"2025-08-12T00:03:04.069","not_before":"2025-08-11T23:04:33","not_after":"2025-11-09T23:04:32","serial_number":"05db41917aa6146ca29cc3a918e57bfa2dcf","result_count":2},{"issuer_ca_id":295814,"issuer_name":"C=US, O=Let's Encrypt, CN=R10","common_name":"mempool.mikoshi.de","name_value":"mempool.mikoshi.de","id":18986859548,"entry_timestamp":"2025-06-13T00:01:16.577","not_before":"2025-06-12T23:02:40","not_after":"2025-09-10T23:02:39","serial_number":"05b7e05db409b0791e0b480cfb8f3116b44f","result_count":2},{"issuer_ca_id":295814,"issuer_name":"C=US, O=Let's Encrypt, CN=R10","common_name":"mempool.mikoshi.de","name_value":"mempool.mikoshi.de","id":18987057144,"entry_timestamp":"2025-06-13T00:01:10.626","not_before":"2025-06-12T23:02:40","not_after":"2025-09-10T23:02:39","serial_number":"05b7e05db409b0791e0b480cfb8f3116b44f","result_count":2},{"issuer_ca_id":295814,"issuer_name":"C=US, O=Let's Encrypt, CN=R10","common_name":"mempool.mikoshi.de","name_value":"mempool.mikoshi.de","id":17831239624,"entry_timestamp":"2025-04-14T00:05:10.579","not_before":"2025-04-13T23:06:40","not_after":"2025-07-12T23:06:39","serial_number":"0573b6923c8539ab353225bf023b7fd6b465","result_count":2},{"issuer_ca_id":295814,"issuer_name":"C=US, O=Let's Encrypt, CN=R10","common_name":"mempool.mikoshi.de","name_value":"mempool.mikoshi.de","id":17831349460,"entry_timestamp":"2025-04-14T00:05:10.362","not_before":"2025-04-13T23:06:40","not_after":"2025-07-12T23:06:39","serial_number":"0573b6923c8539ab353225bf023b7fd6b465","result_count":2},{"issuer_ca_id":295815,"issuer_name":"C=US, O=Let's Encrypt, CN=R11","common_name":"mempool.mikoshi.de","name_value":"mempool.mikoshi.de","id":17170793138,"entry_timestamp":"2025-02-13T00:00:22.884","not_before":"2025-02-12T23:01:52","not_after":"2025-05-13T23:01:51","serial_number":"048ddc03e0d19d586ef5508bb636fa2ba81b","result_count":2},{"issuer_ca_id":295815,"issuer_name":"C=US, O=Let's Encrypt, CN=R11","common_name":"mempool.mikoshi.de","name_value":"mempool.mikoshi.de","id":16704095754,"entry_timestamp":"2025-02-13T00:00:22.634","not_before":"2025-02-12T23:01:52","not_after":"2025-05-13T23:01:51","serial_number":"048ddc03e0d19d586ef5508bb636fa2ba81b","result_count":2},{"issuer_ca_id":295814,"issuer_name":"C=US, O=Let's Encrypt, CN=R10","common_name":"mempool.mikoshi.de","name_value":"mempool.mikoshi.de","id":16636671204,"entry_timestamp":"2025-02-09T15:12:41.443","not_before":"2025-02-09T14:14:11","not_after":"2025-05-10T14:14:10","serial_number":"03a2ba996fd26f676c53edec5725f7442c90","result_count":2},{"issuer_ca_id":295814,"issuer_name":"C=US, O=Let's Encrypt, CN=R10","common_name":"mempool.mikoshi.de","name_value":"mempool.mikoshi.de","id":16635433368,"entry_timestamp":"2025-02-09T15:12:41.328","not_before":"2025-02-09T14:14:11","not_after":"2025-05-10T14:14:10","serial_number":"03a2ba996fd26f676c53edec5725f7442c90","result_count":2}]}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -1 +0,0 @@
{"domain":"misp.mikoshi.de","first_cached":"2025-09-14T22:38:25.627275+00:00","last_upstream_query":"2025-09-15T15:37:51.293899+00:00","upstream_query_count":2,"certificates":[{"issuer_ca_id":295810,"issuer_name":"C=US, O=Let's Encrypt, CN=E5","common_name":"misp.mikoshi.de","name_value":"misp.mikoshi.de","id":17353605244,"entry_timestamp":"2025-02-25T00:29:30.385","not_before":"2025-02-24T23:30:59","not_after":"2025-05-25T23:30:58","serial_number":"03b9fa625fe61e6c16d14916613ca1f46d04","result_count":2},{"issuer_ca_id":295810,"issuer_name":"C=US, O=Let's Encrypt, CN=E5","common_name":"misp.mikoshi.de","name_value":"misp.mikoshi.de","id":16895667572,"entry_timestamp":"2025-02-25T00:29:29.913","not_before":"2025-02-24T23:30:59","not_after":"2025-05-25T23:30:58","serial_number":"03b9fa625fe61e6c16d14916613ca1f46d04","result_count":2}]}

View File

@@ -1 +0,0 @@
{"domain":"mx00.ionos.de","first_cached":"2025-09-14T21:05:21.043082+00:00","last_upstream_query":"2025-09-15T15:34:57.508633+00:00","upstream_query_count":3,"certificates":[{"issuer_ca_id":245439,"issuer_name":"C=DE, O=Deutsche Telekom Security GmbH, CN=Telekom Security ServerID OV Class 2 CA","common_name":"mx.kundenserver.de","name_value":"mx00.ionos.de","id":17921174855,"entry_timestamp":"2025-04-18T11:32:56.685","not_before":"2024-05-14T10:13:42","not_after":"2025-05-18T23:59:59","serial_number":"01f21195d95cb3f63712c59f40b2f75c","result_count":1},{"issuer_ca_id":245439,"issuer_name":"C=DE, O=Deutsche Telekom Security GmbH, CN=Telekom Security ServerID OV Class 2 CA","common_name":"mx.kundenserver.de","name_value":"mx00.ionos.de","id":17755974719,"entry_timestamp":"2025-04-10T06:20:35.546","not_before":"2025-04-10T06:20:33","not_after":"2026-04-14T23:59:59","serial_number":"27efd5b7b17610e4ae86d40dea979ad7","result_count":1},{"issuer_ca_id":245439,"issuer_name":"C=DE, O=Deutsche Telekom Security GmbH, CN=Telekom Security ServerID OV Class 2 CA","common_name":"mx.kundenserver.de","name_value":"mx00.ionos.de","id":13038507917,"entry_timestamp":"2024-05-14T10:13:43.64","not_before":"2024-05-14T10:13:42","not_after":"2025-05-18T23:59:59","serial_number":"01f21195d95cb3f63712c59f40b2f75c","result_count":1},{"issuer_ca_id":245439,"issuer_name":"C=DE, O=Deutsche Telekom Security GmbH, CN=Telekom Security ServerID OV Class 2 CA","common_name":"mx.kundenserver.de","name_value":"mx00.ionos.de","id":9700366741,"entry_timestamp":"2023-06-20T11:08:14.981","not_before":"2023-06-20T11:08:11","not_after":"2024-06-24T23:59:59","serial_number":"153f3cd769500d3eebec07c90476d817","result_count":1},{"issuer_ca_id":6069,"issuer_name":"C=DE, O=T-Systems International GmbH, OU=T-Systems Trust Center, ST=Nordrhein Westfalen, postalCode=57250, L=Netphen, street=Untere Industriestr. 20, CN=TeleSec ServerPass Class 2 CA","common_name":"mx.kundenserver.de","name_value":"mx00.ionos.de","id":7107715703,"entry_timestamp":"2022-07-12T10:00:03.026","not_before":"2022-07-12T10:00:01","not_after":"2023-07-16T23:59:59","serial_number":"210a3739eb290b28d1199f6a9c04d294","result_count":1},{"issuer_ca_id":6069,"issuer_name":"C=DE, O=T-Systems International GmbH, OU=T-Systems Trust Center, ST=Nordrhein Westfalen, postalCode=57250, L=Netphen, street=Untere Industriestr. 20, CN=TeleSec ServerPass Class 2 CA","common_name":"mx.kundenserver.de","name_value":"mx00.ionos.de","id":4981516894,"entry_timestamp":"2021-08-04T08:35:13.1","not_before":"2021-08-04T08:35:11","not_after":"2022-08-08T23:59:59","serial_number":"11ae5449f5d5cc2a5ec198105748f927","result_count":1},{"issuer_ca_id":6069,"issuer_name":"C=DE, O=T-Systems International GmbH, OU=T-Systems Trust Center, ST=Nordrhein Westfalen, postalCode=57250, L=Netphen, street=Untere Industriestr. 20, CN=TeleSec ServerPass Class 2 CA","common_name":"mx.kundenserver.de","name_value":"mx00.ionos.de","id":2864694015,"entry_timestamp":"2020-05-28T07:54:38.37","not_before":"2020-05-28T07:54:37","not_after":"2022-06-02T23:59:59","serial_number":"325b678601aae53e99926c1834988786","result_count":1},{"issuer_ca_id":6069,"issuer_name":"C=DE, O=T-Systems International GmbH, OU=T-Systems Trust Center, ST=Nordrhein Westfalen, postalCode=57250, L=Netphen, street=Untere Industriestr. 20, CN=TeleSec ServerPass Class 2 CA","common_name":"mx.kundenserver.de","name_value":"mx00.ionos.de","id":2857249553,"entry_timestamp":"2020-05-26T09:01:33.944","not_before":"2020-05-26T09:01:33","not_after":"2022-05-31T23:59:59","serial_number":"0ceee698ba17a744881fbb3998c05748","result_count":1},{"issuer_ca_id":6069,"issuer_name":"C=DE, O=T-Systems International GmbH, OU=T-Systems Trust Center, ST=Nordrhein Westfalen, postalCode=57250, L=Netphen, street=Untere Industriestr. 20, CN=TeleSec ServerPass Class 2 CA","common_name":"mx.kundenserver.de","name_value":"mx00.ionos.de","id":2857204010,"entry_timestamp":"2020-05-26T08:46:52.8","not_before":"2020-05-26T08:46:52","not_after":"2022-05-31T23:59:59","serial_number":"0ac520de92fde640943c1d2c0eb2f6e8","result_count":1},{"issuer_ca_id":6069,"issuer_name":"C=DE, O=T-Systems International GmbH, OU=T-Systems Trust Center, ST=Nordrhein Westfalen, postalCode=57250, L=Netphen, street=Untere Industriestr. 20, CN=TeleSec ServerPass Class 2 CA","common_name":"mx.kundenserver.de","name_value":"mx00.ionos.de","id":2856876813,"entry_timestamp":"2020-05-26T06:58:49.881","not_before":"2020-05-26T06:58:49","not_after":"2022-05-31T23:59:59","serial_number":"2f9201af62a3408df1579b8a39c0f7b6","result_count":1}]}

View File

@@ -1,188 +0,0 @@
{
"domain": "mx00.kundenserver.de",
"first_cached": "2025-09-15T19:23:52.908544+00:00",
"last_upstream_query": "2025-09-15T19:23:52.908548+00:00",
"upstream_query_count": 1,
"certificates": [
{
"issuer_ca_id": 245439,
"issuer_name": "C=DE, O=Deutsche Telekom Security GmbH, CN=Telekom Security ServerID OV Class 2 CA",
"common_name": "mx.kundenserver.de",
"name_value": "mx00.kundenserver.de",
"id": 17921174855,
"entry_timestamp": "2025-04-18T11:32:56.685",
"not_before": "2024-05-14T10:13:42",
"not_after": "2025-05-18T23:59:59",
"serial_number": "01f21195d95cb3f63712c59f40b2f75c",
"result_count": 1
},
{
"issuer_ca_id": 245439,
"issuer_name": "C=DE, O=Deutsche Telekom Security GmbH, CN=Telekom Security ServerID OV Class 2 CA",
"common_name": "mx.kundenserver.de",
"name_value": "mx00.kundenserver.de",
"id": 17755974719,
"entry_timestamp": "2025-04-10T06:20:35.546",
"not_before": "2025-04-10T06:20:33",
"not_after": "2026-04-14T23:59:59",
"serial_number": "27efd5b7b17610e4ae86d40dea979ad7",
"result_count": 1
},
{
"issuer_ca_id": 245439,
"issuer_name": "C=DE, O=Deutsche Telekom Security GmbH, CN=Telekom Security ServerID OV Class 2 CA",
"common_name": "mx.kundenserver.de",
"name_value": "mx00.kundenserver.de",
"id": 13038507917,
"entry_timestamp": "2024-05-14T10:13:43.64",
"not_before": "2024-05-14T10:13:42",
"not_after": "2025-05-18T23:59:59",
"serial_number": "01f21195d95cb3f63712c59f40b2f75c",
"result_count": 1
},
{
"issuer_ca_id": 245439,
"issuer_name": "C=DE, O=Deutsche Telekom Security GmbH, CN=Telekom Security ServerID OV Class 2 CA",
"common_name": "mx.kundenserver.de",
"name_value": "mx00.kundenserver.de",
"id": 9700366741,
"entry_timestamp": "2023-06-20T11:08:14.981",
"not_before": "2023-06-20T11:08:11",
"not_after": "2024-06-24T23:59:59",
"serial_number": "153f3cd769500d3eebec07c90476d817",
"result_count": 1
},
{
"issuer_ca_id": 6069,
"issuer_name": "C=DE, O=T-Systems International GmbH, OU=T-Systems Trust Center, ST=Nordrhein Westfalen, postalCode=57250, L=Netphen, street=Untere Industriestr. 20, CN=TeleSec ServerPass Class 2 CA",
"common_name": "mx.kundenserver.de",
"name_value": "mx00.kundenserver.de",
"id": 7107715703,
"entry_timestamp": "2022-07-12T10:00:03.026",
"not_before": "2022-07-12T10:00:01",
"not_after": "2023-07-16T23:59:59",
"serial_number": "210a3739eb290b28d1199f6a9c04d294",
"result_count": 1
},
{
"issuer_ca_id": 6069,
"issuer_name": "C=DE, O=T-Systems International GmbH, OU=T-Systems Trust Center, ST=Nordrhein Westfalen, postalCode=57250, L=Netphen, street=Untere Industriestr. 20, CN=TeleSec ServerPass Class 2 CA",
"common_name": "mx.kundenserver.de",
"name_value": "mx00.kundenserver.de",
"id": 4981516894,
"entry_timestamp": "2021-08-04T08:35:13.1",
"not_before": "2021-08-04T08:35:11",
"not_after": "2022-08-08T23:59:59",
"serial_number": "11ae5449f5d5cc2a5ec198105748f927",
"result_count": 1
},
{
"issuer_ca_id": 6069,
"issuer_name": "C=DE, O=T-Systems International GmbH, OU=T-Systems Trust Center, ST=Nordrhein Westfalen, postalCode=57250, L=Netphen, street=Untere Industriestr. 20, CN=TeleSec ServerPass Class 2 CA",
"common_name": "mx.kundenserver.de",
"name_value": "mx00.kundenserver.de",
"id": 2864694015,
"entry_timestamp": "2020-05-28T07:54:38.37",
"not_before": "2020-05-28T07:54:37",
"not_after": "2022-06-02T23:59:59",
"serial_number": "325b678601aae53e99926c1834988786",
"result_count": 1
},
{
"issuer_ca_id": 6069,
"issuer_name": "C=DE, O=T-Systems International GmbH, OU=T-Systems Trust Center, ST=Nordrhein Westfalen, postalCode=57250, L=Netphen, street=Untere Industriestr. 20, CN=TeleSec ServerPass Class 2 CA",
"common_name": "mx.kundenserver.de",
"name_value": "mx00.kundenserver.de",
"id": 2857249553,
"entry_timestamp": "2020-05-26T09:01:33.944",
"not_before": "2020-05-26T09:01:33",
"not_after": "2022-05-31T23:59:59",
"serial_number": "0ceee698ba17a744881fbb3998c05748",
"result_count": 1
},
{
"issuer_ca_id": 6069,
"issuer_name": "C=DE, O=T-Systems International GmbH, OU=T-Systems Trust Center, ST=Nordrhein Westfalen, postalCode=57250, L=Netphen, street=Untere Industriestr. 20, CN=TeleSec ServerPass Class 2 CA",
"common_name": "mx.kundenserver.de",
"name_value": "mx00.kundenserver.de",
"id": 2857204010,
"entry_timestamp": "2020-05-26T08:46:52.8",
"not_before": "2020-05-26T08:46:52",
"not_after": "2022-05-31T23:59:59",
"serial_number": "0ac520de92fde640943c1d2c0eb2f6e8",
"result_count": 1
},
{
"issuer_ca_id": 6069,
"issuer_name": "C=DE, O=T-Systems International GmbH, OU=T-Systems Trust Center, ST=Nordrhein Westfalen, postalCode=57250, L=Netphen, street=Untere Industriestr. 20, CN=TeleSec ServerPass Class 2 CA",
"common_name": "mx.kundenserver.de",
"name_value": "mx00.kundenserver.de",
"id": 2856876813,
"entry_timestamp": "2020-05-26T06:58:49.881",
"not_before": "2020-05-26T06:58:49",
"not_after": "2022-05-31T23:59:59",
"serial_number": "2f9201af62a3408df1579b8a39c0f7b6",
"result_count": 1
},
{
"issuer_ca_id": 6069,
"issuer_name": "C=DE, O=T-Systems International GmbH, OU=T-Systems Trust Center, ST=Nordrhein Westfalen, postalCode=57250, L=Netphen, street=Untere Industriestr. 20, CN=TeleSec ServerPass Class 2 CA",
"common_name": "mx.kundenserver.de",
"name_value": "mx00.kundenserver.de",
"id": 1351991065,
"entry_timestamp": "2019-04-05T05:26:06.601",
"not_before": "2019-02-18T09:14:39",
"not_after": "2021-02-23T23:59:59",
"serial_number": "2c12501e6e490dd60bfb87d85edad1d1",
"result_count": 1
},
{
"issuer_ca_id": 6069,
"issuer_name": "C=DE, O=T-Systems International GmbH, OU=T-Systems Trust Center, ST=Nordrhein Westfalen, postalCode=57250, L=Netphen, street=Untere Industriestr. 20, CN=TeleSec ServerPass Class 2 CA",
"common_name": "mx.kundenserver.de",
"name_value": "mx00.kundenserver.de",
"id": 1213296236,
"entry_timestamp": "2019-02-18T09:14:39.61",
"not_before": "2019-02-18T09:14:39",
"not_after": "2021-02-23T23:59:59",
"serial_number": "2c12501e6e490dd60bfb87d85edad1d1",
"result_count": 1
},
{
"issuer_ca_id": 1375,
"issuer_name": "C=DE, O=T-Systems International GmbH, OU=T-Systems Trust Center, ST=NRW, postalCode=57250, L=Netphen, street=Untere Industriestr. 20, CN=TeleSec ServerPass DE-1",
"common_name": "mx00.kundenserver.de",
"name_value": "mx00.kundenserver.de",
"id": 370285812,
"entry_timestamp": "2018-03-30T01:09:17.252",
"not_before": "2013-08-06T15:49:56",
"not_after": "2014-08-11T23:59:59",
"serial_number": "00f17c74ae3d6e7a5c",
"result_count": 2
},
{
"issuer_ca_id": 1477,
"issuer_name": "C=DE, O=T-Systems International GmbH, OU=T-Systems Trust Center, ST=Nordrhein Westfalen, postalCode=57250, L=Netphen, street=Untere Industriestr. 20, CN=TeleSec ServerPass DE-2",
"common_name": "mx.kundenserver.de",
"name_value": "mx00.kundenserver.de",
"id": 307747879,
"entry_timestamp": "2018-01-19T09:01:19.72",
"not_before": "2017-03-22T10:21:38",
"not_after": "2019-03-27T23:59:59",
"serial_number": "00bf95dcc292d7bf01",
"result_count": 1
},
{
"issuer_ca_id": 1477,
"issuer_name": "C=DE, O=T-Systems International GmbH, OU=T-Systems Trust Center, ST=Nordrhein Westfalen, postalCode=57250, L=Netphen, street=Untere Industriestr. 20, CN=TeleSec ServerPass DE-2",
"common_name": "mx00.kundenserver.de",
"name_value": "mx00.kundenserver.de",
"id": 14627870,
"entry_timestamp": "2016-03-08T11:54:51.83",
"not_before": "2014-07-22T11:15:15",
"not_after": "2017-07-27T23:59:59",
"serial_number": "20e14d5c7f18e199",
"result_count": 2
}
]
}

View File

@@ -1 +0,0 @@
{"domain":"mx01.ionos.de","first_cached":"2025-09-14T21:05:58.567956+00:00","last_upstream_query":"2025-09-15T15:34:59.570960+00:00","upstream_query_count":3,"certificates":[{"issuer_ca_id":245439,"issuer_name":"C=DE, O=Deutsche Telekom Security GmbH, CN=Telekom Security ServerID OV Class 2 CA","common_name":"mx.kundenserver.de","name_value":"mx01.ionos.de","id":17921174855,"entry_timestamp":"2025-04-18T11:32:56.685","not_before":"2024-05-14T10:13:42","not_after":"2025-05-18T23:59:59","serial_number":"01f21195d95cb3f63712c59f40b2f75c","result_count":1},{"issuer_ca_id":245439,"issuer_name":"C=DE, O=Deutsche Telekom Security GmbH, CN=Telekom Security ServerID OV Class 2 CA","common_name":"mx.kundenserver.de","name_value":"mx01.ionos.de","id":17755974719,"entry_timestamp":"2025-04-10T06:20:35.546","not_before":"2025-04-10T06:20:33","not_after":"2026-04-14T23:59:59","serial_number":"27efd5b7b17610e4ae86d40dea979ad7","result_count":1},{"issuer_ca_id":245439,"issuer_name":"C=DE, O=Deutsche Telekom Security GmbH, CN=Telekom Security ServerID OV Class 2 CA","common_name":"mx.kundenserver.de","name_value":"mx01.ionos.de","id":13038507917,"entry_timestamp":"2024-05-14T10:13:43.64","not_before":"2024-05-14T10:13:42","not_after":"2025-05-18T23:59:59","serial_number":"01f21195d95cb3f63712c59f40b2f75c","result_count":1},{"issuer_ca_id":245439,"issuer_name":"C=DE, O=Deutsche Telekom Security GmbH, CN=Telekom Security ServerID OV Class 2 CA","common_name":"mx.kundenserver.de","name_value":"mx01.ionos.de","id":9700366741,"entry_timestamp":"2023-06-20T11:08:14.981","not_before":"2023-06-20T11:08:11","not_after":"2024-06-24T23:59:59","serial_number":"153f3cd769500d3eebec07c90476d817","result_count":1},{"issuer_ca_id":6069,"issuer_name":"C=DE, O=T-Systems International GmbH, OU=T-Systems Trust Center, ST=Nordrhein Westfalen, postalCode=57250, L=Netphen, street=Untere Industriestr. 20, CN=TeleSec ServerPass Class 2 CA","common_name":"mx.kundenserver.de","name_value":"mx01.ionos.de","id":7107715703,"entry_timestamp":"2022-07-12T10:00:03.026","not_before":"2022-07-12T10:00:01","not_after":"2023-07-16T23:59:59","serial_number":"210a3739eb290b28d1199f6a9c04d294","result_count":1},{"issuer_ca_id":6069,"issuer_name":"C=DE, O=T-Systems International GmbH, OU=T-Systems Trust Center, ST=Nordrhein Westfalen, postalCode=57250, L=Netphen, street=Untere Industriestr. 20, CN=TeleSec ServerPass Class 2 CA","common_name":"mx.kundenserver.de","name_value":"mx01.ionos.de","id":4981516894,"entry_timestamp":"2021-08-04T08:35:13.1","not_before":"2021-08-04T08:35:11","not_after":"2022-08-08T23:59:59","serial_number":"11ae5449f5d5cc2a5ec198105748f927","result_count":1},{"issuer_ca_id":6069,"issuer_name":"C=DE, O=T-Systems International GmbH, OU=T-Systems Trust Center, ST=Nordrhein Westfalen, postalCode=57250, L=Netphen, street=Untere Industriestr. 20, CN=TeleSec ServerPass Class 2 CA","common_name":"mx.kundenserver.de","name_value":"mx01.ionos.de","id":2864694015,"entry_timestamp":"2020-05-28T07:54:38.37","not_before":"2020-05-28T07:54:37","not_after":"2022-06-02T23:59:59","serial_number":"325b678601aae53e99926c1834988786","result_count":1},{"issuer_ca_id":6069,"issuer_name":"C=DE, O=T-Systems International GmbH, OU=T-Systems Trust Center, ST=Nordrhein Westfalen, postalCode=57250, L=Netphen, street=Untere Industriestr. 20, CN=TeleSec ServerPass Class 2 CA","common_name":"mx.kundenserver.de","name_value":"mx01.ionos.de","id":2857249553,"entry_timestamp":"2020-05-26T09:01:33.944","not_before":"2020-05-26T09:01:33","not_after":"2022-05-31T23:59:59","serial_number":"0ceee698ba17a744881fbb3998c05748","result_count":1},{"issuer_ca_id":6069,"issuer_name":"C=DE, O=T-Systems International GmbH, OU=T-Systems Trust Center, ST=Nordrhein Westfalen, postalCode=57250, L=Netphen, street=Untere Industriestr. 20, CN=TeleSec ServerPass Class 2 CA","common_name":"mx.kundenserver.de","name_value":"mx01.ionos.de","id":2857204010,"entry_timestamp":"2020-05-26T08:46:52.8","not_before":"2020-05-26T08:46:52","not_after":"2022-05-31T23:59:59","serial_number":"0ac520de92fde640943c1d2c0eb2f6e8","result_count":1},{"issuer_ca_id":6069,"issuer_name":"C=DE, O=T-Systems International GmbH, OU=T-Systems Trust Center, ST=Nordrhein Westfalen, postalCode=57250, L=Netphen, street=Untere Industriestr. 20, CN=TeleSec ServerPass Class 2 CA","common_name":"mx.kundenserver.de","name_value":"mx01.ionos.de","id":2856876813,"entry_timestamp":"2020-05-26T06:58:49.881","not_before":"2020-05-26T06:58:49","not_after":"2022-05-31T23:59:59","serial_number":"2f9201af62a3408df1579b8a39c0f7b6","result_count":1}]}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -1 +0,0 @@
{"domain":"nostr.mikoshi.de","first_cached":"2025-09-14T22:44:55.522098+00:00","last_upstream_query":"2025-09-15T15:39:39.928858+00:00","upstream_query_count":2,"certificates":[{"issuer_ca_id":295809,"issuer_name":"C=US, O=Let's Encrypt, CN=E8","common_name":"nostr.mikoshi.de","name_value":"nostr.mikoshi.de","id":20839972270,"entry_timestamp":"2025-09-07T00:01:25.998","not_before":"2025-09-06T23:02:55","not_after":"2025-12-05T23:02:54","serial_number":"05c5c3ab0353acb84d7adc05e78d6d6fe276","result_count":2},{"issuer_ca_id":295809,"issuer_name":"C=US, O=Let's Encrypt, CN=E8","common_name":"nostr.mikoshi.de","name_value":"nostr.mikoshi.de","id":20839069128,"entry_timestamp":"2025-09-07T00:01:25.786","not_before":"2025-09-06T23:02:55","not_after":"2025-12-05T23:02:54","serial_number":"05c5c3ab0353acb84d7adc05e78d6d6fe276","result_count":2},{"issuer_ca_id":295813,"issuer_name":"C=US, O=Let's Encrypt, CN=E7","common_name":"nostr.mikoshi.de","name_value":"nostr.mikoshi.de","id":20641626677,"entry_timestamp":"2025-08-29T00:03:39.504","not_before":"2025-08-28T23:05:09","not_after":"2025-11-26T23:05:08","serial_number":"059eab3e56a39c431f4cb961af259f45f550","result_count":2},{"issuer_ca_id":295813,"issuer_name":"C=US, O=Let's Encrypt, CN=E7","common_name":"nostr.mikoshi.de","name_value":"nostr.mikoshi.de","id":20641627201,"entry_timestamp":"2025-08-29T00:03:39.306","not_before":"2025-08-28T23:05:09","not_after":"2025-11-26T23:05:08","serial_number":"059eab3e56a39c431f4cb961af259f45f550","result_count":2},{"issuer_ca_id":295810,"issuer_name":"C=US, O=Let's Encrypt, CN=E5","common_name":"nostr.mikoshi.de","name_value":"nostr.mikoshi.de","id":20446505609,"entry_timestamp":"2025-08-19T20:58:17.951","not_before":"2025-08-19T19:59:45","not_after":"2025-11-17T19:59:44","serial_number":"06e00b2fda8f18091bb0be67f6809f87a889","result_count":2},{"issuer_ca_id":295810,"issuer_name":"C=US, O=Let's Encrypt, CN=E5","common_name":"nostr.mikoshi.de","name_value":"nostr.mikoshi.de","id":20441143198,"entry_timestamp":"2025-08-19T20:58:15.697","not_before":"2025-08-19T19:59:45","not_after":"2025-11-17T19:59:44","serial_number":"06e00b2fda8f18091bb0be67f6809f87a889","result_count":2},{"issuer_ca_id":295815,"issuer_name":"C=US, O=Let's Encrypt, CN=R11","common_name":"nostr.mikoshi.de","name_value":"nostr.mikoshi.de","id":17170798515,"entry_timestamp":"2025-02-13T00:00:50.437","not_before":"2025-02-12T23:02:19","not_after":"2025-05-13T23:02:18","serial_number":"04b641da285b3701db3e199cc49b87a023c7","result_count":2},{"issuer_ca_id":295815,"issuer_name":"C=US, O=Let's Encrypt, CN=R11","common_name":"nostr.mikoshi.de","name_value":"nostr.mikoshi.de","id":16705237488,"entry_timestamp":"2025-02-13T00:00:50.226","not_before":"2025-02-12T23:02:19","not_after":"2025-05-13T23:02:18","serial_number":"04b641da285b3701db3e199cc49b87a023c7","result_count":2},{"issuer_ca_id":295814,"issuer_name":"C=US, O=Let's Encrypt, CN=R10","common_name":"nostr.mikoshi.de","name_value":"nostr.mikoshi.de","id":17122272223,"entry_timestamp":"2025-02-09T15:15:01.538","not_before":"2025-02-09T14:16:30","not_after":"2025-05-10T14:16:29","serial_number":"04f78d3955d454fb6d004d08cfadb198d2be","result_count":2},{"issuer_ca_id":295814,"issuer_name":"C=US, O=Let's Encrypt, CN=R10","common_name":"nostr.mikoshi.de","name_value":"nostr.mikoshi.de","id":16636445173,"entry_timestamp":"2025-02-09T15:15:01.221","not_before":"2025-02-09T14:16:30","not_after":"2025-05-10T14:16:29","serial_number":"04f78d3955d454fb6d004d08cfadb198d2be","result_count":2}]}

View File

@@ -1 +0,0 @@
{"domain":"notes.mikoshi.de","first_cached":"2025-09-15T15:37:27.243670+00:00","last_upstream_query":"2025-09-15T15:37:27.243675+00:00","upstream_query_count":1,"certificates":[{"issuer_ca_id":295815,"issuer_name":"C=US, O=Let's Encrypt, CN=R11","common_name":"notes.mikoshi.de","name_value":"notes.mikoshi.de","id":17831397265,"entry_timestamp":"2025-04-14T00:15:27.018","not_before":"2025-04-13T23:16:56","not_after":"2025-07-12T23:16:55","serial_number":"0604f6b0149b4afe45efbe46a5493c1ec3fd","result_count":2},{"issuer_ca_id":295815,"issuer_name":"C=US, O=Let's Encrypt, CN=R11","common_name":"notes.mikoshi.de","name_value":"notes.mikoshi.de","id":17831343922,"entry_timestamp":"2025-04-14T00:15:26.683","not_before":"2025-04-13T23:16:56","not_after":"2025-07-12T23:16:55","serial_number":"0604f6b0149b4afe45efbe46a5493c1ec3fd","result_count":2},{"issuer_ca_id":295814,"issuer_name":"C=US, O=Let's Encrypt, CN=R10","common_name":"notes.mikoshi.de","name_value":"notes.mikoshi.de","id":17170808839,"entry_timestamp":"2025-02-13T00:01:30.661","not_before":"2025-02-12T23:03:00","not_after":"2025-05-13T23:02:59","serial_number":"032b2779b00fd8c25fb56ccab4a5eccf7b1a","result_count":2},{"issuer_ca_id":295814,"issuer_name":"C=US, O=Let's Encrypt, CN=R10","common_name":"notes.mikoshi.de","name_value":"notes.mikoshi.de","id":16704108124,"entry_timestamp":"2025-02-13T00:01:30.468","not_before":"2025-02-12T23:03:00","not_after":"2025-05-13T23:02:59","serial_number":"032b2779b00fd8c25fb56ccab4a5eccf7b1a","result_count":2},{"issuer_ca_id":295814,"issuer_name":"C=US, O=Let's Encrypt, CN=R10","common_name":"notes.mikoshi.de","name_value":"notes.mikoshi.de","id":17122334548,"entry_timestamp":"2025-02-09T15:18:27.206","not_before":"2025-02-09T14:19:56","not_after":"2025-05-10T14:19:55","serial_number":"042257f7bcc91c0994e9c3c76da6ee700a03","result_count":2},{"issuer_ca_id":295814,"issuer_name":"C=US, O=Let's Encrypt, CN=R10","common_name":"notes.mikoshi.de","name_value":"notes.mikoshi.de","id":16636453516,"entry_timestamp":"2025-02-09T15:18:26.537","not_before":"2025-02-09T14:19:56","not_after":"2025-05-10T14:19:55","serial_number":"042257f7bcc91c0994e9c3c76da6ee700a03","result_count":2}]}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -1 +0,0 @@
{"domain":"office.mikoshi.de","first_cached":"2025-09-15T15:38:27.549467+00:00","last_upstream_query":"2025-09-15T15:38:27.549473+00:00","upstream_query_count":1,"certificates":[{"issuer_ca_id":295815,"issuer_name":"C=US, O=Let's Encrypt, CN=R11","common_name":"office.mikoshi.de","name_value":"office.mikoshi.de","id":20275820856,"entry_timestamp":"2025-08-12T00:07:33.018","not_before":"2025-08-11T23:09:02","not_after":"2025-11-09T23:09:01","serial_number":"05c2c936c2f12251f76b59d3ad2854f50f78","result_count":2},{"issuer_ca_id":295815,"issuer_name":"C=US, O=Let's Encrypt, CN=R11","common_name":"office.mikoshi.de","name_value":"office.mikoshi.de","id":20275819318,"entry_timestamp":"2025-08-12T00:07:32.912","not_before":"2025-08-11T23:09:02","not_after":"2025-11-09T23:09:01","serial_number":"05c2c936c2f12251f76b59d3ad2854f50f78","result_count":2},{"issuer_ca_id":295815,"issuer_name":"C=US, O=Let's Encrypt, CN=R11","common_name":"office.mikoshi.de","name_value":"office.mikoshi.de","id":18987110425,"entry_timestamp":"2025-06-13T00:04:44.238","not_before":"2025-06-12T23:06:13","not_after":"2025-09-10T23:06:12","serial_number":"051acaa08d5d89e6f4063edabca209961196","result_count":2},{"issuer_ca_id":295815,"issuer_name":"C=US, O=Let's Encrypt, CN=R11","common_name":"office.mikoshi.de","name_value":"office.mikoshi.de","id":18987111139,"entry_timestamp":"2025-06-13T00:04:43.915","not_before":"2025-06-12T23:06:13","not_after":"2025-09-10T23:06:12","serial_number":"051acaa08d5d89e6f4063edabca209961196","result_count":2},{"issuer_ca_id":295815,"issuer_name":"C=US, O=Let's Encrypt, CN=R11","common_name":"office.mikoshi.de","name_value":"office.mikoshi.de","id":17831462745,"entry_timestamp":"2025-04-14T00:16:05.147","not_before":"2025-04-13T23:17:32","not_after":"2025-07-12T23:17:31","serial_number":"054ddaf61e4b9f57e8d56a9497df9149c395","result_count":2},{"issuer_ca_id":295815,"issuer_name":"C=US, O=Let's Encrypt, CN=R11","common_name":"office.mikoshi.de","name_value":"office.mikoshi.de","id":17831369811,"entry_timestamp":"2025-04-14T00:16:03.009","not_before":"2025-04-13T23:17:32","not_after":"2025-07-12T23:17:31","serial_number":"054ddaf61e4b9f57e8d56a9497df9149c395","result_count":2},{"issuer_ca_id":295814,"issuer_name":"C=US, O=Let's Encrypt, CN=R10","common_name":"office.mikoshi.de","name_value":"office.mikoshi.de","id":17170808669,"entry_timestamp":"2025-02-13T00:01:46.473","not_before":"2025-02-12T23:03:15","not_after":"2025-05-13T23:03:14","serial_number":"03deb0895b1825adbbbaf9addcd01dd92799","result_count":2},{"issuer_ca_id":295814,"issuer_name":"C=US, O=Let's Encrypt, CN=R10","common_name":"office.mikoshi.de","name_value":"office.mikoshi.de","id":16720296902,"entry_timestamp":"2025-02-13T00:01:45.743","not_before":"2025-02-12T23:03:15","not_after":"2025-05-13T23:03:14","serial_number":"03deb0895b1825adbbbaf9addcd01dd92799","result_count":2},{"issuer_ca_id":295814,"issuer_name":"C=US, O=Let's Encrypt, CN=R10","common_name":"office.mikoshi.de","name_value":"office.mikoshi.de","id":17122359365,"entry_timestamp":"2025-02-09T15:19:36.715","not_before":"2025-02-09T14:21:06","not_after":"2025-05-10T14:21:05","serial_number":"04610182dee49a266a3d43aadacfd0b41e27","result_count":2},{"issuer_ca_id":295814,"issuer_name":"C=US, O=Let's Encrypt, CN=R10","common_name":"office.mikoshi.de","name_value":"office.mikoshi.de","id":16635528699,"entry_timestamp":"2025-02-09T15:19:36.337","not_before":"2025-02-09T14:21:06","not_after":"2025-05-10T14:21:05","serial_number":"04610182dee49a266a3d43aadacfd0b41e27","result_count":2}]}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -1 +0,0 @@
{"domain":"proxy.piped.mikoshi.de","first_cached":"2025-09-14T22:45:40.325331+00:00","last_upstream_query":"2025-09-15T15:38:51.713680+00:00","upstream_query_count":2,"certificates":[{"issuer_ca_id":295819,"issuer_name":"C=US, O=Let's Encrypt, CN=E6","common_name":"proxy.piped.mikoshi.de","name_value":"proxy.piped.mikoshi.de","id":20189220475,"entry_timestamp":"2025-08-08T00:05:07.009","not_before":"2025-08-07T23:06:36","not_after":"2025-11-05T23:06:35","serial_number":"05c0d9d7f7cae49c673abcdb28c4412d78d6","result_count":2},{"issuer_ca_id":295819,"issuer_name":"C=US, O=Let's Encrypt, CN=E6","common_name":"proxy.piped.mikoshi.de","name_value":"proxy.piped.mikoshi.de","id":20189220702,"entry_timestamp":"2025-08-08T00:05:06.824","not_before":"2025-08-07T23:06:36","not_after":"2025-11-05T23:06:35","serial_number":"05c0d9d7f7cae49c673abcdb28c4412d78d6","result_count":2},{"issuer_ca_id":295819,"issuer_name":"C=US, O=Let's Encrypt, CN=E6","common_name":"proxy.piped.mikoshi.de","name_value":"proxy.piped.mikoshi.de","id":20060639877,"entry_timestamp":"2025-08-02T00:01:52.165","not_before":"2025-08-01T23:03:21","not_after":"2025-10-30T23:03:20","serial_number":"05cb1fd70bdfe7e07c8a952b4e089c39d1da","result_count":2},{"issuer_ca_id":295819,"issuer_name":"C=US, O=Let's Encrypt, CN=E6","common_name":"proxy.piped.mikoshi.de","name_value":"proxy.piped.mikoshi.de","id":20060638194,"entry_timestamp":"2025-08-02T00:01:51.846","not_before":"2025-08-01T23:03:21","not_after":"2025-10-30T23:03:20","serial_number":"05cb1fd70bdfe7e07c8a952b4e089c39d1da","result_count":2},{"issuer_ca_id":295810,"issuer_name":"C=US, O=Let's Encrypt, CN=E5","common_name":"proxy.piped.mikoshi.de","name_value":"proxy.piped.mikoshi.de","id":19929369417,"entry_timestamp":"2025-07-27T00:02:26.4","not_before":"2025-07-26T23:03:54","not_after":"2025-10-24T23:03:53","serial_number":"063f8984c7c967816e258a7216ecd1959f34","result_count":2},{"issuer_ca_id":295810,"issuer_name":"C=US, O=Let's Encrypt, CN=E5","common_name":"proxy.piped.mikoshi.de","name_value":"proxy.piped.mikoshi.de","id":19929369596,"entry_timestamp":"2025-07-27T00:02:24.492","not_before":"2025-07-26T23:03:54","not_after":"2025-10-24T23:03:53","serial_number":"063f8984c7c967816e258a7216ecd1959f34","result_count":2},{"issuer_ca_id":295819,"issuer_name":"C=US, O=Let's Encrypt, CN=E6","common_name":"proxy.piped.mikoshi.de","name_value":"proxy.piped.mikoshi.de","id":19803763772,"entry_timestamp":"2025-07-21T00:00:57.2","not_before":"2025-07-20T23:02:26","not_after":"2025-10-18T23:02:25","serial_number":"0572a8c3609d51428351eb07244bcd441072","result_count":2},{"issuer_ca_id":295819,"issuer_name":"C=US, O=Let's Encrypt, CN=E6","common_name":"proxy.piped.mikoshi.de","name_value":"proxy.piped.mikoshi.de","id":19803763758,"entry_timestamp":"2025-07-21T00:00:56.856","not_before":"2025-07-20T23:02:26","not_after":"2025-10-18T23:02:25","serial_number":"0572a8c3609d51428351eb07244bcd441072","result_count":2},{"issuer_ca_id":295819,"issuer_name":"C=US, O=Let's Encrypt, CN=E6","common_name":"proxy.piped.mikoshi.de","name_value":"proxy.piped.mikoshi.de","id":19668416256,"entry_timestamp":"2025-07-15T00:00:58.486","not_before":"2025-07-14T23:02:28","not_after":"2025-10-12T23:02:27","serial_number":"06664191409b60fb8f1241b999cd884247cb","result_count":2},{"issuer_ca_id":295819,"issuer_name":"C=US, O=Let's Encrypt, CN=E6","common_name":"proxy.piped.mikoshi.de","name_value":"proxy.piped.mikoshi.de","id":19668412981,"entry_timestamp":"2025-07-15T00:00:58.222","not_before":"2025-07-14T23:02:28","not_after":"2025-10-12T23:02:27","serial_number":"06664191409b60fb8f1241b999cd884247cb","result_count":2},{"issuer_ca_id":295819,"issuer_name":"C=US, O=Let's Encrypt, CN=E6","common_name":"proxy.piped.mikoshi.de","name_value":"proxy.piped.mikoshi.de","id":19523857935,"entry_timestamp":"2025-07-08T06:31:01.3","not_before":"2025-07-08T05:32:26","not_after":"2025-10-06T05:32:25","serial_number":"05def41b49262bc3c90ceef09a3c53fdb897","result_count":2},{"issuer_ca_id":295819,"issuer_name":"C=US, O=Let's Encrypt, CN=E6","common_name":"proxy.piped.mikoshi.de","name_value":"proxy.piped.mikoshi.de","id":19523855448,"entry_timestamp":"2025-07-08T06:30:56.952","not_before":"2025-07-08T05:32:26","not_after":"2025-10-06T05:32:25","serial_number":"05def41b49262bc3c90ceef09a3c53fdb897","result_count":2}]}

View File

@@ -1 +0,0 @@
{"domain":"push.mikoshi.de","first_cached":"2025-09-15T15:36:51.090852+00:00","last_upstream_query":"2025-09-15T15:36:51.090855+00:00","upstream_query_count":1,"certificates":[{"issuer_ca_id":295815,"issuer_name":"C=US, O=Let's Encrypt, CN=R11","common_name":"push.mikoshi.de","name_value":"push.mikoshi.de","id":20275820653,"entry_timestamp":"2025-08-12T00:06:47.342","not_before":"2025-08-11T23:08:16","not_after":"2025-11-09T23:08:15","serial_number":"052026f4f3142d63bd9ca3feae317ece4ee9","result_count":2},{"issuer_ca_id":295815,"issuer_name":"C=US, O=Let's Encrypt, CN=R11","common_name":"push.mikoshi.de","name_value":"push.mikoshi.de","id":20275820169,"entry_timestamp":"2025-08-12T00:06:47.109","not_before":"2025-08-11T23:08:16","not_after":"2025-11-09T23:08:15","serial_number":"052026f4f3142d63bd9ca3feae317ece4ee9","result_count":2},{"issuer_ca_id":295814,"issuer_name":"C=US, O=Let's Encrypt, CN=R10","common_name":"push.mikoshi.de","name_value":"push.mikoshi.de","id":18987077850,"entry_timestamp":"2025-06-13T00:04:10.192","not_before":"2025-06-12T23:05:37","not_after":"2025-09-10T23:05:36","serial_number":"0546092d0c32d96eb7fcf0ce30e5e65ea3e1","result_count":2},{"issuer_ca_id":295814,"issuer_name":"C=US, O=Let's Encrypt, CN=R10","common_name":"push.mikoshi.de","name_value":"push.mikoshi.de","id":18987099791,"entry_timestamp":"2025-06-13T00:04:07.918","not_before":"2025-06-12T23:05:37","not_after":"2025-09-10T23:05:36","serial_number":"0546092d0c32d96eb7fcf0ce30e5e65ea3e1","result_count":2},{"issuer_ca_id":295815,"issuer_name":"C=US, O=Let's Encrypt, CN=R11","common_name":"push.mikoshi.de","name_value":"push.mikoshi.de","id":17831474873,"entry_timestamp":"2025-04-14T00:14:50.26","not_before":"2025-04-13T23:16:19","not_after":"2025-07-12T23:16:18","serial_number":"0513fd56736b1233441a3275762b03fc9eb0","result_count":2},{"issuer_ca_id":295815,"issuer_name":"C=US, O=Let's Encrypt, CN=R11","common_name":"push.mikoshi.de","name_value":"push.mikoshi.de","id":17831474384,"entry_timestamp":"2025-04-14T00:14:50.004","not_before":"2025-04-13T23:16:19","not_after":"2025-07-12T23:16:18","serial_number":"0513fd56736b1233441a3275762b03fc9eb0","result_count":2},{"issuer_ca_id":295815,"issuer_name":"C=US, O=Let's Encrypt, CN=R11","common_name":"push.mikoshi.de","name_value":"push.mikoshi.de","id":17170801795,"entry_timestamp":"2025-02-13T00:01:17.002","not_before":"2025-02-12T23:02:46","not_after":"2025-05-13T23:02:45","serial_number":"03487570ab1eaa62f8f4c3b61a8b90eda732","result_count":2},{"issuer_ca_id":295815,"issuer_name":"C=US, O=Let's Encrypt, CN=R11","common_name":"push.mikoshi.de","name_value":"push.mikoshi.de","id":16715026255,"entry_timestamp":"2025-02-13T00:01:16.729","not_before":"2025-02-12T23:02:46","not_after":"2025-05-13T23:02:45","serial_number":"03487570ab1eaa62f8f4c3b61a8b90eda732","result_count":2},{"issuer_ca_id":295815,"issuer_name":"C=US, O=Let's Encrypt, CN=R11","common_name":"push.mikoshi.de","name_value":"push.mikoshi.de","id":17122309940,"entry_timestamp":"2025-02-09T15:17:17.076","not_before":"2025-02-09T14:18:46","not_after":"2025-05-10T14:18:45","serial_number":"047ea82614cb4449bda99fc1ba86eb49b5c8","result_count":2},{"issuer_ca_id":295815,"issuer_name":"C=US, O=Let's Encrypt, CN=R11","common_name":"push.mikoshi.de","name_value":"push.mikoshi.de","id":16635500733,"entry_timestamp":"2025-02-09T15:17:16.594","not_before":"2025-02-09T14:18:46","not_after":"2025-05-10T14:18:45","serial_number":"047ea82614cb4449bda99fc1ba86eb49b5c8","result_count":2}]}

File diff suppressed because one or more lines are too long

View File

@@ -1 +0,0 @@
{"domain":"s3.cc24.dev","first_cached":"2025-09-14T21:38:35.568153+00:00","last_upstream_query":"2025-09-14T21:38:35.568155+00:00","upstream_query_count":1,"certificates":[{"issuer_ca_id":295819,"issuer_name":"C=US, O=Let's Encrypt, CN=E6","common_name":"console.s3.cc24.dev","name_value":"console.s3.cc24.dev","id":20287575466,"entry_timestamp":"2025-08-12T12:55:37.077","not_before":"2025-08-12T11:57:05","not_after":"2025-11-10T11:57:04","serial_number":"066bdfa83088f8d7e67284da94dd5d122ed6","result_count":2},{"issuer_ca_id":295819,"issuer_name":"C=US, O=Let's Encrypt, CN=E6","common_name":"console.s3.cc24.dev","name_value":"console.s3.cc24.dev","id":20287575457,"entry_timestamp":"2025-08-12T12:55:36.75","not_before":"2025-08-12T11:57:05","not_after":"2025-11-10T11:57:04","serial_number":"066bdfa83088f8d7e67284da94dd5d122ed6","result_count":2},{"issuer_ca_id":295819,"issuer_name":"C=US, O=Let's Encrypt, CN=E6","common_name":"s3.cc24.dev","name_value":"s3.cc24.dev","id":20285693027,"entry_timestamp":"2025-08-12T10:58:41.611","not_before":"2025-08-12T10:00:11","not_after":"2025-11-10T10:00:10","serial_number":"06f0f73404258136977fdbfe4cf51db786a7","result_count":2},{"issuer_ca_id":295819,"issuer_name":"C=US, O=Let's Encrypt, CN=E6","common_name":"s3.cc24.dev","name_value":"s3.cc24.dev","id":20285693495,"entry_timestamp":"2025-08-12T10:58:41.366","not_before":"2025-08-12T10:00:11","not_after":"2025-11-10T10:00:10","serial_number":"06f0f73404258136977fdbfe4cf51db786a7","result_count":2}]}

View File

@@ -1 +0,0 @@
{"domain":"se.mikoshi.de","first_cached":"2025-09-14T22:37:29.207379+00:00","last_upstream_query":"2025-09-15T15:40:52.328157+00:00","upstream_query_count":2,"certificates":[{"issuer_ca_id":295815,"issuer_name":"C=US, O=Let's Encrypt, CN=R11","common_name":"se.mikoshi.de","name_value":"se.mikoshi.de","id":20296592765,"entry_timestamp":"2025-08-13T00:02:43.765","not_before":"2025-08-12T23:04:13","not_after":"2025-11-10T23:04:12","serial_number":"05688b90444fda4afff5208583d9b4c6b453","result_count":2},{"issuer_ca_id":295815,"issuer_name":"C=US, O=Let's Encrypt, CN=R11","common_name":"se.mikoshi.de","name_value":"se.mikoshi.de","id":20296592676,"entry_timestamp":"2025-08-13T00:02:43.253","not_before":"2025-08-12T23:04:13","not_after":"2025-11-10T23:04:12","serial_number":"05688b90444fda4afff5208583d9b4c6b453","result_count":2},{"issuer_ca_id":295814,"issuer_name":"C=US, O=Let's Encrypt, CN=R10","common_name":"se.mikoshi.de","name_value":"se.mikoshi.de","id":19007481148,"entry_timestamp":"2025-06-14T00:01:17.383","not_before":"2025-06-13T23:02:46","not_after":"2025-09-11T23:02:45","serial_number":"057f456b58a7ea34177d50585ea3b4561e6b","result_count":2},{"issuer_ca_id":295814,"issuer_name":"C=US, O=Let's Encrypt, CN=R10","common_name":"se.mikoshi.de","name_value":"se.mikoshi.de","id":19007493221,"entry_timestamp":"2025-06-14T00:01:17.049","not_before":"2025-06-13T23:02:46","not_after":"2025-09-11T23:02:45","serial_number":"057f456b58a7ea34177d50585ea3b4561e6b","result_count":2},{"issuer_ca_id":295815,"issuer_name":"C=US, O=Let's Encrypt, CN=R11","common_name":"se.mikoshi.de","name_value":"se.mikoshi.de","id":17850961291,"entry_timestamp":"2025-04-15T00:00:37.293","not_before":"2025-04-14T23:02:02","not_after":"2025-07-13T23:02:01","serial_number":"052c5b098d5fa135547d9e3d7f7496b63af6","result_count":2},{"issuer_ca_id":295815,"issuer_name":"C=US, O=Let's Encrypt, CN=R11","common_name":"se.mikoshi.de","name_value":"se.mikoshi.de","id":17850962036,"entry_timestamp":"2025-04-15T00:00:32.962","not_before":"2025-04-14T23:02:02","not_after":"2025-07-13T23:02:01","serial_number":"052c5b098d5fa135547d9e3d7f7496b63af6","result_count":2},{"issuer_ca_id":295815,"issuer_name":"C=US, O=Let's Encrypt, CN=R11","common_name":"se.mikoshi.de","name_value":"se.mikoshi.de","id":17170796076,"entry_timestamp":"2025-02-13T00:00:29.982","not_before":"2025-02-12T23:01:59","not_after":"2025-05-13T23:01:58","serial_number":"04ecdefe30d1b5ce4d3ebb91bbbb2257bd15","result_count":2},{"issuer_ca_id":295815,"issuer_name":"C=US, O=Let's Encrypt, CN=R11","common_name":"se.mikoshi.de","name_value":"se.mikoshi.de","id":16704095774,"entry_timestamp":"2025-02-13T00:00:29.674","not_before":"2025-02-12T23:01:59","not_after":"2025-05-13T23:01:58","serial_number":"04ecdefe30d1b5ce4d3ebb91bbbb2257bd15","result_count":2},{"issuer_ca_id":295815,"issuer_name":"C=US, O=Let's Encrypt, CN=R11","common_name":"se.mikoshi.de","name_value":"se.mikoshi.de","id":17122261002,"entry_timestamp":"2025-02-09T15:13:15.78","not_before":"2025-02-09T14:14:45","not_after":"2025-05-10T14:14:44","serial_number":"03972d789d00e59045e4f37eae917438e10a","result_count":2},{"issuer_ca_id":295815,"issuer_name":"C=US, O=Let's Encrypt, CN=R11","common_name":"se.mikoshi.de","name_value":"se.mikoshi.de","id":16635473126,"entry_timestamp":"2025-02-09T15:13:15.412","not_before":"2025-02-09T14:14:45","not_after":"2025-05-10T14:14:44","serial_number":"03972d789d00e59045e4f37eae917438e10a","result_count":2},{"issuer_ca_id":183267,"issuer_name":"C=US, O=Let's Encrypt, CN=R3","common_name":"se.mikoshi.de","name_value":"se.mikoshi.de","id":11490113222,"entry_timestamp":"2023-12-16T00:55:58.472","not_before":"2023-12-15T23:55:57","not_after":"2024-03-14T23:55:56","serial_number":"0386fd7fd921ad63f4805ad4f593819aa238","result_count":2},{"issuer_ca_id":183267,"issuer_name":"C=US, O=Let's Encrypt, CN=R3","common_name":"se.mikoshi.de","name_value":"se.mikoshi.de","id":11422214995,"entry_timestamp":"2023-12-16T00:55:57.647","not_before":"2023-12-15T23:55:57","not_after":"2024-03-14T23:55:56","serial_number":"0386fd7fd921ad63f4805ad4f593819aa238","result_count":2}]}

View File

@@ -1 +0,0 @@
{"domain":"signaling.mikoshi.de","first_cached":"2025-09-14T21:05:14.189157+00:00","last_upstream_query":"2025-09-15T15:36:14.904100+00:00","upstream_query_count":3,"certificates":[{"issuer_ca_id":295819,"issuer_name":"C=US, O=Let's Encrypt, CN=E6","common_name":"signaling.mikoshi.de","name_value":"signaling.mikoshi.de","id":19208276669,"entry_timestamp":"2025-06-23T18:21:11.885","not_before":"2025-06-23T17:22:40","not_after":"2025-09-21T17:22:39","serial_number":"0542fce9cb99bb1c1d18e5e452c90d850936","result_count":2},{"issuer_ca_id":295819,"issuer_name":"C=US, O=Let's Encrypt, CN=E6","common_name":"signaling.mikoshi.de","name_value":"signaling.mikoshi.de","id":19208276557,"entry_timestamp":"2025-06-23T18:21:11.215","not_before":"2025-06-23T17:22:40","not_after":"2025-09-21T17:22:39","serial_number":"0542fce9cb99bb1c1d18e5e452c90d850936","result_count":2},{"issuer_ca_id":295819,"issuer_name":"C=US, O=Let's Encrypt, CN=E6","common_name":"signaling.mikoshi.de","name_value":"signaling.mikoshi.de","id":19208272013,"entry_timestamp":"2025-06-23T18:20:29.619","not_before":"2025-06-23T17:21:56","not_after":"2025-09-21T17:21:55","serial_number":"0540be6c8cb99dcaa5492af7b934f40466f9","result_count":2},{"issuer_ca_id":295819,"issuer_name":"C=US, O=Let's Encrypt, CN=E6","common_name":"signaling.mikoshi.de","name_value":"signaling.mikoshi.de","id":19208263539,"entry_timestamp":"2025-06-23T18:20:26.82","not_before":"2025-06-23T17:21:56","not_after":"2025-09-21T17:21:55","serial_number":"0540be6c8cb99dcaa5492af7b934f40466f9","result_count":2},{"issuer_ca_id":295819,"issuer_name":"C=US, O=Let's Encrypt, CN=E6","common_name":"signaling.mikoshi.de","name_value":"signaling.mikoshi.de","id":17428224909,"entry_timestamp":"2025-03-23T15:21:03.771","not_before":"2025-03-23T14:22:33","not_after":"2025-06-21T14:22:32","serial_number":"0537513d69487cead5f018b5322aa54fb52e","result_count":2},{"issuer_ca_id":295819,"issuer_name":"C=US, O=Let's Encrypt, CN=E6","common_name":"signaling.mikoshi.de","name_value":"signaling.mikoshi.de","id":17346408492,"entry_timestamp":"2025-03-23T15:21:03.617","not_before":"2025-03-23T14:22:33","not_after":"2025-06-21T14:22:32","serial_number":"0537513d69487cead5f018b5322aa54fb52e","result_count":2},{"issuer_ca_id":295815,"issuer_name":"C=US, O=Let's Encrypt, CN=R11","common_name":"signaling.mikoshi.de","name_value":"signaling.mikoshi.de","id":17170806575,"entry_timestamp":"2025-02-13T00:01:39.507","not_before":"2025-02-12T23:03:07","not_after":"2025-05-13T23:03:06","serial_number":"04a3141d80551d2287647211445f32131b19","result_count":2},{"issuer_ca_id":295815,"issuer_name":"C=US, O=Let's Encrypt, CN=R11","common_name":"signaling.mikoshi.de","name_value":"signaling.mikoshi.de","id":16704105641,"entry_timestamp":"2025-02-13T00:01:37.463","not_before":"2025-02-12T23:03:07","not_after":"2025-05-13T23:03:06","serial_number":"04a3141d80551d2287647211445f32131b19","result_count":2},{"issuer_ca_id":295815,"issuer_name":"C=US, O=Let's Encrypt, CN=R11","common_name":"signaling.mikoshi.de","name_value":"signaling.mikoshi.de","id":17122350772,"entry_timestamp":"2025-02-09T15:19:01.645","not_before":"2025-02-09T14:20:31","not_after":"2025-05-10T14:20:30","serial_number":"0456c53707eac4c8e79109b09eb9257674ef","result_count":2},{"issuer_ca_id":295815,"issuer_name":"C=US, O=Let's Encrypt, CN=R11","common_name":"signaling.mikoshi.de","name_value":"signaling.mikoshi.de","id":16635514012,"entry_timestamp":"2025-02-09T15:19:01.438","not_before":"2025-02-09T14:20:31","not_after":"2025-05-10T14:20:30","serial_number":"0456c53707eac4c8e79109b09eb9257674ef","result_count":2}]}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -1 +0,0 @@
{"domain":"test.mikoshi.de","first_cached":"2025-09-14T22:38:58.849950+00:00","last_upstream_query":"2025-09-15T15:34:55.551888+00:00","upstream_query_count":2,"certificates":[{"issuer_ca_id":183267,"issuer_name":"C=US, O=Let's Encrypt, CN=R3","common_name":"test.mikoshi.de","name_value":"test.mikoshi.de","id":11527598498,"entry_timestamp":"2023-12-19T19:30:11.511","not_before":"2023-12-19T18:30:10","not_after":"2024-03-18T18:30:09","serial_number":"0460a2ce513e2971556b911e64d3c06c876d","result_count":2},{"issuer_ca_id":183267,"issuer_name":"C=US, O=Let's Encrypt, CN=R3","common_name":"test.mikoshi.de","name_value":"test.mikoshi.de","id":11448041639,"entry_timestamp":"2023-12-19T19:30:10.729","not_before":"2023-12-19T18:30:10","not_after":"2024-03-18T18:30:09","serial_number":"0460a2ce513e2971556b911e64d3c06c876d","result_count":2},{"issuer_ca_id":183267,"issuer_name":"C=US, O=Let's Encrypt, CN=R3","common_name":"test.mikoshi.de","name_value":"test.mikoshi.de","id":11487822748,"entry_timestamp":"2023-12-15T22:27:24.154","not_before":"2023-12-15T21:27:23","not_after":"2024-03-14T21:27:22","serial_number":"03524dd265a8db8b1d3b8ae9236457b06564","result_count":2},{"issuer_ca_id":183267,"issuer_name":"C=US, O=Let's Encrypt, CN=R3","common_name":"test.mikoshi.de","name_value":"test.mikoshi.de","id":11420685419,"entry_timestamp":"2023-12-15T22:27:23.743","not_before":"2023-12-15T21:27:23","not_after":"2024-03-14T21:27:22","serial_number":"03524dd265a8db8b1d3b8ae9236457b06564","result_count":2},{"issuer_ca_id":183267,"issuer_name":"C=US, O=Let's Encrypt, CN=R3","common_name":"test.mikoshi.de","name_value":"test.mikoshi.de","id":10845362810,"entry_timestamp":"2023-10-20T20:03:11.855","not_before":"2023-10-20T19:03:11","not_after":"2024-01-18T19:03:10","serial_number":"04fb05ec64b2614143f419dfe3c1e058a6f8","result_count":2},{"issuer_ca_id":183267,"issuer_name":"C=US, O=Let's Encrypt, CN=R3","common_name":"test.mikoshi.de","name_value":"test.mikoshi.de","id":10845356148,"entry_timestamp":"2023-10-20T20:03:11.585","not_before":"2023-10-20T19:03:11","not_after":"2024-01-18T19:03:10","serial_number":"04fb05ec64b2614143f419dfe3c1e058a6f8","result_count":2}]}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -1,32 +0,0 @@
{
"domain": "www.overcuriousity.org",
"first_cached": "2025-09-14T21:16:24.041839+00:00",
"last_upstream_query": "2025-09-15T19:08:25.160183+00:00",
"upstream_query_count": 3,
"certificates": [
{
"issuer_ca_id": 295819,
"issuer_name": "C=US, O=Let's Encrypt, CN=E6",
"common_name": "signaling.mikoshi.de",
"name_value": "www.overcuriousity.org",
"id": 19208272013,
"entry_timestamp": "2025-06-23T18:20:29.619",
"not_before": "2025-06-23T17:21:56",
"not_after": "2025-09-21T17:21:55",
"serial_number": "0540be6c8cb99dcaa5492af7b934f40466f9",
"result_count": 1
},
{
"issuer_ca_id": 295819,
"issuer_name": "C=US, O=Let's Encrypt, CN=E6",
"common_name": "signaling.mikoshi.de",
"name_value": "www.overcuriousity.org",
"id": 19208263539,
"entry_timestamp": "2025-06-23T18:20:26.82",
"not_before": "2025-06-23T17:21:56",
"not_after": "2025-09-21T17:21:55",
"serial_number": "0540be6c8cb99dcaa5492af7b934f40466f9",
"result_count": 1
}
]
}

View File

@@ -1 +0,0 @@
{"domain":"zap.mikoshi.de","first_cached":"2025-09-14T22:37:56.901178+00:00","last_upstream_query":"2025-09-15T15:36:02.901638+00:00","upstream_query_count":2,"certificates":[{"issuer_ca_id":295813,"issuer_name":"C=US, O=Let's Encrypt, CN=E7","common_name":"zap.mikoshi.de","name_value":"zap.mikoshi.de","id":20979146330,"entry_timestamp":"2025-09-13T00:01:36.857","not_before":"2025-09-12T23:03:06","not_after":"2025-12-11T23:03:05","serial_number":"060330123144270f9c8614ee282e43b5b676","result_count":2},{"issuer_ca_id":295813,"issuer_name":"C=US, O=Let's Encrypt, CN=E7","common_name":"zap.mikoshi.de","name_value":"zap.mikoshi.de","id":20979146321,"entry_timestamp":"2025-09-13T00:01:36.705","not_before":"2025-09-12T23:03:06","not_after":"2025-12-11T23:03:05","serial_number":"060330123144270f9c8614ee282e43b5b676","result_count":2},{"issuer_ca_id":295809,"issuer_name":"C=US, O=Let's Encrypt, CN=E8","common_name":"zap.mikoshi.de","name_value":"zap.mikoshi.de","id":20955786867,"entry_timestamp":"2025-09-12T00:00:06.78","not_before":"2025-09-11T23:01:36","not_after":"2025-12-10T23:01:35","serial_number":"069fdbfcf2023341872c23d4eadf03dbd600","result_count":2},{"issuer_ca_id":295809,"issuer_name":"C=US, O=Let's Encrypt, CN=E8","common_name":"zap.mikoshi.de","name_value":"zap.mikoshi.de","id":20955786725,"entry_timestamp":"2025-09-12T00:00:06.615","not_before":"2025-09-11T23:01:36","not_after":"2025-12-10T23:01:35","serial_number":"069fdbfcf2023341872c23d4eadf03dbd600","result_count":2},{"issuer_ca_id":295809,"issuer_name":"C=US, O=Let's Encrypt, CN=E8","common_name":"zap.mikoshi.de","name_value":"zap.mikoshi.de","id":20754243960,"entry_timestamp":"2025-09-03T00:01:13.766","not_before":"2025-09-02T23:02:41","not_after":"2025-12-01T23:02:40","serial_number":"05c8fbc52b5d8c0ca2089679fd1574503cf0","result_count":2},{"issuer_ca_id":295809,"issuer_name":"C=US, O=Let's Encrypt, CN=E8","common_name":"zap.mikoshi.de","name_value":"zap.mikoshi.de","id":20754243261,"entry_timestamp":"2025-09-03T00:01:11.505","not_before":"2025-09-02T23:02:41","not_after":"2025-12-01T23:02:40","serial_number":"05c8fbc52b5d8c0ca2089679fd1574503cf0","result_count":2},{"issuer_ca_id":295813,"issuer_name":"C=US, O=Let's Encrypt, CN=E7","common_name":"zap.mikoshi.de","name_value":"zap.mikoshi.de","id":20539947210,"entry_timestamp":"2025-08-24T10:34:58.674","not_before":"2025-08-24T09:36:27","not_after":"2025-11-22T09:36:26","serial_number":"062deaf87750f6cf54f0027bbf6f9617447b","result_count":2},{"issuer_ca_id":295813,"issuer_name":"C=US, O=Let's Encrypt, CN=E7","common_name":"zap.mikoshi.de","name_value":"zap.mikoshi.de","id":20539914846,"entry_timestamp":"2025-08-24T10:34:58.16","not_before":"2025-08-24T09:36:27","not_after":"2025-11-22T09:36:26","serial_number":"062deaf87750f6cf54f0027bbf6f9617447b","result_count":2}]}

View File

@@ -1,3 +1,5 @@
# dnsrecon-reduced/config.py
""" """
Configuration management for DNSRecon tool. Configuration management for DNSRecon tool.
Handles API key storage, rate limiting, and default settings. Handles API key storage, rate limiting, and default settings.
@@ -19,27 +21,28 @@ class Config:
# --- General Settings --- # --- General Settings ---
self.default_recursion_depth = 2 self.default_recursion_depth = 2
self.default_timeout = 30 self.default_timeout = 60
self.max_concurrent_requests = 5 self.max_concurrent_requests = 1
self.large_entity_threshold = 100 self.large_entity_threshold = 100
self.max_retries_per_target = 8 self.max_retries_per_target = 8
self.cache_expiry_hours = 12
# --- Provider Caching Settings --- # --- Provider Caching Settings ---
self.cache_timeout_hours = 6 # Provider-specific cache timeout self.cache_timeout_hours = 6 # Provider-specific cache timeout
# --- Rate Limiting (requests per minute) --- # --- Rate Limiting (requests per minute) ---
self.rate_limits = { self.rate_limits = {
'crtsh': 30, 'crtsh': 5,
'shodan': 60, 'shodan': 60,
'dns': 100 'dns': 100,
'correlation': 0 # Set to 0 to make sure correlations run last
} }
# --- Provider Settings --- # --- Provider Settings ---
self.enabled_providers = { self.enabled_providers = {
'crtsh': True, 'crtsh': True,
'dns': True, 'dns': True,
'shodan': False 'shodan': False,
'correlation': True # Enable the new provider by default
} }
# --- Logging --- # --- Logging ---
@@ -67,7 +70,6 @@ class Config:
self.max_concurrent_requests = int(os.getenv('MAX_CONCURRENT_REQUESTS', self.max_concurrent_requests)) self.max_concurrent_requests = int(os.getenv('MAX_CONCURRENT_REQUESTS', self.max_concurrent_requests))
self.large_entity_threshold = int(os.getenv('LARGE_ENTITY_THRESHOLD', self.large_entity_threshold)) self.large_entity_threshold = int(os.getenv('LARGE_ENTITY_THRESHOLD', self.large_entity_threshold))
self.max_retries_per_target = int(os.getenv('MAX_RETRIES_PER_TARGET', self.max_retries_per_target)) self.max_retries_per_target = int(os.getenv('MAX_RETRIES_PER_TARGET', self.max_retries_per_target))
self.cache_expiry_hours = int(os.getenv('CACHE_EXPIRY_HOURS', self.cache_expiry_hours))
self.cache_timeout_hours = int(os.getenv('CACHE_TIMEOUT_HOURS', self.cache_timeout_hours)) self.cache_timeout_hours = int(os.getenv('CACHE_TIMEOUT_HOURS', self.cache_timeout_hours))
# Override Flask and session settings # Override Flask and session settings
@@ -85,6 +87,60 @@ class Config:
self.enabled_providers[provider] = True self.enabled_providers[provider] = True
return True return True
def set_provider_enabled(self, provider: str, enabled: bool) -> bool:
"""
Set provider enabled status for the session.
Args:
provider: Provider name
enabled: Whether the provider should be enabled
Returns:
True if the setting was applied successfully
"""
provider_key = provider.lower()
self.enabled_providers[provider_key] = enabled
return True
def get_provider_enabled(self, provider: str) -> bool:
"""
Get provider enabled status.
Args:
provider: Provider name
Returns:
True if the provider is enabled
"""
provider_key = provider.lower()
return self.enabled_providers.get(provider_key, True) # Default to enabled
def bulk_set_provider_settings(self, provider_settings: dict) -> dict:
"""
Set multiple provider settings at once.
Args:
provider_settings: Dict of provider_name -> {'enabled': bool, ...}
Returns:
Dict with results for each provider
"""
results = {}
for provider_name, settings in provider_settings.items():
provider_key = provider_name.lower()
try:
if 'enabled' in settings:
self.enabled_providers[provider_key] = settings['enabled']
results[provider_key] = {'success': True, 'enabled': settings['enabled']}
else:
results[provider_key] = {'success': False, 'error': 'No enabled setting provided'}
except Exception as e:
results[provider_key] = {'success': False, 'error': str(e)}
return results
def get_api_key(self, provider: str) -> Optional[str]: def get_api_key(self, provider: str) -> Optional[str]:
"""Get API key for a provider.""" """Get API key for a provider."""
return self.api_keys.get(provider) return self.api_keys.get(provider)

View File

@@ -1,8 +1,10 @@
# core/graph_manager.py # dnsrecon-reduced/core/graph_manager.py
""" """
Graph data model for DNSRecon using NetworkX. Graph data model for DNSRecon using NetworkX.
Manages in-memory graph storage with confidence scoring and forensic metadata. Manages in-memory graph storage with confidence scoring and forensic metadata.
Now fully compatible with the unified ProviderResult data model.
FIXED: Added proper pickle support to prevent weakref serialization errors.
""" """
import re import re
from datetime import datetime, timezone from datetime import datetime, timezone
@@ -16,7 +18,8 @@ class NodeType(Enum):
"""Enumeration of supported node types.""" """Enumeration of supported node types."""
DOMAIN = "domain" DOMAIN = "domain"
IP = "ip" IP = "ip"
ASN = "asn" ISP = "isp"
CA = "ca"
LARGE_ENTITY = "large_entity" LARGE_ENTITY = "large_entity"
CORRELATION_OBJECT = "correlation_object" CORRELATION_OBJECT = "correlation_object"
@@ -28,6 +31,8 @@ class GraphManager:
""" """
Thread-safe graph manager for DNSRecon infrastructure mapping. Thread-safe graph manager for DNSRecon infrastructure mapping.
Uses NetworkX for in-memory graph storage with confidence scoring. Uses NetworkX for in-memory graph storage with confidence scoring.
Compatible with unified ProviderResult data model.
FIXED: Added proper pickle support to handle NetworkX graph serialization.
""" """
def __init__(self): def __init__(self):
@@ -35,178 +40,88 @@ class GraphManager:
self.graph = nx.DiGraph() self.graph = nx.DiGraph()
self.creation_time = datetime.now(timezone.utc).isoformat() self.creation_time = datetime.now(timezone.utc).isoformat()
self.last_modified = self.creation_time self.last_modified = self.creation_time
self.correlation_index = {}
# Compile regex for date filtering for efficiency
self.date_pattern = re.compile(r'^\d{4}-\d{2}-\d{2}[ T]\d{2}:\d{2}:\d{2}')
def __getstate__(self): def __getstate__(self):
"""Prepare GraphManager for pickling, excluding compiled regex.""" """Prepare GraphManager for pickling by converting NetworkX graph to serializable format."""
state = self.__dict__.copy() state = self.__dict__.copy()
# Compiled regex patterns are not always picklable
if 'date_pattern' in state: # Convert NetworkX graph to a serializable format
del state['date_pattern'] if hasattr(self, 'graph') and self.graph:
# Extract all nodes with their data
nodes_data = {}
for node_id, attrs in self.graph.nodes(data=True):
nodes_data[node_id] = dict(attrs)
# Extract all edges with their data
edges_data = []
for source, target, attrs in self.graph.edges(data=True):
edges_data.append({
'source': source,
'target': target,
'attributes': dict(attrs)
})
# Replace the NetworkX graph with serializable data
state['_graph_nodes'] = nodes_data
state['_graph_edges'] = edges_data
del state['graph']
return state return state
def __setstate__(self, state): def __setstate__(self, state):
"""Restore GraphManager state and recompile regex.""" """Restore GraphManager after unpickling by reconstructing NetworkX graph."""
# Restore basic attributes
self.__dict__.update(state) self.__dict__.update(state)
self.date_pattern = re.compile(r'^\d{4}-\d{2}-\d{2}[ T]\d{2}:\d{2}:\d{2}')
def _update_correlation_index(self, node_id: str, data: Any, path: List[str] = [], parent_attr: str = ""): # Reconstruct NetworkX graph from serializable data
"""Recursively traverse metadata and add hashable values to the index with better path tracking.""" self.graph = nx.DiGraph()
if path is None:
path = []
if isinstance(data, dict): # Restore nodes
for key, value in data.items(): if hasattr(self, '_graph_nodes'):
self._update_correlation_index(node_id, value, path + [key], key) for node_id, attrs in self._graph_nodes.items():
elif isinstance(data, list): self.graph.add_node(node_id, **attrs)
for i, item in enumerate(data): del self._graph_nodes
# Instead of just using [i], include the parent attribute context
list_path_component = f"[{i}]" if not parent_attr else f"{parent_attr}[{i}]"
self._update_correlation_index(node_id, item, path + [list_path_component], parent_attr)
else:
self._add_to_correlation_index(node_id, data, ".".join(path), parent_attr)
def _add_to_correlation_index(self, node_id: str, value: Any, path_str: str, parent_attr: str = ""): # Restore edges
"""Add a hashable value to the correlation index, filtering out noise.""" if hasattr(self, '_graph_edges'):
if not isinstance(value, (str, int, float, bool)) or value is None: for edge_data in self._graph_edges:
return self.graph.add_edge(
edge_data['source'],
edge_data['target'],
**edge_data['attributes']
)
del self._graph_edges
# Ignore certain paths that contain noisy, non-unique identifiers def add_node(self, node_id: str, node_type: NodeType, attributes: Optional[List[Dict[str, Any]]] = None,
if any(keyword in path_str.lower() for keyword in ['count', 'total', 'timestamp', 'date']):
return
# Filter out common low-entropy values and date-like strings
if isinstance(value, str):
# FIXED: Prevent correlation on date/time strings.
if self.date_pattern.match(value):
return
if len(value) < 4 or value.lower() in ['true', 'false', 'unknown', 'none', 'crt.sh']:
return
elif isinstance(value, int) and (abs(value) < 1024 or abs(value) > 65535):
return # Ignore small integers and common port numbers
elif isinstance(value, bool):
return # Ignore boolean values
# Add the valuable correlation data to the index
if value not in self.correlation_index:
self.correlation_index[value] = {}
if node_id not in self.correlation_index[value]:
self.correlation_index[value][node_id] = []
# Store both the full path and the parent attribute for better edge labeling
correlation_entry = {
'path': path_str,
'parent_attr': parent_attr,
'meaningful_attr': self._extract_meaningful_attribute(path_str, parent_attr)
}
if correlation_entry not in self.correlation_index[value][node_id]:
self.correlation_index[value][node_id].append(correlation_entry)
def _extract_meaningful_attribute(self, path_str: str, parent_attr: str = "") -> str:
"""Extract the most meaningful attribute name from a path string."""
if not path_str:
return "unknown"
path_parts = path_str.split('.')
# Look for the last non-array-index part
for part in reversed(path_parts):
# Skip array indices like [0], [1], etc.
if not (part.startswith('[') and part.endswith(']') and part[1:-1].isdigit()):
# Clean up compound names like "hostnames[0]" to just "hostnames"
clean_part = re.sub(r'\[\d+\]$', '', part)
if clean_part:
return clean_part
# Fallback to parent attribute if available
if parent_attr:
return parent_attr
# Last resort - use the first meaningful part
for part in path_parts:
if not (part.startswith('[') and part.endswith(']') and part[1:-1].isdigit()):
clean_part = re.sub(r'\[\d+\]$', '', part)
if clean_part:
return clean_part
return "correlation"
def _check_for_correlations(self, new_node_id: str, data: Any, path: List[str] = [], parent_attr: str = "") -> List[Dict]:
"""Recursively traverse metadata to find correlations with existing data."""
if path is None:
path = []
all_correlations = []
if isinstance(data, dict):
for key, value in data.items():
if key == 'source': # Avoid correlating on the provider name
continue
all_correlations.extend(self._check_for_correlations(new_node_id, value, path + [key], key))
elif isinstance(data, list):
for i, item in enumerate(data):
list_path_component = f"[{i}]" if not parent_attr else f"{parent_attr}[{i}]"
all_correlations.extend(self._check_for_correlations(new_node_id, item, path + [list_path_component], parent_attr))
else:
value = data
if value in self.correlation_index:
existing_nodes_with_paths = self.correlation_index[value]
unique_nodes = set(existing_nodes_with_paths.keys())
unique_nodes.add(new_node_id)
if len(unique_nodes) < 2:
return all_correlations # Correlation must involve at least two distinct nodes
new_source = {
'node_id': new_node_id,
'path': ".".join(path),
'parent_attr': parent_attr,
'meaningful_attr': self._extract_meaningful_attribute(".".join(path), parent_attr)
}
all_sources = [new_source]
for node_id, path_entries in existing_nodes_with_paths.items():
for entry in path_entries:
if isinstance(entry, dict):
all_sources.append({
'node_id': node_id,
'path': entry['path'],
'parent_attr': entry.get('parent_attr', ''),
'meaningful_attr': entry.get('meaningful_attr', self._extract_meaningful_attribute(entry['path'], entry.get('parent_attr', '')))
})
else:
# Handle legacy string-only entries
all_sources.append({
'node_id': node_id,
'path': str(entry),
'parent_attr': '',
'meaningful_attr': self._extract_meaningful_attribute(str(entry))
})
all_correlations.append({
'value': value,
'sources': all_sources,
'nodes': list(unique_nodes)
})
return all_correlations
def add_node(self, node_id: str, node_type: NodeType, attributes: Optional[Dict[str, Any]] = None,
description: str = "", metadata: Optional[Dict[str, Any]] = None) -> bool: description: str = "", metadata: Optional[Dict[str, Any]] = None) -> bool:
"""Add a node to the graph, update attributes, and process correlations.""" """
Add a node to the graph, update attributes, and process correlations.
Now compatible with unified data model - attributes are dictionaries from converted StandardAttribute objects.
"""
is_new_node = not self.graph.has_node(node_id) is_new_node = not self.graph.has_node(node_id)
if is_new_node: if is_new_node:
self.graph.add_node(node_id, type=node_type.value, self.graph.add_node(node_id, type=node_type.value,
added_timestamp=datetime.now(timezone.utc).isoformat(), added_timestamp=datetime.now(timezone.utc).isoformat(),
attributes=attributes or {}, attributes=attributes or [], # Store as a list from the start
description=description, description=description,
metadata=metadata or {}) metadata=metadata or {})
else: else:
# Safely merge new attributes into existing attributes # Safely merge new attributes into the existing list of attributes
if attributes: if attributes:
existing_attributes = self.graph.nodes[node_id].get('attributes', {}) existing_attributes = self.graph.nodes[node_id].get('attributes', [])
existing_attributes.update(attributes)
# Handle cases where old data might still be in dictionary format
if not isinstance(existing_attributes, list):
existing_attributes = []
# Create a set of existing attribute names for efficient duplicate checking
existing_attr_names = {attr['name'] for attr in existing_attributes}
for new_attr in attributes:
if new_attr['name'] not in existing_attr_names:
existing_attributes.append(new_attr)
existing_attr_names.add(new_attr['name'])
self.graph.nodes[node_id]['attributes'] = existing_attributes self.graph.nodes[node_id]['attributes'] = existing_attributes
if description: if description:
self.graph.nodes[node_id]['description'] = description self.graph.nodes[node_id]['description'] = description
@@ -215,186 +130,22 @@ class GraphManager:
existing_metadata.update(metadata) existing_metadata.update(metadata)
self.graph.nodes[node_id]['metadata'] = existing_metadata self.graph.nodes[node_id]['metadata'] = existing_metadata
if attributes and node_type != NodeType.CORRELATION_OBJECT:
correlations = self._check_for_correlations(node_id, attributes)
for corr in correlations:
value = corr['value']
# STEP 1: Substring check against all existing nodes
if self._correlation_value_matches_existing_node(value):
# Skip creating correlation node - would be redundant
continue
eligible_nodes = set(corr['nodes'])
if len(eligible_nodes) < 2:
# Need at least 2 nodes to create a correlation
continue
# STEP 3: Check for existing correlation node with same connection pattern
correlation_nodes_with_pattern = self._find_correlation_nodes_with_same_pattern(eligible_nodes)
if correlation_nodes_with_pattern:
# STEP 4: Merge with existing correlation node
target_correlation_node = correlation_nodes_with_pattern[0]
self._merge_correlation_values(target_correlation_node, value, corr)
else:
# STEP 5: Create new correlation node for eligible nodes only
correlation_node_id = f"corr_{abs(hash(str(sorted(eligible_nodes))))}"
self.add_node(correlation_node_id, NodeType.CORRELATION_OBJECT,
metadata={'values': [value], 'sources': corr['sources'],
'correlated_nodes': list(eligible_nodes)})
# Create edges from eligible nodes to this correlation node with better labeling
for c_node_id in eligible_nodes:
if self.graph.has_node(c_node_id):
# Find the best attribute name for this node
meaningful_attr = self._find_best_attribute_name_for_node(c_node_id, corr['sources'])
relationship_type = f"c_{meaningful_attr}"
self.add_edge(c_node_id, correlation_node_id, relationship_type, confidence_score=0.9)
self._update_correlation_index(node_id, attributes)
self.last_modified = datetime.now(timezone.utc).isoformat() self.last_modified = datetime.now(timezone.utc).isoformat()
return is_new_node return is_new_node
def _find_best_attribute_name_for_node(self, node_id: str, sources: List[Dict]) -> str:
"""Find the best attribute name for a correlation edge by looking at the sources."""
node_sources = [s for s in sources if s['node_id'] == node_id]
if not node_sources:
return "correlation"
# Use the meaningful_attr if available
for source in node_sources:
meaningful_attr = source.get('meaningful_attr')
if meaningful_attr and meaningful_attr != "unknown":
return meaningful_attr
# Fallback to parent_attr
for source in node_sources:
parent_attr = source.get('parent_attr')
if parent_attr:
return parent_attr
# Last resort - extract from path
for source in node_sources:
path = source.get('path', '')
if path:
extracted = self._extract_meaningful_attribute(path)
if extracted != "unknown":
return extracted
return "correlation"
def _has_direct_edge_bidirectional(self, node_a: str, node_b: str) -> bool:
"""
Check if there's a direct edge between two nodes in either direction.
Returns True if node_a→node_b OR node_b→node_a exists.
"""
return (self.graph.has_edge(node_a, node_b) or
self.graph.has_edge(node_b, node_a))
def _correlation_value_matches_existing_node(self, correlation_value: str) -> bool:
"""
Check if correlation value contains any existing node ID as substring.
Returns True if match found (correlation node should NOT be created).
"""
correlation_str = str(correlation_value).lower()
# Check against all existing nodes
for existing_node_id in self.graph.nodes():
if existing_node_id.lower() in correlation_str:
return True
return False
def _find_correlation_nodes_with_same_pattern(self, node_set: set) -> List[str]:
"""
Find existing correlation nodes that have the exact same pattern of connected nodes.
Returns list of correlation node IDs with matching patterns.
"""
correlation_nodes = self.get_nodes_by_type(NodeType.CORRELATION_OBJECT)
matching_nodes = []
for corr_node_id in correlation_nodes:
# Get all nodes connected to this correlation node
connected_nodes = set()
# Add all predecessors (nodes pointing TO the correlation node)
connected_nodes.update(self.graph.predecessors(corr_node_id))
# Add all successors (nodes pointed TO by the correlation node)
connected_nodes.update(self.graph.successors(corr_node_id))
# Check if the pattern matches exactly
if connected_nodes == node_set:
matching_nodes.append(corr_node_id)
return matching_nodes
def _merge_correlation_values(self, target_node_id: str, new_value: Any, corr_data: Dict) -> None:
"""
Merge a new correlation value into an existing correlation node.
Uses same logic as large entity merging.
"""
if not self.graph.has_node(target_node_id):
return
target_metadata = self.graph.nodes[target_node_id]['metadata']
# Get existing values (ensure it's a list)
existing_values = target_metadata.get('values', [])
if not isinstance(existing_values, list):
existing_values = [existing_values]
# Add new value if not already present
if new_value not in existing_values:
existing_values.append(new_value)
# Merge sources
existing_sources = target_metadata.get('sources', [])
new_sources = corr_data.get('sources', [])
# Create set of unique sources based on (node_id, path) tuples
source_set = set()
for source in existing_sources + new_sources:
source_tuple = (source['node_id'], source.get('path', ''))
source_set.add(source_tuple)
# Convert back to list of dictionaries
merged_sources = [{'node_id': nid, 'path': path} for nid, path in source_set]
# Update metadata
target_metadata.update({
'values': existing_values,
'sources': merged_sources,
'correlated_nodes': list(set(target_metadata.get('correlated_nodes', []) + corr_data.get('nodes', []))),
'merge_count': len(existing_values),
'last_merge_timestamp': datetime.now(timezone.utc).isoformat()
})
# Update description to reflect merged nature
value_count = len(existing_values)
node_count = len(target_metadata['correlated_nodes'])
self.graph.nodes[target_node_id]['description'] = (
f"Correlation container with {value_count} merged values "
f"across {node_count} nodes"
)
def add_edge(self, source_id: str, target_id: str, relationship_type: str, def add_edge(self, source_id: str, target_id: str, relationship_type: str,
confidence_score: float = 0.5, source_provider: str = "unknown", confidence_score: float = 0.5, source_provider: str = "unknown",
raw_data: Optional[Dict[str, Any]] = None) -> bool: raw_data: Optional[Dict[str, Any]] = None) -> bool:
"""Add or update an edge between two nodes, ensuring nodes exist.""" """
UPDATED: Add or update an edge between two nodes with raw relationship labels.
"""
if not self.graph.has_node(source_id) or not self.graph.has_node(target_id): if not self.graph.has_node(source_id) or not self.graph.has_node(target_id):
return False return False
new_confidence = confidence_score new_confidence = confidence_score
if relationship_type.startswith("c_"): # UPDATED: Use raw relationship type - no formatting
edge_label = relationship_type edge_label = relationship_type
else:
edge_label = f"{source_provider}_{relationship_type}"
if self.graph.has_edge(source_id, target_id): if self.graph.has_edge(source_id, target_id):
# If edge exists, update confidence if the new score is higher. # If edge exists, update confidence if the new score is higher.
@@ -404,7 +155,7 @@ class GraphManager:
self.graph.edges[source_id, target_id]['updated_by'] = source_provider self.graph.edges[source_id, target_id]['updated_by'] = source_provider
return False return False
# Add a new edge with all attributes. # Add a new edge with raw attributes
self.graph.add_edge(source_id, target_id, self.graph.add_edge(source_id, target_id,
relationship_type=edge_label, relationship_type=edge_label,
confidence_score=new_confidence, confidence_score=new_confidence,
@@ -422,18 +173,6 @@ class GraphManager:
# Remove node from the graph (NetworkX handles removing connected edges) # Remove node from the graph (NetworkX handles removing connected edges)
self.graph.remove_node(node_id) self.graph.remove_node(node_id)
# Clean up the correlation index
keys_to_delete = []
for value, nodes in self.correlation_index.items():
if node_id in nodes:
del nodes[node_id]
if not nodes: # If no other nodes are associated with this value, remove it
keys_to_delete.append(value)
for key in keys_to_delete:
if key in self.correlation_index:
del self.correlation_index[key]
self.last_modified = datetime.now(timezone.utc).isoformat() self.last_modified = datetime.now(timezone.utc).isoformat()
return True return True
@@ -449,70 +188,65 @@ class GraphManager:
"""Get all nodes of a specific type.""" """Get all nodes of a specific type."""
return [n for n, d in self.graph.nodes(data=True) if d.get('type') == node_type.value] return [n for n, d in self.graph.nodes(data=True) if d.get('type') == node_type.value]
def get_neighbors(self, node_id: str) -> List[str]:
"""Get all unique neighbors (predecessors and successors) for a node."""
if not self.graph.has_node(node_id):
return []
return list(set(self.graph.predecessors(node_id)) | set(self.graph.successors(node_id)))
def get_high_confidence_edges(self, min_confidence: float = 0.8) -> List[Tuple[str, str, Dict]]: def get_high_confidence_edges(self, min_confidence: float = 0.8) -> List[Tuple[str, str, Dict]]:
"""Get edges with confidence score above a given threshold.""" """Get edges with confidence score above a given threshold."""
return [(u, v, d) for u, v, d in self.graph.edges(data=True) return [(u, v, d) for u, v, d in self.graph.edges(data=True)
if d.get('confidence_score', 0) >= min_confidence] if d.get('confidence_score', 0) >= min_confidence]
def get_graph_data(self) -> Dict[str, Any]: def get_graph_data(self) -> Dict[str, Any]:
"""Export graph data formatted for frontend visualization.""" """
Export graph data formatted for frontend visualization.
SIMPLIFIED: No certificate styling - frontend handles all visual styling.
"""
nodes = [] nodes = []
for node_id, attrs in self.graph.nodes(data=True): for node_id, attrs in self.graph.nodes(data=True):
node_data = {'id': node_id, 'label': node_id, 'type': attrs.get('type', 'unknown'), node_data = {
'attributes': attrs.get('attributes', {}), 'id': node_id,
'label': node_id,
'type': attrs.get('type', 'unknown'),
'attributes': attrs.get('attributes', []), # Raw attributes list
'description': attrs.get('description', ''), 'description': attrs.get('description', ''),
'metadata': attrs.get('metadata', {}), 'metadata': attrs.get('metadata', {}),
'added_timestamp': attrs.get('added_timestamp')} 'added_timestamp': attrs.get('added_timestamp'),
# Customize node appearance based on type and attributes 'max_depth_reached': attrs.get('metadata', {}).get('max_depth_reached', False)
node_type = node_data['type'] }
attributes = node_data['attributes']
if node_type == 'domain' and attributes.get('certificates', {}).get('has_valid_cert') is False:
node_data['color'] = {'background': '#c7c7c7', 'border': '#999'} # Gray for invalid cert
# Add incoming and outgoing edges to node data # Add incoming and outgoing edges to node data
if self.graph.has_node(node_id): if self.graph.has_node(node_id):
node_data['incoming_edges'] = [{'from': u, 'data': d} for u, _, d in self.graph.in_edges(node_id, data=True)] node_data['incoming_edges'] = [
node_data['outgoing_edges'] = [{'to': v, 'data': d} for _, v, d in self.graph.out_edges(node_id, data=True)] {'from': u, 'data': d} for u, _, d in self.graph.in_edges(node_id, data=True)
]
node_data['outgoing_edges'] = [
{'to': v, 'data': d} for _, v, d in self.graph.out_edges(node_id, data=True)
]
nodes.append(node_data) nodes.append(node_data)
edges = [] edges = []
for source, target, attrs in self.graph.edges(data=True): for source, target, attrs in self.graph.edges(data=True):
edges.append({'from': source, 'to': target, edges.append({
'from': source,
'to': target,
'label': attrs.get('relationship_type', ''), 'label': attrs.get('relationship_type', ''),
'confidence_score': attrs.get('confidence_score', 0), 'confidence_score': attrs.get('confidence_score', 0),
'source_provider': attrs.get('source_provider', ''), 'source_provider': attrs.get('source_provider', ''),
'discovery_timestamp': attrs.get('discovery_timestamp')}) 'discovery_timestamp': attrs.get('discovery_timestamp')
})
return { return {
'nodes': nodes, 'edges': edges, 'nodes': nodes,
'edges': edges,
'statistics': self.get_statistics()['basic_metrics'] 'statistics': self.get_statistics()['basic_metrics']
} }
def export_json(self) -> Dict[str, Any]:
"""Export complete graph data as a JSON-serializable dictionary."""
graph_data = nx.node_link_data(self.graph) # Use NetworkX's built-in robust serializer
return {
'export_metadata': {
'export_timestamp': datetime.now(timezone.utc).isoformat(),
'graph_creation_time': self.creation_time,
'last_modified': self.last_modified,
'total_nodes': self.get_node_count(),
'total_edges': self.get_edge_count(),
'graph_format': 'dnsrecon_v1_nodeling'
},
'graph': graph_data,
'statistics': self.get_statistics()
}
def _get_confidence_distribution(self) -> Dict[str, int]: def _get_confidence_distribution(self) -> Dict[str, int]:
"""Get distribution of edge confidence scores.""" """Get distribution of edge confidence scores with empty graph handling."""
distribution = {'high': 0, 'medium': 0, 'low': 0} distribution = {'high': 0, 'medium': 0, 'low': 0}
# FIXED: Handle empty graph case
if self.get_edge_count() == 0:
return distribution
for _, _, data in self.graph.edges(data=True): for _, _, data in self.graph.edges(data=True):
confidence = data.get('confidence_score', 0) confidence = data.get('confidence_score', 0)
if confidence >= 0.8: if confidence >= 0.8:
@@ -524,27 +258,46 @@ class GraphManager:
return distribution return distribution
def get_statistics(self) -> Dict[str, Any]: def get_statistics(self) -> Dict[str, Any]:
"""Get comprehensive statistics about the graph.""" """Get comprehensive statistics about the graph with proper empty graph handling."""
stats = {'basic_metrics': {'total_nodes': self.get_node_count(),
'total_edges': self.get_edge_count(), # FIXED: Handle empty graph case properly
node_count = self.get_node_count()
edge_count = self.get_edge_count()
stats = {
'basic_metrics': {
'total_nodes': node_count,
'total_edges': edge_count,
'creation_time': self.creation_time, 'creation_time': self.creation_time,
'last_modified': self.last_modified}, 'last_modified': self.last_modified
'node_type_distribution': {}, 'relationship_type_distribution': {}, },
'node_type_distribution': {},
'relationship_type_distribution': {},
'confidence_distribution': self._get_confidence_distribution(), 'confidence_distribution': self._get_confidence_distribution(),
'provider_distribution': {}} 'provider_distribution': {}
# Calculate distributions }
# FIXED: Only calculate distributions if we have data
if node_count > 0:
# Calculate node type distributions
for node_type in NodeType: for node_type in NodeType:
stats['node_type_distribution'][node_type.value] = self.get_nodes_by_type(node_type).__len__() count = len(self.get_nodes_by_type(node_type))
if count > 0: # Only include types that exist
stats['node_type_distribution'][node_type.value] = count
if edge_count > 0:
# Calculate edge distributions
for _, _, data in self.graph.edges(data=True): for _, _, data in self.graph.edges(data=True):
rel_type = data.get('relationship_type', 'unknown') rel_type = data.get('relationship_type', 'unknown')
stats['relationship_type_distribution'][rel_type] = stats['relationship_type_distribution'].get(rel_type, 0) + 1 stats['relationship_type_distribution'][rel_type] = stats['relationship_type_distribution'].get(rel_type, 0) + 1
provider = data.get('source_provider', 'unknown') provider = data.get('source_provider', 'unknown')
stats['provider_distribution'][provider] = stats['provider_distribution'].get(provider, 0) + 1 stats['provider_distribution'][provider] = stats['provider_distribution'].get(provider, 0) + 1
return stats return stats
def clear(self) -> None: def clear(self) -> None:
"""Clear all nodes, edges, and indices from the graph.""" """Clear all nodes and edges from the graph."""
self.graph.clear() self.graph.clear()
self.correlation_index.clear()
self.creation_time = datetime.now(timezone.utc).isoformat() self.creation_time = datetime.now(timezone.utc).isoformat()
self.last_modified = self.creation_time self.last_modified = self.creation_time

View File

@@ -40,6 +40,7 @@ class ForensicLogger:
""" """
Thread-safe forensic logging system for DNSRecon. Thread-safe forensic logging system for DNSRecon.
Maintains detailed audit trail of all reconnaissance activities. Maintains detailed audit trail of all reconnaissance activities.
FIXED: Enhanced pickle support to prevent weakref issues in logging handlers.
""" """
def __init__(self, session_id: str = ""): def __init__(self, session_id: str = ""):
@@ -50,7 +51,7 @@ class ForensicLogger:
session_id: Unique identifier for this reconnaissance session session_id: Unique identifier for this reconnaissance session
""" """
self.session_id = session_id or self._generate_session_id() self.session_id = session_id or self._generate_session_id()
#self.lock = threading.Lock() self.lock = threading.Lock()
# Initialize audit trail storage # Initialize audit trail storage
self.api_requests: List[APIRequest] = [] self.api_requests: List[APIRequest] = []
@@ -65,43 +66,75 @@ class ForensicLogger:
'target_domains': set() 'target_domains': set()
} }
# Configure standard logger # Configure standard logger with simple setup to avoid weakrefs
self.logger = logging.getLogger(f'dnsrecon.{self.session_id}') self.logger = logging.getLogger(f'dnsrecon.{self.session_id}')
self.logger.setLevel(logging.INFO) self.logger.setLevel(logging.INFO)
# Create formatter for structured logging # Create minimal formatter
formatter = logging.Formatter( formatter = logging.Formatter(
'%(asctime)s - %(name)s - %(levelname)s - %(message)s' '%(asctime)s - %(name)s - %(levelname)s - %(message)s'
) )
# Add console handler if not already present # Add console handler only if not already present (avoid duplicate handlers)
if not self.logger.handlers: if not self.logger.handlers:
console_handler = logging.StreamHandler() console_handler = logging.StreamHandler()
console_handler.setFormatter(formatter) console_handler.setFormatter(formatter)
self.logger.addHandler(console_handler) self.logger.addHandler(console_handler)
def __getstate__(self): def __getstate__(self):
"""Prepare ForensicLogger for pickling by excluding unpicklable objects.""" """
FIXED: Prepare ForensicLogger for pickling by excluding problematic objects.
"""
state = self.__dict__.copy() state = self.__dict__.copy()
# Remove the unpickleable 'logger' attribute
if 'logger' in state: # Remove potentially unpickleable attributes that may contain weakrefs
del state['logger'] unpicklable_attrs = ['logger', 'lock']
for attr in unpicklable_attrs:
if attr in state:
del state[attr]
# Convert sets to lists for JSON serialization compatibility
if 'session_metadata' in state:
metadata = state['session_metadata'].copy()
if 'providers_used' in metadata and isinstance(metadata['providers_used'], set):
metadata['providers_used'] = list(metadata['providers_used'])
if 'target_domains' in metadata and isinstance(metadata['target_domains'], set):
metadata['target_domains'] = list(metadata['target_domains'])
state['session_metadata'] = metadata
return state return state
def __setstate__(self, state): def __setstate__(self, state):
"""Restore ForensicLogger after unpickling by reconstructing logger.""" """
FIXED: Restore ForensicLogger after unpickling by reconstructing components.
"""
self.__dict__.update(state) self.__dict__.update(state)
# Re-initialize the 'logger' attribute
# Re-initialize threading lock
self.lock = threading.Lock()
# Re-initialize logger with minimal setup
self.logger = logging.getLogger(f'dnsrecon.{self.session_id}') self.logger = logging.getLogger(f'dnsrecon.{self.session_id}')
self.logger.setLevel(logging.INFO) self.logger.setLevel(logging.INFO)
formatter = logging.Formatter( formatter = logging.Formatter(
'%(asctime)s - %(name)s - %(levelname)s - %(message)s' '%(asctime)s - %(name)s - %(levelname)s - %(message)s'
) )
# Only add handler if not already present
if not self.logger.handlers: if not self.logger.handlers:
console_handler = logging.StreamHandler() console_handler = logging.StreamHandler()
console_handler.setFormatter(formatter) console_handler.setFormatter(formatter)
self.logger.addHandler(console_handler) self.logger.addHandler(console_handler)
# Convert lists back to sets if needed
if 'session_metadata' in self.__dict__:
metadata = self.session_metadata
if 'providers_used' in metadata and isinstance(metadata['providers_used'], list):
metadata['providers_used'] = set(metadata['providers_used'])
if 'target_domains' in metadata and isinstance(metadata['target_domains'], list):
metadata['target_domains'] = set(metadata['target_domains'])
def _generate_session_id(self) -> str: def _generate_session_id(self) -> str:
"""Generate unique session identifier.""" """Generate unique session identifier."""
return f"dnsrecon_{datetime.now(timezone.utc).strftime('%Y%m%d_%H%M%S')}" return f"dnsrecon_{datetime.now(timezone.utc).strftime('%Y%m%d_%H%M%S')}"
@@ -140,6 +173,7 @@ class ForensicLogger:
discovery_context=discovery_context discovery_context=discovery_context
) )
with self.lock:
self.api_requests.append(api_request) self.api_requests.append(api_request)
self.session_metadata['total_requests'] += 1 self.session_metadata['total_requests'] += 1
self.session_metadata['providers_used'].add(provider) self.session_metadata['providers_used'].add(provider)
@@ -147,11 +181,15 @@ class ForensicLogger:
if target_indicator: if target_indicator:
self.session_metadata['target_domains'].add(target_indicator) self.session_metadata['target_domains'].add(target_indicator)
# Log to standard logger # Log to standard logger with error handling
try:
if error: if error:
self.logger.error(f"API Request Failed - {provider}: {url} - {error}") self.logger.error(f"API Request Failed - {provider}: {url}")
else: else:
self.logger.info(f"API Request - {provider}: {url} - Status: {status_code}") self.logger.info(f"API Request - {provider}: {url} - Status: {status_code}")
except Exception:
# If logging fails, continue without breaking the application
pass
def log_relationship_discovery(self, source_node: str, target_node: str, def log_relationship_discovery(self, source_node: str, target_node: str,
relationship_type: str, confidence_score: float, relationship_type: str, confidence_score: float,
@@ -180,29 +218,44 @@ class ForensicLogger:
discovery_method=discovery_method discovery_method=discovery_method
) )
with self.lock:
self.relationships.append(relationship) self.relationships.append(relationship)
self.session_metadata['total_relationships'] += 1 self.session_metadata['total_relationships'] += 1
# Log to standard logger with error handling
try:
self.logger.info( self.logger.info(
f"Relationship Discovered - {source_node} -> {target_node} " f"Relationship Discovered - {source_node} -> {target_node} "
f"({relationship_type}) - Confidence: {confidence_score:.2f} - Provider: {provider}" f"({relationship_type}) - Confidence: {confidence_score:.2f} - Provider: {provider}"
) )
except Exception:
# If logging fails, continue without breaking the application
pass
def log_scan_start(self, target_domain: str, recursion_depth: int, def log_scan_start(self, target_domain: str, recursion_depth: int,
enabled_providers: List[str]) -> None: enabled_providers: List[str]) -> None:
"""Log the start of a reconnaissance scan.""" """Log the start of a reconnaissance scan."""
try:
self.logger.info(f"Scan Started - Target: {target_domain}, Depth: {recursion_depth}") self.logger.info(f"Scan Started - Target: {target_domain}, Depth: {recursion_depth}")
self.logger.info(f"Enabled Providers: {', '.join(enabled_providers)}") self.logger.info(f"Enabled Providers: {', '.join(enabled_providers)}")
with self.lock:
self.session_metadata['target_domains'].add(target_domain) self.session_metadata['target_domains'].add(target_domain)
except Exception:
pass
def log_scan_complete(self) -> None: def log_scan_complete(self) -> None:
"""Log the completion of a reconnaissance scan.""" """Log the completion of a reconnaissance scan."""
with self.lock:
self.session_metadata['end_time'] = datetime.now(timezone.utc).isoformat() self.session_metadata['end_time'] = datetime.now(timezone.utc).isoformat()
# Convert sets to lists for serialization
self.session_metadata['providers_used'] = list(self.session_metadata['providers_used']) self.session_metadata['providers_used'] = list(self.session_metadata['providers_used'])
self.session_metadata['target_domains'] = list(self.session_metadata['target_domains']) self.session_metadata['target_domains'] = list(self.session_metadata['target_domains'])
try:
self.logger.info(f"Scan Complete - Session: {self.session_id}") self.logger.info(f"Scan Complete - Session: {self.session_id}")
except Exception:
pass
def export_audit_trail(self) -> Dict[str, Any]: def export_audit_trail(self) -> Dict[str, Any]:
""" """
@@ -211,6 +264,7 @@ class ForensicLogger:
Returns: Returns:
Dictionary containing complete session audit trail Dictionary containing complete session audit trail
""" """
with self.lock:
return { return {
'session_metadata': self.session_metadata.copy(), 'session_metadata': self.session_metadata.copy(),
'api_requests': [asdict(req) for req in self.api_requests], 'api_requests': [asdict(req) for req in self.api_requests],
@@ -226,7 +280,13 @@ class ForensicLogger:
Dictionary containing summary statistics Dictionary containing summary statistics
""" """
provider_stats = {} provider_stats = {}
for provider in self.session_metadata['providers_used']:
# Ensure providers_used is a set for iteration
providers_used = self.session_metadata['providers_used']
if isinstance(providers_used, list):
providers_used = set(providers_used)
for provider in providers_used:
provider_requests = [req for req in self.api_requests if req.provider == provider] provider_requests = [req for req in self.api_requests if req.provider == provider]
provider_relationships = [rel for rel in self.relationships if rel.provider == provider] provider_relationships = [rel for rel in self.relationships if rel.provider == provider]

107
core/provider_result.py Normal file
View File

@@ -0,0 +1,107 @@
# dnsrecon-reduced/core/provider_result.py
"""
Unified data model for DNSRecon passive reconnaissance.
Standardizes the data structure across all providers to ensure consistent processing.
"""
from typing import Any, Optional, List, Dict
from dataclasses import dataclass, field
from datetime import datetime, timezone
@dataclass
class StandardAttribute:
"""A unified data structure for a single piece of information about a node."""
target_node: str
name: str
value: Any
type: str
provider: str
confidence: float
timestamp: datetime = field(default_factory=lambda: datetime.now(timezone.utc))
metadata: Optional[Dict[str, Any]] = field(default_factory=dict)
def __post_init__(self):
"""Validate the attribute after initialization."""
if not isinstance(self.confidence, (int, float)) or not 0.0 <= self.confidence <= 1.0:
raise ValueError(f"Confidence must be between 0.0 and 1.0, got {self.confidence}")
@dataclass
class Relationship:
"""A unified data structure for a directional link between two nodes."""
source_node: str
target_node: str
relationship_type: str
confidence: float
provider: str
timestamp: datetime = field(default_factory=lambda: datetime.now(timezone.utc))
raw_data: Optional[Dict[str, Any]] = field(default_factory=dict)
def __post_init__(self):
"""Validate the relationship after initialization."""
if not isinstance(self.confidence, (int, float)) or not 0.0 <= self.confidence <= 1.0:
raise ValueError(f"Confidence must be between 0.0 and 1.0, got {self.confidence}")
@dataclass
class ProviderResult:
"""A container for all data returned by a provider from a single query."""
attributes: List[StandardAttribute] = field(default_factory=list)
relationships: List[Relationship] = field(default_factory=list)
def add_attribute(self, target_node: str, name: str, value: Any, attr_type: str,
provider: str, confidence: float = 0.8,
metadata: Optional[Dict[str, Any]] = None) -> None:
"""Helper method to add an attribute to the result."""
self.attributes.append(StandardAttribute(
target_node=target_node,
name=name,
value=value,
type=attr_type,
provider=provider,
confidence=confidence,
metadata=metadata or {}
))
def add_relationship(self, source_node: str, target_node: str, relationship_type: str,
provider: str, confidence: float = 0.8,
raw_data: Optional[Dict[str, Any]] = None) -> None:
"""Helper method to add a relationship to the result."""
self.relationships.append(Relationship(
source_node=source_node,
target_node=target_node,
relationship_type=relationship_type,
confidence=confidence,
provider=provider,
raw_data=raw_data or {}
))
def get_discovered_nodes(self) -> set:
"""Get all unique node identifiers discovered in this result."""
nodes = set()
# Add nodes from relationships
for rel in self.relationships:
nodes.add(rel.source_node)
nodes.add(rel.target_node)
# Add nodes from attributes
for attr in self.attributes:
nodes.add(attr.target_node)
return nodes
def get_relationship_count(self) -> int:
"""Get the total number of relationships in this result."""
return len(self.relationships)
def get_attribute_count(self) -> int:
"""Get the total number of attributes in this result."""
return len(self.attributes)
##TODO
#def is_large_entity(self, threshold: int) -> bool:
# """Check if this result qualifies as a large entity based on relationship count."""
# return self.get_relationship_count() > threshold

28
core/rate_limiter.py Normal file
View File

@@ -0,0 +1,28 @@
# dnsrecon-reduced/core/rate_limiter.py
import time
class GlobalRateLimiter:
def __init__(self, redis_client):
self.redis = redis_client
def is_rate_limited(self, key, limit, period):
"""
Check if a key is rate-limited.
"""
now = time.time()
key = f"rate_limit:{key}"
# Remove old timestamps
self.redis.zremrangebyscore(key, 0, now - period)
# Check the count
count = self.redis.zcard(key)
if count >= limit:
return True
# Add new timestamp
self.redis.zadd(key, {now: now})
self.redis.expire(key, period)
return False

File diff suppressed because it is too large Load Diff

View File

@@ -5,18 +5,16 @@ import time
import uuid import uuid
import redis import redis
import pickle import pickle
from typing import Dict, Optional, Any, List from typing import Dict, Optional, Any
import copy
from core.scanner import Scanner from core.scanner import Scanner
from config import config from config import config
# WARNING: Using pickle can be a security risk if the data source is not trusted.
# In this case, we are only serializing/deserializing our own trusted Scanner objects,
# which is generally safe. Do not unpickle data from untrusted sources.
class SessionManager: class SessionManager:
""" """
Manages multiple scanner instances for concurrent user sessions using Redis. FIXED: Manages multiple scanner instances for concurrent user sessions using Redis.
Enhanced to properly maintain WebSocket connections throughout scan lifecycle.
""" """
def __init__(self, session_timeout_minutes: int = 0): def __init__(self, session_timeout_minutes: int = 0):
@@ -28,7 +26,13 @@ class SessionManager:
self.redis_client = redis.StrictRedis(db=0, decode_responses=False) self.redis_client = redis.StrictRedis(db=0, decode_responses=False)
self.session_timeout = session_timeout_minutes * 60 # Convert to seconds self.session_timeout = session_timeout_minutes * 60 # Convert to seconds
self.lock = threading.Lock() # Lock for local operations, Redis handles atomic ops self.lock = threading.Lock()
# FIXED: Add a creation lock to prevent race conditions
self.creation_lock = threading.Lock()
# Track active socketio connections per session
self.active_socketio_connections = {}
# Start cleanup thread # Start cleanup thread
self.cleanup_thread = threading.Thread(target=self._cleanup_loop, daemon=True) self.cleanup_thread = threading.Thread(target=self._cleanup_loop, daemon=True)
@@ -40,7 +44,7 @@ class SessionManager:
"""Prepare SessionManager for pickling.""" """Prepare SessionManager for pickling."""
state = self.__dict__.copy() state = self.__dict__.copy()
# Exclude unpickleable attributes - Redis client and threading objects # Exclude unpickleable attributes - Redis client and threading objects
unpicklable_attrs = ['lock', 'cleanup_thread', 'redis_client'] unpicklable_attrs = ['lock', 'cleanup_thread', 'redis_client', 'creation_lock', 'active_socketio_connections']
for attr in unpicklable_attrs: for attr in unpicklable_attrs:
if attr in state: if attr in state:
del state[attr] del state[attr]
@@ -50,9 +54,10 @@ class SessionManager:
"""Restore SessionManager after unpickling.""" """Restore SessionManager after unpickling."""
self.__dict__.update(state) self.__dict__.update(state)
# Re-initialize unpickleable attributes # Re-initialize unpickleable attributes
import redis
self.redis_client = redis.StrictRedis(db=0, decode_responses=False) self.redis_client = redis.StrictRedis(db=0, decode_responses=False)
self.lock = threading.Lock() self.lock = threading.Lock()
self.creation_lock = threading.Lock()
self.active_socketio_connections = {}
self.cleanup_thread = threading.Thread(target=self._cleanup_loop, daemon=True) self.cleanup_thread = threading.Thread(target=self._cleanup_loop, daemon=True)
self.cleanup_thread.start() self.cleanup_thread.start()
@@ -64,20 +69,70 @@ class SessionManager:
"""Generates the Redis key for a session's stop signal.""" """Generates the Redis key for a session's stop signal."""
return f"dnsrecon:stop:{session_id}" return f"dnsrecon:stop:{session_id}"
def create_session(self) -> str: def register_socketio_connection(self, session_id: str, socketio) -> None:
""" """
Create a new user session and store it in Redis. FIXED: Register a socketio connection for a session.
This ensures the connection is maintained throughout the session lifecycle.
""" """
with self.lock:
self.active_socketio_connections[session_id] = socketio
print(f"Registered socketio connection for session {session_id}")
def get_socketio_connection(self, session_id: str):
"""
FIXED: Get the active socketio connection for a session.
"""
with self.lock:
return self.active_socketio_connections.get(session_id)
def _prepare_scanner_for_storage(self, scanner: Scanner, session_id: str) -> Scanner:
"""
FIXED: Prepare scanner for storage by ensuring proper cleanup of unpicklable objects.
Now preserves socketio connection info for restoration.
"""
# Set the session ID on the scanner for cross-process stop signal management
scanner.session_id = session_id
# FIXED: Don't set socketio to None if we want to preserve real-time updates
# Instead, we'll restore it when loading the scanner
scanner.socketio = None
# Force cleanup of any threading objects that might cause issues
if hasattr(scanner, 'stop_event'):
scanner.stop_event = None
if hasattr(scanner, 'scan_thread'):
scanner.scan_thread = None
if hasattr(scanner, 'executor'):
scanner.executor = None
if hasattr(scanner, 'status_logger_thread'):
scanner.status_logger_thread = None
if hasattr(scanner, 'status_logger_stop_event'):
scanner.status_logger_stop_event = None
return scanner
def create_session(self, socketio=None) -> str:
"""
FIXED: Create a new user session with enhanced WebSocket management.
"""
# FIXED: Use creation lock to prevent race conditions
with self.creation_lock:
session_id = str(uuid.uuid4()) session_id = str(uuid.uuid4())
print(f"=== CREATING SESSION {session_id} IN REDIS ===") print(f"=== CREATING SESSION {session_id} IN REDIS ===")
# FIXED: Register socketio connection first
if socketio:
self.register_socketio_connection(session_id, socketio)
try: try:
from core.session_config import create_session_config from core.session_config import create_session_config
session_config = create_session_config() session_config = create_session_config()
scanner_instance = Scanner(session_config=session_config)
# Set the session ID on the scanner for cross-process stop signal management # Create scanner WITHOUT socketio to avoid weakref issues
scanner_instance.session_id = session_id scanner_instance = Scanner(session_config=session_config, socketio=None)
# Prepare scanner for storage (removes problematic objects)
scanner_instance = self._prepare_scanner_for_storage(scanner_instance, session_id)
session_data = { session_data = {
'scanner': scanner_instance, 'scanner': scanner_instance,
@@ -87,22 +142,37 @@ class SessionManager:
'status': 'active' 'status': 'active'
} }
# Serialize the entire session data dictionary using pickle # Test serialization before storing to catch issues early
serialized_data = pickle.dumps(session_data) try:
test_serialization = pickle.dumps(session_data)
print(f"Session serialization test successful ({len(test_serialization)} bytes)")
except Exception as pickle_error:
print(f"PICKLE TEST FAILED: {pickle_error}")
# Try to identify the problematic object
for key, value in session_data.items():
try:
pickle.dumps(value)
print(f" {key}: OK")
except Exception as item_error:
print(f" {key}: FAILED - {item_error}")
raise pickle_error
# Store in Redis # Store in Redis
session_key = self._get_session_key(session_id) session_key = self._get_session_key(session_id)
self.redis_client.setex(session_key, self.session_timeout, serialized_data) self.redis_client.setex(session_key, self.session_timeout, test_serialization)
# Initialize stop signal as False # Initialize stop signal as False
stop_key = self._get_stop_signal_key(session_id) stop_key = self._get_stop_signal_key(session_id)
self.redis_client.setex(stop_key, self.session_timeout, b'0') self.redis_client.setex(stop_key, self.session_timeout, b'0')
print(f"Session {session_id} stored in Redis with stop signal initialized") print(f"Session {session_id} stored in Redis with stop signal initialized")
print(f"Session has {len(scanner_instance.providers)} providers: {[p.get_name() for p in scanner_instance.providers]}")
return session_id return session_id
except Exception as e: except Exception as e:
print(f"ERROR: Failed to create session {session_id}: {e}") print(f"ERROR: Failed to create session {session_id}: {e}")
import traceback
traceback.print_exc()
raise raise
def set_stop_signal(self, session_id: str) -> bool: def set_stop_signal(self, session_id: str) -> bool:
@@ -172,31 +242,63 @@ class SessionManager:
# Ensure the scanner has the correct session ID for stop signal checking # Ensure the scanner has the correct session ID for stop signal checking
if 'scanner' in session_data and session_data['scanner']: if 'scanner' in session_data and session_data['scanner']:
session_data['scanner'].session_id = session_id session_data['scanner'].session_id = session_id
# FIXED: Restore socketio connection from our registry
socketio_conn = self.get_socketio_connection(session_id)
if socketio_conn:
session_data['scanner'].socketio = socketio_conn
print(f"Restored socketio connection for session {session_id}")
else:
print(f"No socketio connection found for session {session_id}")
session_data['scanner'].socketio = None
return session_data return session_data
return None return None
except Exception as e: except Exception as e:
print(f"ERROR: Failed to get session data for {session_id}: {e}") print(f"ERROR: Failed to get session data for {session_id}: {e}")
import traceback
traceback.print_exc()
return None return None
def _save_session_data(self, session_id: str, session_data: Dict[str, Any]) -> bool: def _save_session_data(self, session_id: str, session_data: Dict[str, Any]) -> bool:
""" """
Serializes and saves session data back to Redis with updated TTL. Serializes and saves session data back to Redis with updated TTL.
FIXED: Now preserves socketio connection during storage.
Returns: Returns:
bool: True if save was successful bool: True if save was successful
""" """
try: try:
session_key = self._get_session_key(session_id) session_key = self._get_session_key(session_id)
serialized_data = pickle.dumps(session_data)
# Create a deep copy to avoid modifying the original scanner object
session_data_to_save = copy.deepcopy(session_data)
# Prepare scanner for storage if it exists
if 'scanner' in session_data_to_save and session_data_to_save['scanner']:
# FIXED: Preserve the original socketio connection before preparing for storage
original_socketio = session_data_to_save['scanner'].socketio
session_data_to_save['scanner'] = self._prepare_scanner_for_storage(
session_data_to_save['scanner'],
session_id
)
# FIXED: If we had a socketio connection, make sure it's registered
if original_socketio and session_id not in self.active_socketio_connections:
self.register_socketio_connection(session_id, original_socketio)
serialized_data = pickle.dumps(session_data_to_save)
result = self.redis_client.setex(session_key, self.session_timeout, serialized_data) result = self.redis_client.setex(session_key, self.session_timeout, serialized_data)
return result return result
except Exception as e: except Exception as e:
print(f"ERROR: Failed to save session data for {session_id}: {e}") print(f"ERROR: Failed to save session data for {session_id}: {e}")
import traceback
traceback.print_exc()
return False return False
def update_session_scanner(self, session_id: str, scanner: 'Scanner') -> bool: def update_session_scanner(self, session_id: str, scanner: 'Scanner') -> bool:
""" """
Updates just the scanner object in a session with immediate persistence. FIXED: Updates just the scanner object in a session with immediate persistence.
Now maintains socketio connection throughout the update process.
Returns: Returns:
bool: True if update was successful bool: True if update was successful
@@ -204,15 +306,28 @@ class SessionManager:
try: try:
session_data = self._get_session_data(session_id) session_data = self._get_session_data(session_id)
if session_data: if session_data:
# Ensure scanner has the session ID # FIXED: Preserve socketio connection before preparing for storage
scanner.session_id = session_id original_socketio = scanner.socketio
# Prepare scanner for storage
scanner = self._prepare_scanner_for_storage(scanner, session_id)
session_data['scanner'] = scanner session_data['scanner'] = scanner
session_data['last_activity'] = time.time() session_data['last_activity'] = time.time()
# FIXED: Restore socketio connection after preparation
if original_socketio:
self.register_socketio_connection(session_id, original_socketio)
session_data['scanner'].socketio = original_socketio
# Immediately save to Redis for GUI updates # Immediately save to Redis for GUI updates
success = self._save_session_data(session_id, session_data) success = self._save_session_data(session_id, session_data)
if success: if success:
print(f"Scanner state updated for session {session_id} (status: {scanner.status})") # Only log occasionally to reduce noise
if hasattr(self, '_last_update_log'):
if time.time() - self._last_update_log > 5: # Log every 5 seconds max
self._last_update_log = time.time()
else:
self._last_update_log = time.time()
else: else:
print(f"WARNING: Failed to save scanner state for session {session_id}") print(f"WARNING: Failed to save scanner state for session {session_id}")
return success return success
@@ -221,6 +336,8 @@ class SessionManager:
return False return False
except Exception as e: except Exception as e:
print(f"ERROR: Failed to update scanner for session {session_id}: {e}") print(f"ERROR: Failed to update scanner for session {session_id}: {e}")
import traceback
traceback.print_exc()
return False return False
def update_scanner_status(self, session_id: str, status: str) -> bool: def update_scanner_status(self, session_id: str, status: str) -> bool:
@@ -253,7 +370,7 @@ class SessionManager:
def get_session(self, session_id: str) -> Optional[Scanner]: def get_session(self, session_id: str) -> Optional[Scanner]:
""" """
Get scanner instance for a session from Redis with session ID management. FIXED: Get scanner instance for a session from Redis with proper socketio restoration.
""" """
if not session_id: if not session_id:
return None return None
@@ -272,6 +389,15 @@ class SessionManager:
# Ensure the scanner can check the Redis-based stop signal # Ensure the scanner can check the Redis-based stop signal
scanner.session_id = session_id scanner.session_id = session_id
# FIXED: Restore socketio connection from our registry
socketio_conn = self.get_socketio_connection(session_id)
if socketio_conn:
scanner.socketio = socketio_conn
print(f"✓ Restored socketio connection for session {session_id}")
else:
scanner.socketio = None
print(f"⚠️ No socketio connection found for session {session_id}")
return scanner return scanner
def get_session_status_only(self, session_id: str) -> Optional[str]: def get_session_status_only(self, session_id: str) -> Optional[str]:
@@ -323,6 +449,12 @@ class SessionManager:
# Wait a moment for graceful shutdown # Wait a moment for graceful shutdown
time.sleep(0.5) time.sleep(0.5)
# FIXED: Clean up socketio connection
with self.lock:
if session_id in self.active_socketio_connections:
del self.active_socketio_connections[session_id]
print(f"Cleaned up socketio connection for session {session_id}")
# Delete session data and stop signal from Redis # Delete session data and stop signal from Redis
session_key = self._get_session_key(session_id) session_key = self._get_session_key(session_id)
stop_key = self._get_stop_signal_key(session_id) stop_key = self._get_stop_signal_key(session_id)
@@ -334,6 +466,8 @@ class SessionManager:
except Exception as e: except Exception as e:
print(f"ERROR: Failed to terminate session {session_id}: {e}") print(f"ERROR: Failed to terminate session {session_id}: {e}")
import traceback
traceback.print_exc()
return False return False
def _cleanup_loop(self) -> None: def _cleanup_loop(self) -> None:
@@ -354,6 +488,12 @@ class SessionManager:
self.redis_client.delete(stop_key) self.redis_client.delete(stop_key)
print(f"Cleaned up orphaned stop signal for session {session_id}") print(f"Cleaned up orphaned stop signal for session {session_id}")
# Also clean up socketio connection
with self.lock:
if session_id in self.active_socketio_connections:
del self.active_socketio_connections[session_id]
print(f"Cleaned up orphaned socketio for session {session_id}")
except Exception as e: except Exception as e:
print(f"Error in cleanup loop: {e}") print(f"Error in cleanup loop: {e}")
@@ -377,14 +517,16 @@ class SessionManager:
return { return {
'total_active_sessions': active_sessions, 'total_active_sessions': active_sessions,
'running_scans': running_scans, 'running_scans': running_scans,
'total_stop_signals': len(stop_keys) 'total_stop_signals': len(stop_keys),
'active_socketio_connections': len(self.active_socketio_connections)
} }
except Exception as e: except Exception as e:
print(f"ERROR: Failed to get statistics: {e}") print(f"ERROR: Failed to get statistics: {e}")
return { return {
'total_active_sessions': 0, 'total_active_sessions': 0,
'running_scans': 0, 'running_scans': 0,
'total_stop_signals': 0 'total_stop_signals': 0,
'active_socketio_connections': 0
} }
# Global session manager instance # Global session manager instance

View File

@@ -3,17 +3,20 @@ Data provider modules for DNSRecon.
Contains implementations for various reconnaissance data sources. Contains implementations for various reconnaissance data sources.
""" """
from .base_provider import BaseProvider, RateLimiter from .base_provider import BaseProvider
from .crtsh_provider import CrtShProvider from .crtsh_provider import CrtShProvider
from .dns_provider import DNSProvider from .dns_provider import DNSProvider
from .shodan_provider import ShodanProvider from .shodan_provider import ShodanProvider
from .correlation_provider import CorrelationProvider
from core.rate_limiter import GlobalRateLimiter
__all__ = [ __all__ = [
'BaseProvider', 'BaseProvider',
'RateLimiter', 'GlobalRateLimiter',
'CrtShProvider', 'CrtShProvider',
'DNSProvider', 'DNSProvider',
'ShodanProvider' 'ShodanProvider',
'CorrelationProvider'
] ]
__version__ = "0.0.0-rc" __version__ = "0.0.0-rc"

View File

@@ -4,49 +4,18 @@ import time
import requests import requests
import threading import threading
from abc import ABC, abstractmethod from abc import ABC, abstractmethod
from typing import List, Dict, Any, Optional, Tuple from typing import Dict, Any, Optional
from core.logger import get_forensic_logger from core.logger import get_forensic_logger
from core.rate_limiter import GlobalRateLimiter
from core.provider_result import ProviderResult
class RateLimiter:
"""Simple rate limiter for API calls."""
def __init__(self, requests_per_minute: int):
"""
Initialize rate limiter.
Args:
requests_per_minute: Maximum requests allowed per minute
"""
self.requests_per_minute = requests_per_minute
self.min_interval = 60.0 / requests_per_minute
self.last_request_time = 0
def __getstate__(self):
"""RateLimiter is fully picklable, return full state."""
return self.__dict__.copy()
def __setstate__(self, state):
"""Restore RateLimiter state."""
self.__dict__.update(state)
def wait_if_needed(self) -> None:
"""Wait if necessary to respect rate limits."""
current_time = time.time()
time_since_last = current_time - self.last_request_time
if time_since_last < self.min_interval:
sleep_time = self.min_interval - time_since_last
time.sleep(sleep_time)
self.last_request_time = time.time()
class BaseProvider(ABC): class BaseProvider(ABC):
""" """
Abstract base class for all DNSRecon data providers. Abstract base class for all DNSRecon data providers.
Now supports session-specific configuration. Now supports session-specific configuration and returns standardized ProviderResult objects.
FIXED: Enhanced pickle support to prevent weakref serialization errors.
""" """
def __init__(self, name: str, rate_limit: int = 60, timeout: int = 30, session_config=None): def __init__(self, name: str, rate_limit: int = 60, timeout: int = 30, session_config=None):
@@ -68,11 +37,9 @@ class BaseProvider(ABC):
# Fallback to global config for backwards compatibility # Fallback to global config for backwards compatibility
from config import config as global_config from config import config as global_config
self.config = global_config self.config = global_config
actual_rate_limit = rate_limit
actual_timeout = timeout actual_timeout = timeout
self.name = name self.name = name
self.rate_limiter = RateLimiter(actual_rate_limit)
self.timeout = actual_timeout self.timeout = actual_timeout
self._local = threading.local() self._local = threading.local()
self.logger = get_forensic_logger() self.logger = get_forensic_logger()
@@ -87,22 +54,57 @@ class BaseProvider(ABC):
def __getstate__(self): def __getstate__(self):
"""Prepare BaseProvider for pickling by excluding unpicklable objects.""" """Prepare BaseProvider for pickling by excluding unpicklable objects."""
state = self.__dict__.copy() state = self.__dict__.copy()
# Exclude the unpickleable '_local' attribute and stop event
unpicklable_attrs = ['_local', '_stop_event'] # Exclude unpickleable attributes that may contain weakrefs
unpicklable_attrs = [
'_local', # Thread-local storage (contains requests.Session)
'_stop_event', # Threading event
'logger', # Logger may contain weakrefs in handlers
]
for attr in unpicklable_attrs: for attr in unpicklable_attrs:
if attr in state: if attr in state:
del state[attr] del state[attr]
# Also handle any potential weakrefs in the config object
if 'config' in state and hasattr(state['config'], '__getstate__'):
# If config has its own pickle support, let it handle itself
pass
elif 'config' in state:
# Otherwise, ensure config doesn't contain unpicklable objects
try:
# Test if config can be pickled
import pickle
pickle.dumps(state['config'])
except (TypeError, AttributeError):
# If config can't be pickled, we'll recreate it during unpickling
state['_config_class'] = type(state['config']).__name__
del state['config']
return state return state
def __setstate__(self, state): def __setstate__(self, state):
"""Restore BaseProvider after unpickling by reconstructing threading objects.""" """Restore BaseProvider after unpickling by reconstructing threading objects."""
self.__dict__.update(state) self.__dict__.update(state)
# Re-initialize the '_local' attribute and stop event
# Re-initialize unpickleable attributes
self._local = threading.local() self._local = threading.local()
self._stop_event = None self._stop_event = None
self.logger = get_forensic_logger()
# Recreate config if it was removed during pickling
if not hasattr(self, 'config') and hasattr(self, '_config_class'):
if self._config_class == 'Config':
from config import config as global_config
self.config = global_config
elif self._config_class == 'SessionConfig':
from core.session_config import create_session_config
self.config = create_session_config()
del self._config_class
@property @property
def session(self): def session(self):
"""Get or create thread-local requests session."""
if not hasattr(self._local, 'session'): if not hasattr(self._local, 'session'):
self._local.session = requests.Session() self._local.session = requests.Session()
self._local.session.headers.update({ self._local.session.headers.update({
@@ -136,7 +138,7 @@ class BaseProvider(ABC):
pass pass
@abstractmethod @abstractmethod
def query_domain(self, domain: str) -> List[Tuple[str, str, str, float, Dict[str, Any]]]: def query_domain(self, domain: str) -> ProviderResult:
""" """
Query the provider for information about a domain. Query the provider for information about a domain.
@@ -144,12 +146,12 @@ class BaseProvider(ABC):
domain: Domain to investigate domain: Domain to investigate
Returns: Returns:
List of tuples: (source_node, target_node, relationship_type, confidence, raw_data) ProviderResult containing standardized attributes and relationships
""" """
pass pass
@abstractmethod @abstractmethod
def query_ip(self, ip: str) -> List[Tuple[str, str, str, float, Dict[str, Any]]]: def query_ip(self, ip: str) -> ProviderResult:
""" """
Query the provider for information about an IP address. Query the provider for information about an IP address.
@@ -157,7 +159,7 @@ class BaseProvider(ABC):
ip: IP address to investigate ip: IP address to investigate
Returns: Returns:
List of tuples: (source_node, target_node, relationship_type, confidence, raw_data) ProviderResult containing standardized attributes and relationships
""" """
pass pass
@@ -167,13 +169,13 @@ class BaseProvider(ABC):
target_indicator: str = "") -> Optional[requests.Response]: target_indicator: str = "") -> Optional[requests.Response]:
""" """
Make a rate-limited HTTP request. Make a rate-limited HTTP request.
FIXED: Returns response without automatically raising HTTPError exceptions.
Individual providers should handle status codes appropriately.
""" """
if self._is_stop_requested(): if self._is_stop_requested():
print(f"Request cancelled before start: {url}") print(f"Request cancelled before start: {url}")
return None return None
self.rate_limiter.wait_if_needed()
start_time = time.time() start_time = time.time()
response = None response = None
error = None error = None
@@ -205,8 +207,14 @@ class BaseProvider(ABC):
raise ValueError(f"Unsupported HTTP method: {method}") raise ValueError(f"Unsupported HTTP method: {method}")
print(f"Response status: {response.status_code}") print(f"Response status: {response.status_code}")
response.raise_for_status()
# FIXED: Don't automatically raise for HTTP error status codes
# Let individual providers handle status codes appropriately
# Only count 2xx responses as successful
if 200 <= response.status_code < 300:
self.successful_requests += 1 self.successful_requests += 1
else:
self.failed_requests += 1
duration_ms = (time.time() - start_time) * 1000 duration_ms = (time.time() - start_time) * 1000
self.logger.log_api_request( self.logger.log_api_request(
@@ -297,5 +305,5 @@ class BaseProvider(ABC):
'failed_requests': self.failed_requests, 'failed_requests': self.failed_requests,
'success_rate': (self.successful_requests / self.total_requests * 100) if self.total_requests > 0 else 0, 'success_rate': (self.successful_requests / self.total_requests * 100) if self.total_requests > 0 else 0,
'relationships_found': self.total_relationships_found, 'relationships_found': self.total_relationships_found,
'rate_limit': self.rate_limiter.requests_per_minute 'rate_limit': self.config.get_rate_limit(self.name)
} }

View File

@@ -0,0 +1,220 @@
# dnsrecon/providers/correlation_provider.py
import re
from typing import Dict, Any, List
from .base_provider import BaseProvider
from core.provider_result import ProviderResult
from core.graph_manager import NodeType, GraphManager
class CorrelationProvider(BaseProvider):
"""
A provider that finds correlations between nodes in the graph.
FIXED: Enhanced pickle support to prevent weakref issues with graph references.
"""
def __init__(self, name: str = "correlation", session_config=None):
"""
Initialize the correlation provider.
"""
super().__init__(name, session_config=session_config)
self.graph: GraphManager | None = None
self.correlation_index = {}
self.date_pattern = re.compile(r'^\d{4}-\d{2}-\d{2}[ T]\d{2}:\d{2}:\d{2}')
self.EXCLUDED_KEYS = [
'cert_source',
'cert_issuer_ca_id',
'cert_common_name',
'cert_validity_period_days',
'cert_issuer_name',
'cert_serial_number',
'cert_entry_timestamp',
'cert_not_before',
'cert_not_after',
'dns_ttl',
'timestamp',
'last_update',
'updated_timestamp',
'discovery_timestamp',
'query_timestamp',
]
def __getstate__(self):
"""
FIXED: Prepare CorrelationProvider for pickling by excluding graph reference.
"""
state = super().__getstate__()
# Remove graph reference to prevent circular dependencies and weakrefs
if 'graph' in state:
del state['graph']
# Also handle correlation_index which might contain complex objects
if 'correlation_index' in state:
# Clear correlation index as it will be rebuilt when needed
state['correlation_index'] = {}
return state
def __setstate__(self, state):
"""
FIXED: Restore CorrelationProvider after unpickling.
"""
super().__setstate__(state)
# Re-initialize graph reference (will be set by scanner)
self.graph = None
# Re-initialize correlation index
self.correlation_index = {}
# Re-compile regex pattern
self.date_pattern = re.compile(r'^\d{4}-\d{2}-\d{2}[ T]\d{2}:\d{2}:\d{2}')
def get_name(self) -> str:
"""Return the provider name."""
return "correlation"
def get_display_name(self) -> str:
"""Return the provider display name for the UI."""
return "Correlation Engine"
def requires_api_key(self) -> bool:
"""Return True if the provider requires an API key."""
return False
def get_eligibility(self) -> Dict[str, bool]:
"""Return a dictionary indicating if the provider can query domains and/or IPs."""
return {'domains': True, 'ips': True}
def is_available(self) -> bool:
"""Check if the provider is available and properly configured."""
return True
def query_domain(self, domain: str) -> ProviderResult:
"""
Query the provider for information about a domain.
"""
return self._find_correlations(domain)
def query_ip(self, ip: str) -> ProviderResult:
"""
Query the provider for information about an IP address.
"""
return self._find_correlations(ip)
def set_graph_manager(self, graph_manager: GraphManager):
"""
Set the graph manager for the provider to use.
"""
self.graph = graph_manager
def _find_correlations(self, node_id: str) -> ProviderResult:
"""
Find correlations for a given node.
FIXED: Added safety checks to prevent issues when graph is None.
"""
result = ProviderResult()
# FIXED: Ensure self.graph is not None before proceeding
if not self.graph or not self.graph.graph.has_node(node_id):
return result
try:
node_attributes = self.graph.graph.nodes[node_id].get('attributes', [])
except Exception as e:
# If there's any issue accessing the graph, return empty result
print(f"Warning: Could not access graph for correlation analysis: {e}")
return result
for attr in node_attributes:
attr_name = attr.get('name')
attr_value = attr.get('value')
attr_provider = attr.get('provider', 'unknown')
should_exclude = (
any(excluded_key in attr_name or attr_name == excluded_key for excluded_key in self.EXCLUDED_KEYS) or
not isinstance(attr_value, (str, int, float, bool)) or
attr_value is None or
isinstance(attr_value, bool) or
(isinstance(attr_value, str) and (
len(attr_value) < 4 or
self.date_pattern.match(attr_value) or
attr_value.lower() in ['unknown', 'none', 'null', 'n/a', 'true', 'false', '0', '1']
)) or
(isinstance(attr_value, (int, float)) and (
attr_value == 0 or
attr_value == 1 or
abs(attr_value) > 1000000
))
)
if should_exclude:
continue
if attr_value not in self.correlation_index:
self.correlation_index[attr_value] = {
'nodes': set(),
'sources': []
}
self.correlation_index[attr_value]['nodes'].add(node_id)
source_info = {
'node_id': node_id,
'provider': attr_provider,
'attribute': attr_name,
'path': f"{attr_provider}_{attr_name}"
}
existing_sources = [s for s in self.correlation_index[attr_value]['sources']
if s['node_id'] == node_id and s['path'] == source_info['path']]
if not existing_sources:
self.correlation_index[attr_value]['sources'].append(source_info)
if len(self.correlation_index[attr_value]['nodes']) > 1:
self._create_correlation_relationships(attr_value, self.correlation_index[attr_value], result)
return result
def _create_correlation_relationships(self, value: Any, correlation_data: Dict[str, Any], result: ProviderResult):
"""
Create correlation relationships and add them to the provider result.
"""
correlation_node_id = f"corr_{hash(str(value)) & 0x7FFFFFFF}"
nodes = correlation_data['nodes']
sources = correlation_data['sources']
# Add the correlation node as an attribute to the result
result.add_attribute(
target_node=correlation_node_id,
name="correlation_value",
value=value,
attr_type=str(type(value)),
provider=self.name,
confidence=0.9,
metadata={
'correlated_nodes': list(nodes),
'sources': sources,
}
)
for source in sources:
node_id = source['node_id']
provider = source['provider']
attribute = source['attribute']
relationship_label = f"corr_{provider}_{attribute}"
# Add the relationship to the result
result.add_relationship(
source_node=node_id,
target_node=correlation_node_id,
relationship_type=relationship_label,
provider=self.name,
confidence=0.9,
raw_data={
'correlation_value': value,
'original_attribute': attribute,
'correlation_type': 'attribute_matching'
}
)

File diff suppressed because it is too large Load Diff

Some files were not shown because too many files have changed in this diff Show More