Doc/updated documentation (#60)
* added documentation, updated repo pointer in the dashboard, added dashboard link highlighting and mionor fixes * added doc * added logo to dashboard * Fixed dashboard attack chart * Enhance fake data generation with varied request counts for better visualization * Add automatic migrations and support for latitude/longitude in IP stats * Update Helm chart version to 0.2.2 and add timezone configuration option --------- Co-authored-by: BlessedRebuS <patrick.difa@gmail.com>
287
README.md
@@ -10,7 +10,7 @@
|
||||
<div align="center">
|
||||
|
||||
<p align="center">
|
||||
A modern, customizable zero-dependencies honeypot server designed to detect and track malicious activity through deceptive web pages, fake credentials, and canary tokens.
|
||||
A modern, customizable web honeypot server designed to detect and track malicious activity from attackers and web crawlers through deceptive web pages, fake credentials, and canary tokens.
|
||||
</p>
|
||||
|
||||
<div align="center">
|
||||
@@ -55,7 +55,7 @@ Tip: crawl the `robots.txt` paths for additional fun
|
||||
|
||||
## What is Krawl?
|
||||
|
||||
**Krawl** is a cloud‑native deception server designed to detect, delay, and analyze malicious web crawlers and automated scanners.
|
||||
**Krawl** is a cloud‑native deception server designed to detect, delay, and analyze malicious attackers, web crawlers and automated scanners.
|
||||
|
||||
It creates realistic fake web applications filled with low‑hanging fruit such as admin panels, configuration files, and exposed fake credentials to attract and identify suspicious activity.
|
||||
|
||||
@@ -68,11 +68,14 @@ It features:
|
||||
- **Honeypot Paths**: Advertised in robots.txt to catch scanners
|
||||
- **Fake Credentials**: Realistic-looking usernames, passwords, API keys
|
||||
- **[Canary Token](#customizing-the-canary-token) Integration**: External alert triggering
|
||||
- **Random server headers**: Confuse attacks based on server header and version
|
||||
- **Real-time Dashboard**: Monitor suspicious activity
|
||||
- **Customizable Wordlists**: Easy JSON-based configuration
|
||||
- **Random Error Injection**: Mimic real server behavior
|
||||
|
||||

|
||||

|
||||
|
||||

|
||||
|
||||
## 🚀 Installation
|
||||
|
||||
@@ -127,149 +130,98 @@ Stop with:
|
||||
docker-compose down
|
||||
```
|
||||
|
||||
### Helm Chart
|
||||
|
||||
Install with default values:
|
||||
|
||||
```bash
|
||||
helm install krawl oci://ghcr.io/blessedrebus/krawl-chart \
|
||||
--version 2.0.0 \
|
||||
--namespace krawl-system \
|
||||
--create-namespace
|
||||
```
|
||||
|
||||
Or create a minimal `values.yaml` file:
|
||||
|
||||
```yaml
|
||||
service:
|
||||
type: LoadBalancer
|
||||
port: 5000
|
||||
|
||||
ingress:
|
||||
enabled: true
|
||||
className: "traefik"
|
||||
hosts:
|
||||
- host: krawl.example.com
|
||||
paths:
|
||||
- path: /
|
||||
pathType: Prefix
|
||||
|
||||
config:
|
||||
server:
|
||||
port: 5000
|
||||
delay: 100
|
||||
dashboard:
|
||||
secret_path: null # Auto-generated if not set
|
||||
|
||||
database:
|
||||
persistence:
|
||||
enabled: true
|
||||
size: 1Gi
|
||||
```
|
||||
|
||||
Install with custom values:
|
||||
|
||||
```bash
|
||||
helm install krawl oci://ghcr.io/blessedrebus/krawl-chart \
|
||||
--version 2.0.0 \
|
||||
--namespace krawl-system \
|
||||
--create-namespace \
|
||||
-f values.yaml
|
||||
```
|
||||
|
||||
To access the deception server:
|
||||
|
||||
```bash
|
||||
kubectl get svc krawl -n krawl-system
|
||||
```
|
||||
|
||||
Once the EXTERNAL-IP is assigned, access your deception server at `http://<EXTERNAL-IP>:5000`
|
||||
|
||||
### Kubernetes
|
||||
**Krawl is also available natively on Kubernetes**. Installation can be done either [via manifest](kubernetes/README.md) or [using the helm chart](helm/README.md).
|
||||
|
||||
Apply all manifests with:
|
||||
## Use Krawl to Ban Malicious IPs
|
||||
Krawl uses a reputation-based system to classify attacker IP addresses. Every five minutes, Krawl exports the identified malicious IPs to a `malicious_ips.txt` file.
|
||||
|
||||
This file can either be mounted from the Docker container into another system or downloaded directly via `curl`:
|
||||
|
||||
```bash
|
||||
kubectl apply -f https://raw.githubusercontent.com/BlessedRebuS/Krawl/refs/heads/main/kubernetes/krawl-all-in-one-deploy.yaml
|
||||
curl https://your-krawl-instance/<DASHBOARD-PATH>/api/download/malicious_ips.txt
|
||||
```
|
||||
|
||||
Or clone the repo and apply the manifest:
|
||||
This file can be used to [update a set of firewall rules](https://www.allthingstech.ch/using-opnsense-and-ip-blocklists-to-block-malicious-traffic), for example on OPNsense and pfSense, enabling automatic blocking of malicious IPs or using IPtables
|
||||
|
||||
## IP Reputation
|
||||
Krawl [uses tasks that analyze recent traffic to build and continuously update an IP reputation](src/tasks/analyze_ips.py) score. It runs periodically and evaluates each active IP address based on multiple behavioral indicators to classify it as an attacker, crawler, or regular user. Thresholds are fully customizable.
|
||||
|
||||

|
||||
|
||||
The analysis includes:
|
||||
- **Risky HTTP methods usage** (e.g. POST, PUT, DELETE ratios)
|
||||
- **Robots.txt violations**
|
||||
- **Request timing anomalies** (bursty or irregular patterns)
|
||||
- **User-Agent consistency**
|
||||
- **Attack URL detection** (e.g. SQL injection, XSS patterns)
|
||||
|
||||
Each signal contributes to a weighted scoring model that assigns a reputation category:
|
||||
- `attacker`
|
||||
- `bad_crawler`
|
||||
- `good_crawler`
|
||||
- `regular_user`
|
||||
- `unknown` (for insufficient data)
|
||||
|
||||
The resulting scores and metrics are stored in the database and used by Krawl to drive dashboards, reputation tracking, and automated mitigation actions such as IP banning or firewall integration.
|
||||
|
||||
## Forward server header
|
||||
If Krawl is deployed behind a proxy such as NGINX the **server header** should be forwarded using the following configuration in your proxy:
|
||||
|
||||
```bash
|
||||
kubectl apply -f kubernetes/krawl-all-in-one-deploy.yaml
|
||||
location / {
|
||||
proxy_pass https://your-krawl-instance;
|
||||
proxy_pass_header Server;
|
||||
}
|
||||
```
|
||||
|
||||
Access the deception server:
|
||||
## API
|
||||
Krawl uses the following APIs
|
||||
- https://iprep.lcrawl.com (IP Reputation)
|
||||
- https://nominatim.openstreetmap.org/reverse (Reverse IP Lookup)
|
||||
- https://api.ipify.org (Public IP discovery)
|
||||
- http://ident.me (Public IP discovery)
|
||||
- https://ifconfig.me (Public IP discovery)
|
||||
|
||||
## Configuration
|
||||
Krawl uses a **configuration hierarchy** in which **environment variables take precedence over the configuration file**. This approach is recommended for Docker deployments and quick out-of-the-box customization.
|
||||
|
||||
### Configuration via Enviromental Variables
|
||||
|
||||
| Environment Variable | Description | Default |
|
||||
|----------------------|-------------|---------|
|
||||
| `CONFIG_LOCATION` | Path to yaml config file | `config.yaml` |
|
||||
| `KRAWL_PORT` | Server listening port | `5000` |
|
||||
| `KRAWL_DELAY` | Response delay in milliseconds | `100` |
|
||||
| `KRAWL_SERVER_HEADER` | HTTP Server header for deception | `""` |
|
||||
| `KRAWL_LINKS_LENGTH_RANGE` | Link length range as `min,max` | `5,15` |
|
||||
| `KRAWL_LINKS_PER_PAGE_RANGE` | Links per page as `min,max` | `10,15` |
|
||||
| `KRAWL_CHAR_SPACE` | Characters used for link generation | `abcdefgh...` |
|
||||
| `KRAWL_MAX_COUNTER` | Initial counter value | `10` |
|
||||
| `KRAWL_CANARY_TOKEN_URL` | External canary token URL | None |
|
||||
| `KRAWL_CANARY_TOKEN_TRIES` | Requests before showing canary token | `10` |
|
||||
| `KRAWL_DASHBOARD_SECRET_PATH` | Custom dashboard path | Auto-generated |
|
||||
| `KRAWL_API_SERVER_URL` | API server URL | None |
|
||||
| `KRAWL_API_SERVER_PORT` | API server port | `8080` |
|
||||
| `KRAWL_API_SERVER_PATH` | API server endpoint path | `/api/v2/users` |
|
||||
| `KRAWL_PROBABILITY_ERROR_CODES` | Error response probability (0-100%) | `0` |
|
||||
| `KRAWL_DATABASE_PATH` | Database file location | `data/krawl.db` |
|
||||
| `KRAWL_DATABASE_RETENTION_DAYS` | Days to retain data in database | `30` |
|
||||
| `KRAWL_HTTP_RISKY_METHODS_THRESHOLD` | Threshold for risky HTTP methods detection | `0.1` |
|
||||
| `KRAWL_VIOLATED_ROBOTS_THRESHOLD` | Threshold for robots.txt violations | `0.1` |
|
||||
| `KRAWL_UNEVEN_REQUEST_TIMING_THRESHOLD` | Coefficient of variation threshold for timing | `0.5` |
|
||||
| `KRAWL_UNEVEN_REQUEST_TIMING_TIME_WINDOW_SECONDS` | Time window for request timing analysis in seconds | `300` |
|
||||
| `KRAWL_USER_AGENTS_USED_THRESHOLD` | Threshold for detecting multiple user agents | `2` |
|
||||
| `KRAWL_ATTACK_URLS_THRESHOLD` | Threshold for attack URL detection | `1` |
|
||||
|
||||
For example
|
||||
|
||||
```bash
|
||||
kubectl get svc krawl-server -n krawl-system
|
||||
```
|
||||
|
||||
Once the EXTERNAL-IP is assigned, access your deception server at `http://<EXTERNAL-IP>:5000`
|
||||
|
||||
### From Source (Python 3.11+)
|
||||
|
||||
Clone the repository:
|
||||
|
||||
```bash
|
||||
git clone https://github.com/blessedrebus/krawl.git
|
||||
cd krawl/src
|
||||
```
|
||||
|
||||
Run the server:
|
||||
|
||||
```bash
|
||||
python3 server.py
|
||||
```
|
||||
|
||||
Visit `http://localhost:5000` and access the dashboard at `http://localhost:5000/<dashboard-secret-path>`
|
||||
|
||||
## Configuration via Environment Variables
|
||||
|
||||
To customize the deception server installation, environment variables can be specified using the naming convention: `KRAWL_<FIELD_NAME>` where `<FIELD_NAME>` is the configuration field name in uppercase with special characters converted:
|
||||
- `.` → `_`
|
||||
- `-` → `__` (double underscore)
|
||||
- ` ` (space) → `_`
|
||||
|
||||
### Configuration Variables
|
||||
|
||||
| Configuration Field | Environment Variable | Description | Default |
|
||||
|-----------|-----------|-------------|---------|
|
||||
| `port` | `KRAWL_PORT` | Server listening port | `5000` |
|
||||
| `delay` | `KRAWL_DELAY` | Response delay in milliseconds | `100` |
|
||||
| `server_header` | `KRAWL_SERVER_HEADER` | HTTP Server header for deception | `""` |
|
||||
| `links_length_range` | `KRAWL_LINKS_LENGTH_RANGE` | Link length range as `min,max` | `5,15` |
|
||||
| `links_per_page_range` | `KRAWL_LINKS_PER_PAGE_RANGE` | Links per page as `min,max` | `10,15` |
|
||||
| `char_space` | `KRAWL_CHAR_SPACE` | Characters used for link generation | `abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789` |
|
||||
| `max_counter` | `KRAWL_MAX_COUNTER` | Initial counter value | `10` |
|
||||
| `canary_token_url` | `KRAWL_CANARY_TOKEN_URL` | External canary token URL | None |
|
||||
| `canary_token_tries` | `KRAWL_CANARY_TOKEN_TRIES` | Requests before showing canary token | `10` |
|
||||
| `dashboard_secret_path` | `KRAWL_DASHBOARD_SECRET_PATH` | Custom dashboard path | Auto-generated |
|
||||
| `api_server_url` | `KRAWL_API_SERVER_URL` | API server URL | None |
|
||||
| `api_server_port` | `KRAWL_API_SERVER_PORT` | API server port | `8080` |
|
||||
| `api_server_path` | `KRAWL_API_SERVER_PATH` | API server endpoint path | `/api/v2/users` |
|
||||
| `probability_error_codes` | `KRAWL_PROBABILITY_ERROR_CODES` | Error response probability (0-100%) | `0` |
|
||||
| `database_path` | `KRAWL_DATABASE_PATH` | Database file location | `data/krawl.db` |
|
||||
| `database_retention_days` | `KRAWL_DATABASE_RETENTION_DAYS` | Days to retain data in database | `30` |
|
||||
| `http_risky_methods_threshold` | `KRAWL_HTTP_RISKY_METHODS_THRESHOLD` | Threshold for risky HTTP methods detection | `0.1` |
|
||||
| `violated_robots_threshold` | `KRAWL_VIOLATED_ROBOTS_THRESHOLD` | Threshold for robots.txt violations | `0.1` |
|
||||
| `uneven_request_timing_threshold` | `KRAWL_UNEVEN_REQUEST_TIMING_THRESHOLD` | Coefficient of variation threshold for timing | `0.5` |
|
||||
| `uneven_request_timing_time_window_seconds` | `KRAWL_UNEVEN_REQUEST_TIMING_TIME_WINDOW_SECONDS` | Time window for request timing analysis in seconds | `300` |
|
||||
| `user_agents_used_threshold` | `KRAWL_USER_AGENTS_USED_THRESHOLD` | Threshold for detecting multiple user agents | `2` |
|
||||
| `attack_urls_threshold` | `KRAWL_ATTACK_URLS_THRESHOLD` | Threshold for attack URL detection | `1` |
|
||||
|
||||
### Examples
|
||||
|
||||
```bash
|
||||
# Set port and delay
|
||||
export KRAWL_PORT=8080
|
||||
export KRAWL_DELAY=200
|
||||
|
||||
# Set canary token
|
||||
export CONFIG_LOCATION="config.yaml"
|
||||
export KRAWL_CANARY_TOKEN_URL="http://your-canary-token-url"
|
||||
|
||||
# Set tuple values (min,max format)
|
||||
export KRAWL_LINKS_LENGTH_RANGE="3,20"
|
||||
# Set number of pages range (min,max format)
|
||||
export KRAWL_LINKS_PER_PAGE_RANGE="5,25"
|
||||
|
||||
# Set analyzer thresholds
|
||||
@@ -280,7 +232,7 @@ export KRAWL_VIOLATED_ROBOTS_THRESHOLD="0.15"
|
||||
export KRAWL_DASHBOARD_SECRET_PATH="/my-secret-dashboard"
|
||||
```
|
||||
|
||||
Or in Docker:
|
||||
Example of a Docker run with env variables:
|
||||
|
||||
```bash
|
||||
docker run -d \
|
||||
@@ -292,36 +244,20 @@ docker run -d \
|
||||
ghcr.io/blessedrebus/krawl:latest
|
||||
```
|
||||
|
||||
## robots.txt
|
||||
The actual (juicy) robots.txt configuration is the following
|
||||
### Configuration via config.yaml
|
||||
You can use the [config.yaml](config.yaml) file for more advanced configurations, such as Docker Compose or Helm chart deployments.
|
||||
|
||||
```txt
|
||||
Disallow: /admin/
|
||||
Disallow: /api/
|
||||
Disallow: /backup/
|
||||
Disallow: /config/
|
||||
Disallow: /database/
|
||||
Disallow: /private/
|
||||
Disallow: /uploads/
|
||||
Disallow: /wp-admin/
|
||||
Disallow: /phpMyAdmin/
|
||||
Disallow: /admin/login.php
|
||||
Disallow: /api/v1/users
|
||||
Disallow: /api/v2/secrets
|
||||
Disallow: /.env
|
||||
Disallow: /credentials.txt
|
||||
Disallow: /passwords.txt
|
||||
Disallow: /.git/
|
||||
Disallow: /backup.sql
|
||||
Disallow: /db_backup.sql
|
||||
```
|
||||
# Honeypot
|
||||
Below is a complete overview of the Krawl honeypot’s capabilities
|
||||
|
||||
## robots.txt
|
||||
The actual (juicy) robots.txt configuration [is the following](src/templates/html/robots.txt).
|
||||
|
||||
## Honeypot pages
|
||||
Requests to common admin endpoints (`/admin/`, `/wp-admin/`, `/phpMyAdmin/`) return a fake login page. Any login attempt triggers a 1-second delay to simulate real processing and is fully logged in the dashboard (credentials, IP, headers, timing).
|
||||
|
||||
<div align="center">
|
||||
<img src="img/admin-page.png" width="60%" />
|
||||
</div>
|
||||

|
||||
|
||||
|
||||
Requests to paths like `/backup/`, `/config/`, `/database/`, `/private/`, or `/uploads/` return a fake directory listing populated with “interesting” files, each assigned a random file size to look realistic.
|
||||
|
||||
@@ -329,21 +265,23 @@ Requests to paths like `/backup/`, `/config/`, `/database/`, `/private/`, or `/u
|
||||
|
||||
The `.env` endpoint exposes fake database connection strings, **AWS API keys**, and **Stripe secrets**. It intentionally returns an error due to the `Content-Type` being `application/json` instead of plain text, mimicking a “juicy” misconfiguration that crawlers and scanners often flag as information leakage.
|
||||
|
||||

|
||||
The `/server` page displays randomly generated fake error information for each known server.
|
||||
|
||||

|
||||
|
||||
The pages `/api/v1/users` and `/api/v2/secrets` show fake users and random secrets in JSON format
|
||||
|
||||
<div align="center">
|
||||
<img src="img/api-users-page.png" width="45%" style="vertical-align: middle; margin: 0 10px;" />
|
||||
<img src="img/api-secrets-page.png" width="45%" style="vertical-align: middle; margin: 0 10px;" />
|
||||
</div>
|
||||

|
||||
|
||||
The pages `/credentials.txt` and `/passwords.txt` show fake users and random secrets
|
||||
|
||||
<div align="center">
|
||||
<img src="img/credentials-page.png" width="35%" style="vertical-align: middle; margin: 0 10px;" />
|
||||
<img src="img/passwords-page.png" width="45%" style="vertical-align: middle; margin: 0 10px;" />
|
||||
</div>
|
||||

|
||||
|
||||
Pages such as `/users`, `/search`, `/contact`, `/info`, `/input`, and `/feedback`, along with APIs like `/api/sql` and `/api/database`, are designed to lure attackers into performing attacks such as **SQL injection** or **XSS**.
|
||||
|
||||

|
||||
|
||||
Automated tools like **SQLMap** will receive a different randomized database error on each request, increasing scan noise and confusing the attacker. All detected attacks are logged and displayed in the dashboard.
|
||||
|
||||
## Customizing the Canary Token
|
||||
To create a custom canary token, visit https://canarytokens.org
|
||||
@@ -384,11 +322,13 @@ Access the dashboard at `http://<server-ip>:<port>/<dashboard-path>`
|
||||
|
||||
The dashboard shows:
|
||||
- Total and unique accesses
|
||||
- Suspicious activity detection
|
||||
- Top IPs, paths, and user-agents
|
||||
- Suspicious activity and attack detection
|
||||
- Top IPs, paths, user-agents and GeoIP localization
|
||||
- Real-time monitoring
|
||||
|
||||
The attackers' triggered honeypot path and the suspicious activity (such as failed login attempts) are logged
|
||||
The attackers’ access to the honeypot endpoint and related suspicious activities (such as failed login attempts) are logged.
|
||||
|
||||
Krawl also implements a scoring system designed to distinguish between malicious and legitimate behavior on the website.
|
||||
|
||||

|
||||
|
||||
@@ -396,14 +336,7 @@ The top IP Addresses is shown along with top paths and User Agents
|
||||
|
||||

|
||||
|
||||
### Retrieving Dashboard Path
|
||||
|
||||
Check server startup logs or get the secret with
|
||||
|
||||
```bash
|
||||
kubectl get secret krawl-server -n krawl-system \
|
||||
-o jsonpath='{.data.dashboard-path}' | base64 -d && echo
|
||||
```
|
||||

|
||||
|
||||
## 🤝 Contributing
|
||||
|
||||
|
||||
@@ -22,12 +22,8 @@ canary:
|
||||
dashboard:
|
||||
# if set to "null" this will Auto-generates random path if not set
|
||||
# can be set to "/dashboard" or similar <-- note this MUST include a forward slash
|
||||
secret_path: super-secret-dashboard-path
|
||||
|
||||
api:
|
||||
server_url: null
|
||||
server_port: 8080
|
||||
server_path: "/api/v2/users"
|
||||
# secret_path: super-secret-dashboard-path
|
||||
secret_path: null
|
||||
|
||||
database:
|
||||
path: "data/krawl.db"
|
||||
|
||||
@@ -2,8 +2,8 @@ apiVersion: v2
|
||||
name: krawl-chart
|
||||
description: A Helm chart for Krawl honeypot server
|
||||
type: application
|
||||
version: 0.2.1
|
||||
appVersion: 0.2.1
|
||||
version: 0.2.2
|
||||
appVersion: 0.2.2
|
||||
keywords:
|
||||
- honeypot
|
||||
- security
|
||||
|
||||
@@ -10,6 +10,65 @@ A Helm chart for deploying the Krawl honeypot application on Kubernetes.
|
||||
|
||||
## Installation
|
||||
|
||||
|
||||
### Helm Chart
|
||||
|
||||
Install with default values:
|
||||
|
||||
```bash
|
||||
helm install krawl oci://ghcr.io/blessedrebus/krawl-chart \
|
||||
--version 0.2.2 \
|
||||
--namespace krawl-system \
|
||||
--create-namespace
|
||||
```
|
||||
|
||||
Or create a minimal `values.yaml` file:
|
||||
|
||||
```yaml
|
||||
service:
|
||||
type: LoadBalancer
|
||||
port: 5000
|
||||
|
||||
ingress:
|
||||
enabled: true
|
||||
className: "traefik"
|
||||
hosts:
|
||||
- host: krawl.example.com
|
||||
paths:
|
||||
- path: /
|
||||
pathType: Prefix
|
||||
|
||||
config:
|
||||
server:
|
||||
port: 5000
|
||||
delay: 100
|
||||
dashboard:
|
||||
secret_path: null # Auto-generated if not set
|
||||
|
||||
database:
|
||||
persistence:
|
||||
enabled: true
|
||||
size: 1Gi
|
||||
```
|
||||
|
||||
Install with custom values:
|
||||
|
||||
```bash
|
||||
helm install krawl oci://ghcr.io/blessedrebus/krawl-chart \
|
||||
--version 0.2.2 \
|
||||
--namespace krawl-system \
|
||||
--create-namespace \
|
||||
-f values.yaml
|
||||
```
|
||||
|
||||
To access the deception server:
|
||||
|
||||
```bash
|
||||
kubectl get svc krawl -n krawl-system
|
||||
```
|
||||
|
||||
Once the EXTERNAL-IP is assigned, access your deception server at `http://<EXTERNAL-IP>:5000`
|
||||
|
||||
### Add the repository (if applicable)
|
||||
|
||||
```bash
|
||||
@@ -176,6 +235,15 @@ The following table lists the main configuration parameters of the Krawl chart a
|
||||
|-----------|-------------|---------|
|
||||
| `networkPolicy.enabled` | Enable network policy | `true` |
|
||||
|
||||
### Retrieving Dashboard Path
|
||||
|
||||
Check server startup logs or get the secret with
|
||||
|
||||
```bash
|
||||
kubectl get secret krawl-server -n krawl-system \
|
||||
-o jsonpath='{.data.dashboard-path}' | base64 -d && echo
|
||||
```
|
||||
|
||||
## Usage Examples
|
||||
|
||||
### Basic Installation
|
||||
|
||||
@@ -43,6 +43,10 @@ spec:
|
||||
env:
|
||||
- name: CONFIG_LOCATION
|
||||
value: "config.yaml"
|
||||
{{- if .Values.timezone }}
|
||||
- name: TZ
|
||||
value: {{ .Values.timezone | quote }}
|
||||
{{- end }}
|
||||
volumeMounts:
|
||||
- name: config
|
||||
mountPath: /app/config.yaml
|
||||
|
||||
@@ -49,6 +49,11 @@ resources:
|
||||
cpu: 100m
|
||||
memory: 64Mi
|
||||
|
||||
# Container timezone configuration
|
||||
# Set this to change timezone (e.g., "America/New_York", "Europe/Rome")
|
||||
# If not set, container will use its default timezone
|
||||
timezone: ""
|
||||
|
||||
autoscaling:
|
||||
enabled: false
|
||||
minReplicas: 1
|
||||
@@ -67,7 +72,6 @@ config:
|
||||
server:
|
||||
port: 5000
|
||||
delay: 100
|
||||
timezone: null # IANA timezone (e.g., "America/New_York", "Europe/Rome"). If not set, system timezone is used.
|
||||
links:
|
||||
min_length: 5
|
||||
max_length: 15
|
||||
|
||||
|
Before Width: | Height: | Size: 21 KiB After Width: | Height: | Size: 21 KiB |
|
Before Width: | Height: | Size: 90 KiB |
|
Before Width: | Height: | Size: 46 KiB |
BIN
img/credentials-and-passwords.png
Normal file
|
After Width: | Height: | Size: 72 KiB |
|
Before Width: | Height: | Size: 76 KiB |
|
Before Width: | Height: | Size: 98 KiB After Width: | Height: | Size: 133 KiB |
|
Before Width: | Height: | Size: 54 KiB After Width: | Height: | Size: 76 KiB |
BIN
img/dashboard-3.png
Normal file
|
After Width: | Height: | Size: 206 KiB |
BIN
img/env-page.png
|
Before Width: | Height: | Size: 30 KiB |
BIN
img/geoip_dashboard.png
Normal file
|
After Width: | Height: | Size: 179 KiB |
BIN
img/ip-reputation.png
Normal file
|
After Width: | Height: | Size: 72 KiB |
|
Before Width: | Height: | Size: 119 KiB |
BIN
img/server-and-env-page.png
Normal file
|
After Width: | Height: | Size: 86 KiB |
BIN
img/sql_injection.png
Normal file
|
After Width: | Height: | Size: 30 KiB |
BIN
img/users-and-secrets.png
Normal file
|
After Width: | Height: | Size: 67 KiB |
47
kubernetes/README.md
Normal file
@@ -0,0 +1,47 @@
|
||||
### Kubernetes
|
||||
|
||||
Apply all manifests with:
|
||||
|
||||
```bash
|
||||
kubectl apply -f https://raw.githubusercontent.com/BlessedRebuS/Krawl/refs/heads/main/kubernetes/krawl-all-in-one-deploy.yaml
|
||||
```
|
||||
|
||||
Or clone the repo and apply the manifest:
|
||||
|
||||
```bash
|
||||
kubectl apply -f kubernetes/krawl-all-in-one-deploy.yaml
|
||||
```
|
||||
|
||||
Access the deception server:
|
||||
|
||||
```bash
|
||||
kubectl get svc krawl-server -n krawl-system
|
||||
```
|
||||
|
||||
Once the EXTERNAL-IP is assigned, access your deception server at `http://<EXTERNAL-IP>:5000`
|
||||
|
||||
### Retrieving Dashboard Path
|
||||
|
||||
Check server startup logs or get the secret with
|
||||
|
||||
```bash
|
||||
kubectl get secret krawl-server -n krawl-system \
|
||||
-o jsonpath='{.data.dashboard-path}' | base64 -d && echo
|
||||
```
|
||||
|
||||
### From Source (Python 3.11+)
|
||||
|
||||
Clone the repository:
|
||||
|
||||
```bash
|
||||
git clone https://github.com/blessedrebus/krawl.git
|
||||
cd krawl/src
|
||||
```
|
||||
|
||||
Run the server:
|
||||
|
||||
```bash
|
||||
python3 server.py
|
||||
```
|
||||
|
||||
Visit `http://localhost:5000` and access the dashboard at `http://localhost:5000/<dashboard-secret-path>`
|
||||
@@ -28,9 +28,6 @@ class Config:
|
||||
canary_token_url: Optional[str] = None
|
||||
canary_token_tries: int = 10
|
||||
dashboard_secret_path: str = None
|
||||
api_server_url: Optional[str] = None
|
||||
api_server_port: int = 8080
|
||||
api_server_path: str = "/api/v2/users"
|
||||
probability_error_codes: int = 0 # Percentage (0-100)
|
||||
|
||||
# Crawl limiting settings - for legitimate vs malicious crawlers
|
||||
@@ -187,9 +184,6 @@ class Config:
|
||||
canary_token_url=canary.get("token_url"),
|
||||
canary_token_tries=canary.get("token_tries", 10),
|
||||
dashboard_secret_path=dashboard_path,
|
||||
api_server_url=api.get("server_url"),
|
||||
api_server_port=api.get("server_port", 8080),
|
||||
api_server_path=api.get("server_path", "/api/v2/users"),
|
||||
probability_error_codes=behavior.get("probability_error_codes", 0),
|
||||
database_path=database.get("path", "data/krawl.db"),
|
||||
database_retention_days=database.get("retention_days", 30),
|
||||
|
||||
128
src/database.py
@@ -94,6 +94,9 @@ class DatabaseManager:
|
||||
# Create all tables
|
||||
Base.metadata.create_all(self._engine)
|
||||
|
||||
# Run automatic migrations for backward compatibility
|
||||
self._run_migrations(database_path)
|
||||
|
||||
# Set restrictive file permissions (owner read/write only)
|
||||
if os.path.exists(database_path):
|
||||
try:
|
||||
@@ -104,6 +107,47 @@ class DatabaseManager:
|
||||
|
||||
self._initialized = True
|
||||
|
||||
def _run_migrations(self, database_path: str) -> None:
|
||||
"""
|
||||
Run automatic migrations for backward compatibility.
|
||||
Adds missing columns that were added in newer versions.
|
||||
|
||||
Args:
|
||||
database_path: Path to the SQLite database file
|
||||
"""
|
||||
import sqlite3
|
||||
|
||||
try:
|
||||
conn = sqlite3.connect(database_path)
|
||||
cursor = conn.cursor()
|
||||
|
||||
# Check if latitude/longitude columns exist
|
||||
cursor.execute("PRAGMA table_info(ip_stats)")
|
||||
columns = [row[1] for row in cursor.fetchall()]
|
||||
|
||||
migrations_run = []
|
||||
|
||||
# Add latitude column if missing
|
||||
if "latitude" not in columns:
|
||||
cursor.execute("ALTER TABLE ip_stats ADD COLUMN latitude REAL")
|
||||
migrations_run.append("latitude")
|
||||
|
||||
# Add longitude column if missing
|
||||
if "longitude" not in columns:
|
||||
cursor.execute("ALTER TABLE ip_stats ADD COLUMN longitude REAL")
|
||||
migrations_run.append("longitude")
|
||||
|
||||
if migrations_run:
|
||||
conn.commit()
|
||||
applogger.info(
|
||||
f"Auto-migration: Added columns {', '.join(migrations_run)} to ip_stats table"
|
||||
)
|
||||
|
||||
conn.close()
|
||||
except Exception as e:
|
||||
applogger.error(f"Auto-migration failed: {e}")
|
||||
# Don't raise - allow app to continue even if migration fails
|
||||
|
||||
@property
|
||||
def session(self) -> Session:
|
||||
"""Get a thread-local database session."""
|
||||
@@ -399,6 +443,8 @@ class DatabaseManager:
|
||||
asn_org: str,
|
||||
list_on: Dict[str, str],
|
||||
city: Optional[str] = None,
|
||||
latitude: Optional[float] = None,
|
||||
longitude: Optional[float] = None,
|
||||
) -> None:
|
||||
"""
|
||||
Update IP rep stats
|
||||
@@ -410,6 +456,8 @@ class DatabaseManager:
|
||||
asn_org: IP address ASN ORG
|
||||
list_on: public lists containing the IP address
|
||||
city: City name (optional)
|
||||
latitude: Latitude coordinate (optional)
|
||||
longitude: Longitude coordinate (optional)
|
||||
|
||||
"""
|
||||
session = self.session
|
||||
@@ -423,6 +471,10 @@ class DatabaseManager:
|
||||
ip_stats.list_on = list_on
|
||||
if city:
|
||||
ip_stats.city = city
|
||||
if latitude is not None:
|
||||
ip_stats.latitude = latitude
|
||||
if longitude is not None:
|
||||
ip_stats.longitude = longitude
|
||||
session.commit()
|
||||
except Exception as e:
|
||||
session.rollback()
|
||||
@@ -433,7 +485,7 @@ class DatabaseManager:
|
||||
def get_unenriched_ips(self, limit: int = 100) -> List[str]:
|
||||
"""
|
||||
Get IPs that don't have complete reputation data yet.
|
||||
Returns IPs without country_code OR without city data.
|
||||
Returns IPs without country_code, city, latitude, or longitude data.
|
||||
Excludes RFC1918 private addresses and other non-routable IPs.
|
||||
|
||||
Args:
|
||||
@@ -442,27 +494,61 @@ class DatabaseManager:
|
||||
Returns:
|
||||
List of IP addresses without complete reputation data
|
||||
"""
|
||||
from sqlalchemy.exc import OperationalError
|
||||
|
||||
session = self.session
|
||||
try:
|
||||
ips = (
|
||||
session.query(IpStats.ip)
|
||||
.filter(
|
||||
or_(IpStats.country_code.is_(None), IpStats.city.is_(None)),
|
||||
~IpStats.ip.like("10.%"),
|
||||
~IpStats.ip.like("172.16.%"),
|
||||
~IpStats.ip.like("172.17.%"),
|
||||
~IpStats.ip.like("172.18.%"),
|
||||
~IpStats.ip.like("172.19.%"),
|
||||
~IpStats.ip.like("172.2_.%"),
|
||||
~IpStats.ip.like("172.30.%"),
|
||||
~IpStats.ip.like("172.31.%"),
|
||||
~IpStats.ip.like("192.168.%"),
|
||||
~IpStats.ip.like("127.%"),
|
||||
~IpStats.ip.like("169.254.%"),
|
||||
# Try to query including latitude/longitude (for backward compatibility)
|
||||
try:
|
||||
ips = (
|
||||
session.query(IpStats.ip)
|
||||
.filter(
|
||||
or_(
|
||||
IpStats.country_code.is_(None),
|
||||
IpStats.city.is_(None),
|
||||
IpStats.latitude.is_(None),
|
||||
IpStats.longitude.is_(None),
|
||||
),
|
||||
~IpStats.ip.like("10.%"),
|
||||
~IpStats.ip.like("172.16.%"),
|
||||
~IpStats.ip.like("172.17.%"),
|
||||
~IpStats.ip.like("172.18.%"),
|
||||
~IpStats.ip.like("172.19.%"),
|
||||
~IpStats.ip.like("172.2_.%"),
|
||||
~IpStats.ip.like("172.30.%"),
|
||||
~IpStats.ip.like("172.31.%"),
|
||||
~IpStats.ip.like("192.168.%"),
|
||||
~IpStats.ip.like("127.%"),
|
||||
~IpStats.ip.like("169.254.%"),
|
||||
)
|
||||
.limit(limit)
|
||||
.all()
|
||||
)
|
||||
.limit(limit)
|
||||
.all()
|
||||
)
|
||||
except OperationalError as e:
|
||||
# If latitude/longitude columns don't exist yet, fall back to old query
|
||||
if "no such column" in str(e).lower():
|
||||
ips = (
|
||||
session.query(IpStats.ip)
|
||||
.filter(
|
||||
or_(IpStats.country_code.is_(None), IpStats.city.is_(None)),
|
||||
~IpStats.ip.like("10.%"),
|
||||
~IpStats.ip.like("172.16.%"),
|
||||
~IpStats.ip.like("172.17.%"),
|
||||
~IpStats.ip.like("172.18.%"),
|
||||
~IpStats.ip.like("172.19.%"),
|
||||
~IpStats.ip.like("172.2_.%"),
|
||||
~IpStats.ip.like("172.30.%"),
|
||||
~IpStats.ip.like("172.31.%"),
|
||||
~IpStats.ip.like("192.168.%"),
|
||||
~IpStats.ip.like("127.%"),
|
||||
~IpStats.ip.like("169.254.%"),
|
||||
)
|
||||
.limit(limit)
|
||||
.all()
|
||||
)
|
||||
else:
|
||||
raise
|
||||
|
||||
return [ip[0] for ip in ips]
|
||||
finally:
|
||||
self.close_session()
|
||||
@@ -718,6 +804,8 @@ class DatabaseManager:
|
||||
"last_seen": a.last_seen.isoformat() if a.last_seen else None,
|
||||
"country_code": a.country_code,
|
||||
"city": a.city,
|
||||
"latitude": a.latitude,
|
||||
"longitude": a.longitude,
|
||||
"asn": a.asn,
|
||||
"asn_org": a.asn_org,
|
||||
"reputation_score": a.reputation_score,
|
||||
@@ -813,6 +901,8 @@ class DatabaseManager:
|
||||
"last_seen": ip.last_seen.isoformat() if ip.last_seen else None,
|
||||
"country_code": ip.country_code,
|
||||
"city": ip.city,
|
||||
"latitude": ip.latitude,
|
||||
"longitude": ip.longitude,
|
||||
"asn": ip.asn,
|
||||
"asn_org": ip.asn_org,
|
||||
"reputation_score": ip.reputation_score,
|
||||
|
||||
@@ -1,2 +0,0 @@
|
||||
175.23.45.67
|
||||
210.45.67.89
|
||||
@@ -493,6 +493,47 @@ class Handler(BaseHTTPRequestHandler):
|
||||
return
|
||||
user_agent = self._get_user_agent()
|
||||
|
||||
# Handle static files for dashboard
|
||||
if self.config.dashboard_secret_path and self.path.startswith(
|
||||
f"{self.config.dashboard_secret_path}/static/"
|
||||
):
|
||||
import os
|
||||
|
||||
file_path = self.path.replace(
|
||||
f"{self.config.dashboard_secret_path}/static/", ""
|
||||
)
|
||||
static_dir = os.path.join(os.path.dirname(__file__), "templates", "static")
|
||||
full_path = os.path.join(static_dir, file_path)
|
||||
|
||||
# Security check: ensure the path is within static directory
|
||||
if os.path.commonpath(
|
||||
[full_path, static_dir]
|
||||
) == static_dir and os.path.exists(full_path):
|
||||
try:
|
||||
with open(full_path, "rb") as f:
|
||||
content = f.read()
|
||||
self.send_response(200)
|
||||
if file_path.endswith(".svg"):
|
||||
self.send_header("Content-type", "image/svg+xml")
|
||||
elif file_path.endswith(".css"):
|
||||
self.send_header("Content-type", "text/css")
|
||||
elif file_path.endswith(".js"):
|
||||
self.send_header("Content-type", "application/javascript")
|
||||
else:
|
||||
self.send_header("Content-type", "application/octet-stream")
|
||||
self.send_header("Content-Length", str(len(content)))
|
||||
self.end_headers()
|
||||
self.wfile.write(content)
|
||||
return
|
||||
except Exception as e:
|
||||
self.app_logger.error(f"Error serving static file: {e}")
|
||||
|
||||
self.send_response(404)
|
||||
self.send_header("Content-type", "text/plain")
|
||||
self.end_headers()
|
||||
self.wfile.write(b"Not found")
|
||||
return
|
||||
|
||||
if (
|
||||
self.config.dashboard_secret_path
|
||||
and self.path == self.config.dashboard_secret_path
|
||||
|
||||
@@ -8,7 +8,16 @@ Stores access logs, credential attempts, attack detections, and IP statistics.
|
||||
from datetime import datetime
|
||||
from typing import Optional, List, Dict
|
||||
|
||||
from sqlalchemy import String, Integer, Boolean, DateTime, ForeignKey, Index, JSON
|
||||
from sqlalchemy import (
|
||||
String,
|
||||
Integer,
|
||||
Boolean,
|
||||
DateTime,
|
||||
Float,
|
||||
ForeignKey,
|
||||
Index,
|
||||
JSON,
|
||||
)
|
||||
from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column, relationship
|
||||
|
||||
from sanitizer import (
|
||||
@@ -153,6 +162,8 @@ class IpStats(Base):
|
||||
# GeoIP fields (populated by future enrichment)
|
||||
country_code: Mapped[Optional[str]] = mapped_column(String(2), nullable=True)
|
||||
city: Mapped[Optional[str]] = mapped_column(String(MAX_CITY_LENGTH), nullable=True)
|
||||
latitude: Mapped[Optional[float]] = mapped_column(Float, nullable=True)
|
||||
longitude: Mapped[Optional[float]] = mapped_column(Float, nullable=True)
|
||||
asn: Mapped[Optional[int]] = mapped_column(Integer, nullable=True)
|
||||
asn_org: Mapped[Optional[str]] = mapped_column(
|
||||
String(MAX_ASN_ORG_LENGTH), nullable=True
|
||||
|
||||
@@ -29,26 +29,26 @@ def print_usage():
|
||||
print("If no file is provided, random links will be generated.\n")
|
||||
print("Configuration:")
|
||||
print(" Configuration is loaded from a YAML file (default: config.yaml)")
|
||||
print(" Set CONFIG_LOCATION environment variable to use a different file.\n")
|
||||
print(" Example config.yaml structure:")
|
||||
print(" server:")
|
||||
print(" port: 5000")
|
||||
print(" delay: 100")
|
||||
print(" links:")
|
||||
print(" min_length: 5")
|
||||
print(" max_length: 15")
|
||||
print(" min_per_page: 10")
|
||||
print(" max_per_page: 15")
|
||||
print(" canary:")
|
||||
print(" token_url: null")
|
||||
print(" token_tries: 10")
|
||||
print(" dashboard:")
|
||||
print(" secret_path: null # auto-generated if not set")
|
||||
print(" database:")
|
||||
print(' path: "data/krawl.db"')
|
||||
print(" retention_days: 30")
|
||||
print(" behavior:")
|
||||
print(" probability_error_codes: 0")
|
||||
print("Set CONFIG_LOCATION environment variable to use a different file.\n")
|
||||
print("Example config.yaml structure:")
|
||||
print("server:")
|
||||
print("port: 5000")
|
||||
print("delay: 100")
|
||||
print("links:")
|
||||
print("min_length: 5")
|
||||
print("max_length: 15")
|
||||
print("min_per_page: 10")
|
||||
print("max_per_page: 15")
|
||||
print("canary:")
|
||||
print("token_url: null")
|
||||
print("token_tries: 10")
|
||||
print("dashboard:")
|
||||
print("secret_path: null # auto-generated if not set")
|
||||
print("database:")
|
||||
print('path: "data/krawl.db"')
|
||||
print("retention_days: 30")
|
||||
print("behavior:")
|
||||
print("probability_error_codes: 0")
|
||||
|
||||
|
||||
def main():
|
||||
@@ -103,8 +103,16 @@ def main():
|
||||
tasks_master.run_scheduled_tasks()
|
||||
|
||||
try:
|
||||
|
||||
banner = f"""
|
||||
|
||||
============================================================
|
||||
DASHBOARD AVAILABLE AT
|
||||
{config.dashboard_secret_path}
|
||||
============================================================
|
||||
"""
|
||||
app_logger.info(banner)
|
||||
app_logger.info(f"Starting deception server on port {config.port}...")
|
||||
app_logger.info(f"Dashboard available at: {config.dashboard_secret_path}")
|
||||
if config.canary_token_url:
|
||||
app_logger.info(
|
||||
f"Canary token will appear after {config.canary_token_tries} tries"
|
||||
|
||||
@@ -45,6 +45,8 @@ def main():
|
||||
country_iso_code = geoip_data.get("country_iso_code")
|
||||
asn = geoip_data.get("asn_autonomous_system_number")
|
||||
asn_org = geoip_data.get("asn_autonomous_system_organization")
|
||||
latitude = geoip_data.get("location_latitude")
|
||||
longitude = geoip_data.get("location_longitude")
|
||||
|
||||
# Extract city from coordinates using reverse geocoding
|
||||
city = extract_city_from_coordinates(geoip_data)
|
||||
@@ -62,6 +64,8 @@ def main():
|
||||
sanitized_asn_org,
|
||||
sanitized_list_on,
|
||||
sanitized_city,
|
||||
latitude,
|
||||
longitude,
|
||||
)
|
||||
except requests.RequestException as e:
|
||||
app_logger.warning(f"Failed to fetch IP rep for {ip}: {e}")
|
||||
|
||||
@@ -6,7 +6,7 @@ from zoneinfo import ZoneInfo
|
||||
from logger import get_app_logger
|
||||
from database import get_database
|
||||
from config import get_config
|
||||
from models import AccessLog
|
||||
from models import AccessLog, IpStats
|
||||
from ip_utils import is_local_or_private_ip, is_valid_public_ip
|
||||
from sqlalchemy import distinct
|
||||
|
||||
@@ -44,7 +44,8 @@ def has_recent_honeypot_access(session, minutes: int = 5) -> bool:
|
||||
|
||||
def main():
|
||||
"""
|
||||
Export all IPs flagged as suspicious to a text file.
|
||||
Export all attacker IPs to a text file, matching the "Attackers by Total Requests" dashboard table.
|
||||
Uses the same query as the dashboard: IpStats where category == "attacker", ordered by total_requests.
|
||||
TasksMaster will call this function based on the cron schedule.
|
||||
"""
|
||||
task_name = TASK_CONFIG.get("name")
|
||||
@@ -61,10 +62,11 @@ def main():
|
||||
)
|
||||
return
|
||||
|
||||
# Query distinct suspicious IPs
|
||||
results = (
|
||||
session.query(distinct(AccessLog.ip))
|
||||
.filter(AccessLog.is_suspicious == True)
|
||||
# Query attacker IPs from IpStats (same as dashboard "Attackers by Total Requests")
|
||||
attackers = (
|
||||
session.query(IpStats)
|
||||
.filter(IpStats.category == "attacker")
|
||||
.order_by(IpStats.total_requests.desc())
|
||||
.all()
|
||||
)
|
||||
|
||||
@@ -72,7 +74,11 @@ def main():
|
||||
config = get_config()
|
||||
server_ip = config.get_server_ip()
|
||||
|
||||
public_ips = [ip for (ip,) in results if is_valid_public_ip(ip, server_ip)]
|
||||
public_ips = [
|
||||
attacker.ip
|
||||
for attacker in attackers
|
||||
if is_valid_public_ip(attacker.ip, server_ip)
|
||||
]
|
||||
|
||||
# Ensure exports directory exists
|
||||
os.makedirs(EXPORTS_DIR, exist_ok=True)
|
||||
@@ -83,8 +89,8 @@ def main():
|
||||
f.write(f"{ip}\n")
|
||||
|
||||
app_logger.info(
|
||||
f"[Background Task] {task_name} exported {len(public_ips)} public IPs "
|
||||
f"(filtered {len(results) - len(public_ips)} local/private IPs) to {OUTPUT_FILE}"
|
||||
f"[Background Task] {task_name} exported {len(public_ips)} attacker IPs "
|
||||
f"(filtered {len(attackers) - len(public_ips)} local/private IPs) to {OUTPUT_FILE}"
|
||||
)
|
||||
|
||||
except Exception as e:
|
||||
|
||||
@@ -68,6 +68,7 @@ def generate_dashboard(stats: dict, dashboard_path: str = "") -> str:
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Krawl Dashboard</title>
|
||||
<link rel="icon" type="image/svg+xml" href="https://raw.githubusercontent.com/BlessedRebuS/Krawl/refs/heads/main/img/krawl-svg.svg" />
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.9.4/leaflet.min.css" />
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.9.4/leaflet.min.js"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.9.1/chart.min.js"></script>
|
||||
@@ -84,6 +85,30 @@ def generate_dashboard(stats: dict, dashboard_path: str = "") -> str:
|
||||
margin: 0 auto;
|
||||
position: relative;
|
||||
}}
|
||||
.github-logo {{
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
text-decoration: none;
|
||||
color: #58a6ff;
|
||||
transition: color 0.2s;
|
||||
}}
|
||||
.github-logo:hover {{
|
||||
color: #79c0ff;
|
||||
}}
|
||||
.github-logo svg {{
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
fill: currentColor;
|
||||
}}
|
||||
.github-logo-text {{
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
text-decoration: none;
|
||||
}}
|
||||
h1 {{
|
||||
color: #58a6ff;
|
||||
text-align: center;
|
||||
@@ -536,17 +561,25 @@ def generate_dashboard(stats: dict, dashboard_path: str = "") -> str:
|
||||
filter: none;
|
||||
}}
|
||||
.leaflet-popup-content-wrapper {{
|
||||
background-color: #161b22;
|
||||
background-color: #0d1117;
|
||||
color: #c9d1d9;
|
||||
border: 1px solid #30363d;
|
||||
border-radius: 4px;
|
||||
border-radius: 6px;
|
||||
padding: 0;
|
||||
}}
|
||||
.leaflet-popup-content {{
|
||||
margin: 0;
|
||||
min-width: 280px;
|
||||
}}
|
||||
.leaflet-popup-content-wrapper a {{
|
||||
color: #58a6ff;
|
||||
}}
|
||||
.leaflet-popup-tip {{
|
||||
background: #161b22;
|
||||
border-top: 6px solid #30363d;
|
||||
background: #0d1117;
|
||||
border: 1px solid #30363d;
|
||||
}}
|
||||
.ip-detail-popup .leaflet-popup-content-wrapper {{
|
||||
max-width: 340px !important;
|
||||
}}
|
||||
/* Remove the default leaflet icon background */
|
||||
.ip-custom-marker {{
|
||||
@@ -614,6 +647,12 @@ def generate_dashboard(stats: dict, dashboard_path: str = "") -> str:
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<a href="https://github.com/BlessedRebuS/Krawl" class="github-logo" target="_blank" rel="noopener noreferrer">
|
||||
<svg viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.012 8.012 0 0 0 16 8c0-4.42-3.58-8-8-8z"/>
|
||||
</svg>
|
||||
<span class="github-logo-text">BlessedRebuS/Krawl</span>
|
||||
</a>
|
||||
<div class="download-section">
|
||||
<a href="{dashboard_path}/api/download/malicious_ips.txt" class="download-btn" download>
|
||||
Export Malicious IPs
|
||||
@@ -767,23 +806,23 @@ def generate_dashboard(stats: dict, dashboard_path: str = "") -> str:
|
||||
<div style="display: flex; gap: 16px; align-items: center; flex-wrap: wrap;">
|
||||
<label style="display: flex; align-items: center; gap: 6px; cursor: pointer; color: #c9d1d9; font-size: 13px;">
|
||||
<input type="checkbox" id="filter-attacker" checked onchange="updateMapFilters()" style="cursor: pointer;">
|
||||
<span style="color: #f85149;">● Attackers</span>
|
||||
<span style="color: #f85149;">Attackers</span>
|
||||
</label>
|
||||
<label style="display: flex; align-items: center; gap: 6px; cursor: pointer; color: #c9d1d9; font-size: 13px;">
|
||||
<input type="checkbox" id="filter-bad-crawler" checked onchange="updateMapFilters()" style="cursor: pointer;">
|
||||
<span style="color: #f0883e;">● Bad Crawlers</span>
|
||||
<span style="color: #f0883e;">Bad Crawlers</span>
|
||||
</label>
|
||||
<label style="display: flex; align-items: center; gap: 6px; cursor: pointer; color: #c9d1d9; font-size: 13px;">
|
||||
<input type="checkbox" id="filter-good-crawler" checked onchange="updateMapFilters()" style="cursor: pointer;">
|
||||
<span style="color: #3fb950;">● Good Crawlers</span>
|
||||
<span style="color: #3fb950;">Good Crawlers</span>
|
||||
</label>
|
||||
<label style="display: flex; align-items: center; gap: 6px; cursor: pointer; color: #c9d1d9; font-size: 13px;">
|
||||
<input type="checkbox" id="filter-regular-user" checked onchange="updateMapFilters()" style="cursor: pointer;">
|
||||
<span style="color: #58a6ff;">● Regular Users</span>
|
||||
<span style="color: #58a6ff;">Regular Users</span>
|
||||
</label>
|
||||
<label style="display: flex; align-items: center; gap: 6px; cursor: pointer; color: #c9d1d9; font-size: 13px;">
|
||||
<input type="checkbox" id="filter-unknown" checked onchange="updateMapFilters()" style="cursor: pointer;">
|
||||
<span style="color: #8b949e;">● Unknown</span>
|
||||
<span style="color: #8b949e;">Unknown</span>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
@@ -884,8 +923,11 @@ def generate_dashboard(stats: dict, dashboard_path: str = "") -> str:
|
||||
</div>
|
||||
|
||||
<div class="table-container alert-section" style="margin-top: 20px;">
|
||||
<h2>Most Recurring Attack Types</h2>
|
||||
<div style="position: relative; height: 400px; margin-top: 20px;">
|
||||
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 20px;">
|
||||
<h2 style="margin: 0;">Most Recurring Attack Types</h2>
|
||||
<div style="font-size: 12px; color: #8b949e;">Top 10 Attack Vectors</div>
|
||||
</div>
|
||||
<div style="position: relative; height: 450px; margin-top: 20px;">
|
||||
<canvas id="attack-types-chart"></canvas>
|
||||
</div>
|
||||
</div>
|
||||
@@ -1221,6 +1263,97 @@ def generate_dashboard(stats: dict, dashboard_path: str = "") -> str:
|
||||
return html;
|
||||
}}
|
||||
|
||||
// Generate radar chart for map panel
|
||||
function generateMapPanelRadarChart(categoryScores) {{
|
||||
if (!categoryScores || Object.keys(categoryScores).length === 0) {{
|
||||
return '<div style="color: #8b949e; text-align: center; padding: 20px;">No category data available</div>';
|
||||
}}
|
||||
|
||||
let html = '<div style="display: flex; flex-direction: column; align-items: center;">';
|
||||
html += '<svg class="radar-chart" viewBox="-30 -30 260 260" preserveAspectRatio="xMidYMid meet" style="width: 160px; height: 160px;">';
|
||||
|
||||
const scores = {{
|
||||
attacker: categoryScores.attacker || 0,
|
||||
good_crawler: categoryScores.good_crawler || 0,
|
||||
bad_crawler: categoryScores.bad_crawler || 0,
|
||||
regular_user: categoryScores.regular_user || 0,
|
||||
unknown: categoryScores.unknown || 0
|
||||
}};
|
||||
|
||||
const maxScore = Math.max(...Object.values(scores), 1);
|
||||
const minVisibleRadius = 0.15;
|
||||
const normalizedScores = {{}};
|
||||
|
||||
Object.keys(scores).forEach(key => {{
|
||||
normalizedScores[key] = minVisibleRadius + (scores[key] / maxScore) * (1 - minVisibleRadius);
|
||||
}});
|
||||
|
||||
const colors = {{
|
||||
attacker: '#f85149',
|
||||
good_crawler: '#3fb950',
|
||||
bad_crawler: '#f0883e',
|
||||
regular_user: '#58a6ff',
|
||||
unknown: '#8b949e'
|
||||
}};
|
||||
|
||||
const labels = {{
|
||||
attacker: 'Attacker',
|
||||
good_crawler: 'Good Bot',
|
||||
bad_crawler: 'Bad Bot',
|
||||
regular_user: 'User',
|
||||
unknown: 'Unknown'
|
||||
}};
|
||||
|
||||
const cx = 100, cy = 100, maxRadius = 75;
|
||||
for (let i = 1; i <= 5; i++) {{
|
||||
const r = (maxRadius / 5) * i;
|
||||
html += `<circle cx="${{cx}}" cy="${{cy}}" r="${{r}}" fill="none" stroke="#30363d" stroke-width="0.5"/>`;
|
||||
}}
|
||||
|
||||
const angles = [0, 72, 144, 216, 288];
|
||||
const keys = ['good_crawler', 'regular_user', 'unknown', 'bad_crawler', 'attacker'];
|
||||
|
||||
angles.forEach((angle, i) => {{
|
||||
const rad = (angle - 90) * Math.PI / 180;
|
||||
const x2 = cx + maxRadius * Math.cos(rad);
|
||||
const y2 = cy + maxRadius * Math.sin(rad);
|
||||
html += `<line x1="${{cx}}" y1="${{cy}}" x2="${{x2}}" y2="${{y2}}" stroke="#30363d" stroke-width="0.5"/>`;
|
||||
|
||||
const labelDist = maxRadius + 35;
|
||||
const lx = cx + labelDist * Math.cos(rad);
|
||||
const ly = cy + labelDist * Math.sin(rad);
|
||||
html += `<text x="${{lx}}" y="${{ly}}" fill="#8b949e" font-size="12" text-anchor="middle" dominant-baseline="middle">${{labels[keys[i]]}}</text>`;
|
||||
}});
|
||||
|
||||
let points = [];
|
||||
angles.forEach((angle, i) => {{
|
||||
const normalizedScore = normalizedScores[keys[i]];
|
||||
const rad = (angle - 90) * Math.PI / 180;
|
||||
const r = normalizedScore * maxRadius;
|
||||
const x = cx + r * Math.cos(rad);
|
||||
const y = cy + r * Math.sin(rad);
|
||||
points.push(`${{x}},${{y}}`);
|
||||
}});
|
||||
|
||||
const dominantKey = Object.keys(scores).reduce((a, b) => scores[a] > scores[b] ? a : b);
|
||||
const dominantColor = colors[dominantKey];
|
||||
|
||||
html += `<polygon points="${{points.join(' ')}}" fill="${{dominantColor}}" fill-opacity="0.4" stroke="${{dominantColor}}" stroke-width="2.5"/>`;
|
||||
|
||||
angles.forEach((angle, i) => {{
|
||||
const normalizedScore = normalizedScores[keys[i]];
|
||||
const rad = (angle - 90) * Math.PI / 180;
|
||||
const r = normalizedScore * maxRadius;
|
||||
const x = cx + r * Math.cos(rad);
|
||||
const y = cy + r * Math.sin(rad);
|
||||
html += `<circle cx="${{x}}" cy="${{y}}" r="4.5" fill="${{colors[keys[i]]}}" stroke="#0d1117" stroke-width="2"/>`;
|
||||
}});
|
||||
|
||||
html += '</svg>';
|
||||
html += '</div>';
|
||||
return html;
|
||||
}}
|
||||
|
||||
// Tab functionality with hash-based routing
|
||||
function switchTab(tabName) {{
|
||||
// Hide all tabs
|
||||
@@ -2041,7 +2174,11 @@ def generate_dashboard(stats: dict, dashboard_path: str = "") -> str:
|
||||
|
||||
// Helper function to get coordinates for an IP
|
||||
function getIPCoordinates(ip) {{
|
||||
// Try city first
|
||||
// Use actual latitude and longitude if available
|
||||
if (ip.latitude != null && ip.longitude != null) {{
|
||||
return [ip.latitude, ip.longitude];
|
||||
}}
|
||||
// Fall back to city lookup
|
||||
if (ip.city && cityCoordinates[ip.city]) {{
|
||||
return cityCoordinates[ip.city];
|
||||
}}
|
||||
@@ -2102,9 +2239,11 @@ def generate_dashboard(stats: dict, dashboard_path: str = "") -> str:
|
||||
const category = ip.category.toLowerCase();
|
||||
if (!markerLayers[category]) return;
|
||||
|
||||
// Calculate marker size based on request count
|
||||
const sizeRatio = (ip.total_requests / maxRequests) * 0.7 + 0.3;
|
||||
const markerSize = Math.max(15, Math.min(40, 20 * sizeRatio));
|
||||
// Calculate marker size based on request count with more dramatic scaling
|
||||
// Scale up to 10,000 requests, then cap it
|
||||
const requestsForScale = Math.min(ip.total_requests, 10000);
|
||||
const sizeRatio = Math.pow(requestsForScale / 10000, 0.5); // Square root for better visual scaling
|
||||
const markerSize = Math.max(10, Math.min(30, 10 + (sizeRatio * 20)));
|
||||
|
||||
// Create custom marker element with category-specific class
|
||||
const markerElement = document.createElement('div');
|
||||
@@ -2122,7 +2261,7 @@ def generate_dashboard(stats: dict, dashboard_path: str = "") -> str:
|
||||
}})
|
||||
}});
|
||||
|
||||
// Create popup content with category badge
|
||||
// Create popup with category badge and chart
|
||||
const categoryColor = categoryColors[category] || '#8b949e';
|
||||
const categoryLabels = {{
|
||||
attacker: 'Attacker',
|
||||
@@ -2132,26 +2271,103 @@ def generate_dashboard(stats: dict, dashboard_path: str = "") -> str:
|
||||
unknown: 'Unknown'
|
||||
}};
|
||||
|
||||
const popupContent = `
|
||||
<div style="padding: 8px; min-width: 220px;">
|
||||
<div style="display: flex; align-items: center; justify-content: space-between; margin-bottom: 8px;">
|
||||
<strong style="color: #58a6ff;">${{ip.ip}}</strong>
|
||||
<span style="background: ${{categoryColor}}1a; color: ${{categoryColor}}; padding: 2px 8px; border-radius: 12px; font-size: 11px; font-weight: 600;">
|
||||
${{categoryLabels[category]}}
|
||||
</span>
|
||||
</div>
|
||||
<span style="color: #8b949e; font-size: 12px;">
|
||||
${{ip.city ? (ip.country_code ? `${{ip.city}}, ${{ip.country_code}}` : ip.city) : (ip.country_code || 'Unknown')}}
|
||||
</span><br/>
|
||||
<div style="margin-top: 8px; border-top: 1px solid #30363d; padding-top: 8px;">
|
||||
<div><span style="color: #8b949e;">Requests:</span> <span style="color: ${{categoryColor}}; font-weight: bold;">${{ip.total_requests}}</span></div>
|
||||
<div><span style="color: #8b949e;">First Seen:</span> <span style="color: #58a6ff;">${{formatTimestamp(ip.first_seen)}}</span></div>
|
||||
<div><span style="color: #8b949e;">Last Seen:</span> <span style="color: #58a6ff;">${{formatTimestamp(ip.last_seen)}}</span></div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
// Bind popup once when marker is created
|
||||
marker.bindPopup('', {{
|
||||
maxWidth: 550,
|
||||
className: 'ip-detail-popup'
|
||||
}});
|
||||
|
||||
// Add click handler to fetch data and show popup
|
||||
marker.on('click', async function(e) {{
|
||||
// Show loading popup first
|
||||
const loadingPopup = `
|
||||
<div style="padding: 12px; min-width: 280px; max-width: 320px;">
|
||||
<div style="display: flex; align-items: center; justify-content: space-between; margin-bottom: 8px;">
|
||||
<strong style="color: #58a6ff; font-size: 14px;">${{ip.ip}}</strong>
|
||||
<span style="background: ${{categoryColor}}1a; color: ${{categoryColor}}; padding: 2px 8px; border-radius: 12px; font-size: 11px; font-weight: 600;">
|
||||
${{categoryLabels[category]}}
|
||||
</span>
|
||||
</div>
|
||||
<div style="text-align: center; padding: 20px; color: #8b949e;">
|
||||
<div style="font-size: 12px;">Loading details...</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
marker.setPopupContent(loadingPopup);
|
||||
marker.openPopup();
|
||||
|
||||
try {{
|
||||
console.log('Fetching IP stats for:', ip.ip);
|
||||
const response = await fetch(`${{DASHBOARD_PATH}}/api/ip-stats/${{ip.ip}}`);
|
||||
if (!response.ok) throw new Error('Failed to fetch IP stats');
|
||||
|
||||
const stats = await response.json();
|
||||
console.log('Received stats:', stats);
|
||||
|
||||
// Build complete popup content with chart
|
||||
let popupContent = `
|
||||
<div style="padding: 12px; min-width: 200px;">
|
||||
<div style="display: flex; align-items: center; justify-content: space-between; margin-bottom: 8px;">
|
||||
<strong style="color: #58a6ff; font-size: 14px;">${{ip.ip}}</strong>
|
||||
<span style="background: ${{categoryColor}}1a; color: ${{categoryColor}}; padding: 2px 8px; border-radius: 12px; font-size: 11px; font-weight: 600;">
|
||||
${{categoryLabels[category]}}
|
||||
</span>
|
||||
</div>
|
||||
<span style="color: #8b949e; font-size: 12px;">
|
||||
${{ip.city ? (ip.country_code ? `${{ip.city}}, ${{ip.country_code}}` : ip.city) : (ip.country_code || 'Unknown')}}
|
||||
</span><br/>
|
||||
<div style="margin-top: 8px; border-top: 1px solid #30363d; padding-top: 8px;">
|
||||
<div style="margin-bottom: 4px;"><span style="color: #8b949e;">Requests:</span> <span style="color: ${{categoryColor}}; font-weight: bold;">${{ip.total_requests}}</span></div>
|
||||
<div style="margin-bottom: 4px;"><span style="color: #8b949e;">First Seen:</span> <span style="color: #58a6ff; font-size: 11px;">${{formatTimestamp(ip.first_seen)}}</span></div>
|
||||
<div style="margin-bottom: 4px;"><span style="color: #8b949e;">Last Seen:</span> <span style="color: #58a6ff; font-size: 11px;">${{formatTimestamp(ip.last_seen)}}</span></div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
// Add chart if category scores exist
|
||||
if (stats.category_scores && Object.keys(stats.category_scores).length > 0) {{
|
||||
console.log('Category scores found:', stats.category_scores);
|
||||
const chartHtml = generateMapPanelRadarChart(stats.category_scores);
|
||||
console.log('Generated chart HTML length:', chartHtml.length);
|
||||
popupContent += `
|
||||
<div style="margin-top: 12px; border-top: 1px solid #30363d; padding-top: 12px;">
|
||||
${{chartHtml}}
|
||||
</div>
|
||||
`;
|
||||
}}
|
||||
|
||||
popupContent += '</div>';
|
||||
|
||||
// Update popup content
|
||||
console.log('Updating popup content');
|
||||
marker.setPopupContent(popupContent);
|
||||
}} catch (err) {{
|
||||
console.error('Error fetching IP stats:', err);
|
||||
const errorPopup = `
|
||||
<div style="padding: 12px; min-width: 280px; max-width: 320px;">
|
||||
<div style="display: flex; align-items: center; justify-content: space-between; margin-bottom: 8px;">
|
||||
<strong style="color: #58a6ff; font-size: 14px;">${{ip.ip}}</strong>
|
||||
<span style="background: ${{categoryColor}}1a; color: ${{categoryColor}}; padding: 2px 8px; border-radius: 12px; font-size: 11px; font-weight: 600;">
|
||||
${{categoryLabels[category]}}
|
||||
</span>
|
||||
</div>
|
||||
<span style="color: #8b949e; font-size: 12px;">
|
||||
${{ip.city ? (ip.country_code ? `${{ip.city}}, ${{ip.country_code}}` : ip.city) : (ip.country_code || 'Unknown')}}
|
||||
</span><br/>
|
||||
<div style="margin-top: 8px; border-top: 1px solid #30363d; padding-top: 8px;">
|
||||
<div style="margin-bottom: 4px;"><span style="color: #8b949e;">Requests:</span> <span style="color: ${{categoryColor}}; font-weight: bold;">${{ip.total_requests}}</span></div>
|
||||
<div style="margin-bottom: 4px;"><span style="color: #8b949e;">First Seen:</span> <span style="color: #58a6ff; font-size: 11px;">${{formatTimestamp(ip.first_seen)}}</span></div>
|
||||
<div style="margin-bottom: 4px;"><span style="color: #8b949e;">Last Seen:</span> <span style="color: #58a6ff; font-size: 11px;">${{formatTimestamp(ip.last_seen)}}</span></div>
|
||||
</div>
|
||||
<div style="margin-top: 12px; border-top: 1px solid #30363d; padding-top: 12px; text-align: center; color: #f85149; font-size: 11px;">
|
||||
Failed to load chart: ${{err.message}}
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
marker.setPopupContent(errorPopup);
|
||||
}}
|
||||
}});
|
||||
|
||||
marker.bindPopup(popupContent);
|
||||
markerLayers[category].addLayer(marker);
|
||||
}});
|
||||
|
||||
@@ -2270,23 +2486,51 @@ def generate_dashboard(stats: dict, dashboard_path: str = "") -> str:
|
||||
|
||||
const labels = sortedAttacks.map(([type]) => type);
|
||||
const counts = sortedAttacks.map(([, count]) => count);
|
||||
const maxCount = Math.max(...counts);
|
||||
|
||||
// Define colors for different attack types
|
||||
// Enhanced color palette with gradients
|
||||
const colorMap = {{
|
||||
'SQL Injection': '#0969da',
|
||||
'XSS': '#1f6feb',
|
||||
'Directory Traversal': '#2f81f7',
|
||||
'Command Injection': '#54aeff',
|
||||
'Path Traversal': '#79c0ff',
|
||||
'Malware': '#58a6ff',
|
||||
'Brute Force': '#388bfd',
|
||||
'DDoS': '#1a7ae8',
|
||||
'CSRF': '#0860ca',
|
||||
'File Upload': '#1158d4'
|
||||
'SQL Injection': 'rgba(233, 105, 113, 0.85)',
|
||||
'XSS': 'rgba(240, 136, 62, 0.85)',
|
||||
'Directory Traversal': 'rgba(248, 150, 56, 0.85)',
|
||||
'Command Injection': 'rgba(229, 229, 16, 0.85)',
|
||||
'Path Traversal': 'rgba(123, 201, 71, 0.85)',
|
||||
'Malware': 'rgba(88, 166, 255, 0.85)',
|
||||
'Brute Force': 'rgba(79, 161, 246, 0.85)',
|
||||
'DDoS': 'rgba(139, 148, 244, 0.85)',
|
||||
'CSRF': 'rgba(188, 140, 258, 0.85)',
|
||||
'File Upload': 'rgba(241, 107, 223, 0.85)'
|
||||
}};
|
||||
|
||||
const backgroundColors = labels.map(label => colorMap[label] || '#58a6ff');
|
||||
const borderColors = labels.map(label => colorMap[label] || '#58a6ff');
|
||||
const borderColorMap = {{
|
||||
'SQL Injection': 'rgba(233, 105, 113, 1)',
|
||||
'XSS': 'rgba(240, 136, 62, 1)',
|
||||
'Directory Traversal': 'rgba(248, 150, 56, 1)',
|
||||
'Command Injection': 'rgba(229, 229, 16, 1)',
|
||||
'Path Traversal': 'rgba(123, 201, 71, 1)',
|
||||
'Malware': 'rgba(88, 166, 255, 1)',
|
||||
'Brute Force': 'rgba(79, 161, 246, 1)',
|
||||
'DDoS': 'rgba(139, 148, 244, 1)',
|
||||
'CSRF': 'rgba(188, 140, 258, 1)',
|
||||
'File Upload': 'rgba(241, 107, 223, 1)'
|
||||
}};
|
||||
|
||||
const hoverColorMap = {{
|
||||
'SQL Injection': 'rgba(233, 105, 113, 1)',
|
||||
'XSS': 'rgba(240, 136, 62, 1)',
|
||||
'Directory Traversal': 'rgba(248, 150, 56, 1)',
|
||||
'Command Injection': 'rgba(229, 229, 16, 1)',
|
||||
'Path Traversal': 'rgba(123, 201, 71, 1)',
|
||||
'Malware': 'rgba(88, 166, 255, 1)',
|
||||
'Brute Force': 'rgba(79, 161, 246, 1)',
|
||||
'DDoS': 'rgba(139, 148, 244, 1)',
|
||||
'CSRF': 'rgba(188, 140, 258, 1)',
|
||||
'File Upload': 'rgba(241, 107, 223, 1)'
|
||||
}};
|
||||
|
||||
const backgroundColors = labels.map(label => colorMap[label] || 'rgba(88, 166, 255, 0.85)');
|
||||
const borderColors = labels.map(label => borderColorMap[label] || 'rgba(88, 166, 255, 1)');
|
||||
const hoverColors = labels.map(label => hoverColorMap[label] || 'rgba(88, 166, 255, 1)');
|
||||
|
||||
// Create or update chart
|
||||
if (attackTypesChart) {{
|
||||
@@ -2302,9 +2546,9 @@ def generate_dashboard(stats: dict, dashboard_path: str = "") -> str:
|
||||
data: counts,
|
||||
backgroundColor: backgroundColors,
|
||||
borderColor: borderColors,
|
||||
borderWidth: 1.5,
|
||||
borderRadius: 4,
|
||||
hoverBackgroundColor: borderColors
|
||||
borderWidth: 2,
|
||||
borderRadius: 6,
|
||||
borderSkipped: false
|
||||
}}]
|
||||
}},
|
||||
options: {{
|
||||
@@ -2316,22 +2560,31 @@ def generate_dashboard(stats: dict, dashboard_path: str = "") -> str:
|
||||
display: false
|
||||
}},
|
||||
tooltip: {{
|
||||
backgroundColor: '#161b22',
|
||||
enabled: true,
|
||||
backgroundColor: 'rgba(22, 27, 34, 0.95)',
|
||||
titleColor: '#58a6ff',
|
||||
bodyColor: '#c9d1d9',
|
||||
borderColor: '#30363d',
|
||||
borderWidth: 1,
|
||||
padding: 10,
|
||||
borderColor: '#58a6ff',
|
||||
borderWidth: 2,
|
||||
padding: 14,
|
||||
displayColors: false,
|
||||
titleFont: {{
|
||||
size: 13,
|
||||
weight: 'bold'
|
||||
size: 14,
|
||||
weight: 'bold',
|
||||
family: "'Segoe UI', Tahoma, Geneva, Verdana"
|
||||
}},
|
||||
bodyFont: {{
|
||||
size: 12
|
||||
size: 13,
|
||||
family: "'Segoe UI', Tahoma, Geneva, Verdana"
|
||||
}},
|
||||
caretSize: 8,
|
||||
caretPadding: 12,
|
||||
callbacks: {{
|
||||
title: function(context) {{
|
||||
return '';
|
||||
}},
|
||||
label: function(context) {{
|
||||
return 'Occurrences: ' + context.parsed.x;
|
||||
return context.parsed.x;
|
||||
}}
|
||||
}}
|
||||
}}
|
||||
@@ -2342,29 +2595,63 @@ def generate_dashboard(stats: dict, dashboard_path: str = "") -> str:
|
||||
ticks: {{
|
||||
color: '#8b949e',
|
||||
font: {{
|
||||
size: 11
|
||||
size: 12,
|
||||
weight: '500'
|
||||
}}
|
||||
}},
|
||||
grid: {{
|
||||
color: '#30363d',
|
||||
drawBorder: false
|
||||
color: 'rgba(48, 54, 61, 0.4)',
|
||||
drawBorder: false,
|
||||
drawTicks: false
|
||||
}}
|
||||
}},
|
||||
y: {{
|
||||
ticks: {{
|
||||
color: '#c9d1d9',
|
||||
font: {{
|
||||
size: 12
|
||||
size: 13,
|
||||
weight: '600'
|
||||
}},
|
||||
padding: 10
|
||||
padding: 12,
|
||||
callback: function(value, index) {{
|
||||
const label = this.getLabelForValue(value);
|
||||
const maxLength = 25;
|
||||
return label.length > maxLength ? label.substring(0, maxLength) + '…' : label;
|
||||
}}
|
||||
}},
|
||||
grid: {{
|
||||
display: false,
|
||||
drawBorder: false
|
||||
}}
|
||||
}}
|
||||
}},
|
||||
animation: {{
|
||||
duration: 1000,
|
||||
easing: 'easeInOutQuart',
|
||||
delay: (context) => {{
|
||||
let delay = 0;
|
||||
if (context.type === 'data') {{
|
||||
delay = context.dataIndex * 50 + context.datasetIndex * 100;
|
||||
}}
|
||||
return delay;
|
||||
}}
|
||||
}},
|
||||
onHover: (event, activeElements) => {{
|
||||
canvas.style.cursor = activeElements.length > 0 ? 'pointer' : 'default';
|
||||
}}
|
||||
}}
|
||||
}},
|
||||
plugins: [{{
|
||||
id: 'customCanvasBackgroundColor',
|
||||
beforeDraw: (chart) => {{
|
||||
if (chart.ctx) {{
|
||||
chart.ctx.save();
|
||||
chart.ctx.globalCompositeOperation = 'destination-over';
|
||||
chart.ctx.fillStyle = 'rgba(0,0,0,0)';
|
||||
chart.ctx.fillRect(0, 0, chart.width, chart.height);
|
||||
chart.ctx.restore();
|
||||
}}
|
||||
}}
|
||||
}}]
|
||||
}});
|
||||
|
||||
attackTypesChartLoaded = true;
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Krawl</title>
|
||||
<title>Krawl me!</title>
|
||||
<style>
|
||||
body {{
|
||||
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
|
||||
|
||||
95
src/templates/static/krawl-svg.svg
Normal file
@@ -0,0 +1,95 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
width="512"
|
||||
height="512"
|
||||
viewBox="0 0 512 512"
|
||||
version="1.1"
|
||||
id="svg1"
|
||||
xml:space="preserve"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"><defs
|
||||
id="defs1" /><g
|
||||
id="layer1"><g
|
||||
id="g21250"
|
||||
transform="matrix(0.9765625,0,0,0.9765625,1536.0434,1186.1434)"
|
||||
style="display:inline"><path
|
||||
style="display:inline;fill:#000000;fill-opacity:1;stroke-width:0.71608"
|
||||
d="m -1241.1385,-1007.2559 c -0.6853,-0.9666 -1.7404,-3.1071 -1.7404,-3.5311 0,-0.2316 -0.3925,-0.9705 -0.8724,-1.6421 -0.4797,-0.6717 -1.1665,-1.8179 -1.5259,-2.5474 -0.9428,-1.9133 -0.8327,-2.4052 1.0817,-4.8313 2.0393,-2.5844 5.4954,-7.751 7.5001,-11.212 6.6836,-11.5394 10.2543,-26.3502 10.2918,-42.6902 0.014,-6.1916 -0.3138,-11.1512 -1.4222,-21.504 -0.2511,-2.3446 -0.6286,-6.0107 -0.8388,-8.1469 -0.2102,-2.1362 -0.4642,-4.5234 -0.5643,-5.3051 -0.1004,-0.7815 -0.2787,-2.4013 -0.3968,-3.5996 -0.1181,-1.1984 -0.3302,-2.6905 -0.4713,-3.3156 -0.1411,-0.6253 -0.3476,-1.9042 -0.4588,-2.842 -0.5672,-4.7787 -3.2292,-17.1285 -4.7783,-22.1672 -0.4165,-1.3546 -1.1796,-3.9124 -1.6957,-5.6838 -0.5161,-1.7715 -1.6975,-5.4802 -2.6255,-8.2417 -4.6459,-13.8253 -4.9757,-16.427 -2.6904,-21.2198 2.0776,-4.3574 6.2598,-6.6975 11.403,-6.3802 1.8507,0.1141 3.6912,0.539 8.9047,2.0557 1.6153,0.47 3.4482,0.9897 4.0735,1.155 0.6252,0.1653 2.373,0.7217 3.884,1.2364 4.9437,1.6843 6.8819,2.3162 9.189,2.9957 1.2504,0.3683 2.6145,0.8262 3.0313,1.0174 1.1713,0.5374 2.7637,1.1747 3.5998,1.4405 1.4598,0.4641 5.4471,1.9658 6.6964,2.522 4.255,1.8943 7.767,3.4118 8.1765,3.5329 0.2605,0.077 1.9656,0.8866 3.7893,1.7989 1.8235,0.9123 4.2107,2.0926 5.3049,2.6231 1.0942,0.5304 2.6714,1.3307 3.5051,1.7785 0.8335,0.4478 2.4535,1.3177 3.5997,1.9331 2.5082,1.3467 8.2672,4.7786 10.5669,6.2972 0.9141,0.6037 2.589,1.6943 3.7218,2.4238 1.1329,0.7294 2.6443,1.763 3.3586,2.2968 0.7145,0.5337 1.6835,1.2158 2.1534,1.5157 0.4699,0.2998 2.1752,1.5683 3.7895,2.8188 1.6144,1.2504 3.4399,2.6571 4.0566,3.126 1.8302,1.3913 7.6176,6.4077 9.962,8.6346 1.1986,1.1386 2.4349,2.2909 2.7472,2.5607 0.9207,0.7952 9.8749,9.9437 11.9472,12.2064 3.2265,3.523 6.8834,8.0165 12.5068,15.3683 4.6009,6.0149 5.4863,7.2209 8.1198,11.0588 0.6078,0.8857 1.4643,2.0367 1.9035,2.5577 1.8373,2.1799 1.7315,3.9414 -0.2526,4.2075 -0.7601,0.1024 -0.7601,0.1024 -5.9354,-4.9924 -7.7501,-7.6289 -16.7228,-15.5916 -23.3473,-20.7192 -0.6058,-0.4689 -1.6709,-1.3213 -2.3668,-1.8946 -1.1741,-0.9668 -2.9131,-2.2747 -7.9753,-5.9975 -3.3158,-2.4387 -15.7898,-10.6751 -16.1672,-10.6751 -0.046,0 -0.9668,-0.5405 -2.0468,-1.2011 -1.0801,-0.6606 -3.0295,-1.7804 -4.332,-2.4886 -1.3026,-0.7081 -3.3488,-1.8207 -4.5472,-2.4723 -9.458,-5.1431 -18.9529,-9.5468 -26.1458,-12.1266 -11.9189,-4.2748 -14.3961,-5.0584 -21.4093,-6.7727 -8.4966,-2.0771 -8.9929,-2.1657 -9.9263,-1.7716 -0.8527,0.3599 -0.8888,1.4351 -0.1228,3.6579 0.3803,1.1037 0.5808,1.9703 1.4384,6.218 0.7976,3.9505 1.8022,9.4376 2.1677,11.8414 0.087,0.5732 0.3282,2.0226 0.5356,3.2209 0.573,3.3125 1.3897,9.8038 1.74,13.8308 0.1132,1.3025 0.415,4.5424 0.6706,7.1996 1.2443,12.9373 1.4786,18.1876 1.3605,30.5035 -0.106,11.0649 -0.2174,12.4773 -1.9191,24.346 -1.0104,7.0472 -2.8029,14.646 -5.1398,21.7882 -2.6396,8.0677 -7.4463,15.7878 -11.7695,18.9032 -0.4008,0.2889 -1.3683,0.9881 -2.1498,1.554 -2.3051,1.669 -5.9083,3.3112 -8.7153,3.9722 -1.7095,0.4024 -2.0017,0.3753 -2.4278,-0.2255 z"
|
||||
id="path21283" /><path
|
||||
style="display:inline;fill:#000000;fill-opacity:1;stroke-width:0.71608"
|
||||
d="m -1344.6204,-830.62232 c -6.8773,-2.01541 -12.9376,-5.17715 -21.9342,-11.44321 -11.9734,-8.33945 -21.8594,-22.80374 -21.9023,-32.04531 -0.025,-5.21916 1.4471,-8.79863 5.9642,-14.50954 0.6662,-0.84223 1.8506,-2.36869 2.6322,-3.39215 0.7815,-1.02347 1.6434,-2.12479 1.9151,-2.4474 0.2719,-0.32261 1.168,-1.48177 1.9914,-2.57591 0.8234,-1.09416 3.8768,-4.97341 6.785,-8.62057 2.9084,-3.64716 5.5592,-6.97223 5.8908,-7.38905 1.3392,-1.68346 1.3506,-1.83796 0.207,-2.81492 -5.4037,-4.61652 -13.9573,-19.03987 -17.2069,-29.01484 -0.2037,-0.62524 -0.6723,-1.94674 -1.0413,-2.93668 -0.7402,-1.98575 -1.8645,-5.71704 -2.255,-7.48379 -1.8287,-8.27417 -2.1744,-22.61767 -0.7283,-30.21933 0.1487,-0.78153 0.3973,-2.33949 0.5523,-3.46211 0.4319,-3.12594 1.2016,-5.62552 4.5929,-14.91587 0.7521,-2.06 4.7855,-9.6636 5.9297,-11.1782 2.1853,-2.8926 2.2231,-3.2679 0.5445,-5.3997 -7.4283,-9.4333 -13.6635,-24.3793 -15.2216,-36.4873 -1.3218,-10.271 -1.1235,-23.1421 0.4668,-30.2984 0.9613,-4.3261 1.3428,-5.5729 3.7393,-12.2204 1.3168,-3.6525 4.53,-10.2639 7.0297,-14.4641 0.6414,-1.0779 1.1662,-2.0025 1.1662,-2.0549 0,-0.1073 1.4953,-2.2836 3.0347,-4.4166 6.9984,-9.6974 16.482,-18.5941 25.7084,-24.1172 2.879,-1.7236 4.055,-2.4075 4.1393,-2.4075 0.051,0 0.4349,-0.2167 0.8544,-0.4815 0.4195,-0.2649 1.4623,-0.7866 2.3172,-1.1594 0.8549,-0.3727 1.8954,-0.829 2.3122,-1.014 1.1008,-0.4884 5.5833,-2.148 7.6664,-2.8386 2.3895,-0.7922 6.1267,-1.6365 8.3432,-1.885 0.99,-0.111 2.6526,-0.298 3.6946,-0.4155 3.3891,-0.3824 11.9886,0.011 15.1571,0.6944 0.7293,0.1571 2.4345,0.4601 3.7892,0.6733 4.9466,0.7783 13.676,3.9822 18.7546,6.8835 0.939,0.5364 2.1173,1.1859 2.6184,1.4432 0.5011,0.2573 1.4816,0.9244 2.1789,1.4823 0.6972,0.558 1.6066,1.2319 2.0208,1.4976 8.9372,5.7333 22.8368,21.4683 26.7195,30.2479 0.2352,0.5317 0.9909,2.1002 1.6793,3.4854 2.4129,4.8545 5.4995,14.1279 6.6616,20.0131 2.785,14.1049 1.5763,35.4 -2.5863,45.5637 -0.1034,0.2528 -0.4773,1.3328 -0.8306,2.4002 -1.9693,5.9485 -5.6108,13.0478 -8.9706,17.4881 -3.5901,4.7449 -3.5745,4.7071 -2.5231,6.1377 1.5087,2.0529 5.1523,9.0393 6.1466,11.7859 0.2641,0.7295 0.7089,1.9657 0.9882,2.7472 0.2796,0.7816 0.7036,1.8925 0.9425,2.46876 0.2389,0.57626 0.7887,2.32405 1.2217,3.88399 0.4332,1.55993 0.9061,3.21991 1.0509,3.68884 0.3691,1.19458 0.6598,3.35446 1.2495,9.28367 1.1225,11.28504 0.3564,21.6401 -2.3901,32.30343 -0.7667,2.97684 -2.6423,8.57765 -3.5047,10.46575 -0.2017,0.44174 -0.3669,0.852 -0.3669,0.91169 0,0.36241 -4.4274,9.35514 -5.0324,10.22133 -0.291,0.41682 -0.9529,1.39729 -1.4708,2.17882 -2.6368,3.97864 -3.8477,5.45705 -7.9729,9.73351 -1.8786,1.9476 -1.9011,1.49234 0.2162,4.40819 0.6702,0.92315 1.5315,2.14737 1.9138,2.72049 1.2572,1.88443 4.372,6.30253 6.2112,8.81003 0.9937,1.35467 2.4763,3.44349 3.295,4.64185 0.8187,1.19834 2.5155,3.58558 3.7707,5.30494 3.5394,4.84808 5.8002,8.27771 6.6408,10.07382 4.1125,8.78693 -2.8311,23.35628 -16.3975,34.4058 -0.9895,0.80583 -2.1658,1.76354 -2.6142,2.12826 -6.0837,4.94792 -12.8528,8.95466 -19.8212,11.73254 -8.2134,3.27414 -11.0944,3.55091 -11.4915,1.10397 -0.2547,-1.56961 0.017,-2.05948 4.8305,-8.66833 1.4037,-1.92777 3.0215,-4.18712 3.5952,-5.02076 0.5737,-0.83363 1.5713,-2.28303 2.2168,-3.22087 1.0612,-1.54145 1.7115,-2.60302 4.6429,-7.57851 2.9165,-4.95017 5.4898,-11.05328 5.4898,-13.02015 0,-1.24229 -1.2524,-3.30859 -4.7051,-7.76369 -1.8358,-2.36875 -3.3099,-4.36196 -8.6593,-11.70906 -0.645,-0.88573 -2.4844,-3.55999 -4.0877,-5.94276 -3.5111,-5.21787 -2.6716,-4.99024 -9.4518,-2.56243 -1.1251,0.40291 -5.8005,1.2988 -8.2415,1.57925 -1.4589,0.16762 -3.2231,0.38776 -3.9205,0.48922 -2.7564,0.40097 -8.2369,0.16605 -13.6049,-0.58319 -2.2703,-0.31689 -6.6673,-1.46279 -9.9467,-2.59221 -4.2126,-1.45078 -3.9885,-1.45039 -5.0173,-0.009 -0.4669,0.65438 -1.49,2.01033 -2.2735,3.01322 -1.4235,1.82216 -3.3121,4.32005 -4.5369,6.00074 -0.3573,0.49011 -1.9772,2.55386 -3.5999,4.58611 -1.6227,2.03227 -3.1891,4.0145 -3.481,4.40497 -0.2918,0.39047 -0.9608,1.2002 -1.4865,1.7994 -0.8925,1.01738 -3.5659,4.47412 -4.7634,6.1593 -2.8314,3.98464 -2.114,7.76744 3.4537,18.21334 1.3598,2.55114 3.963,6.50495 8.4339,12.80951 5.5864,7.87782 6.0591,8.78903 5.3102,10.2372 -0.6582,1.27276 -1.589,1.36792 -4.6386,0.47424 z"
|
||||
id="path21269" /><path
|
||||
style="display:inline;fill:#000000;fill-opacity:1;stroke-width:0.71608"
|
||||
d="m -1388.7652,-1007.5996 c -5.8227,-2.6259 -9.1991,-5.437 -11.9327,-9.9347 -0.3484,-0.5731 -1.2023,-1.9799 -1.8977,-3.126 -1.3115,-2.162 -4.3598,-8.3758 -5.2191,-10.6392 -1.282,-3.3764 -3.4016,-10.1595 -3.8827,-12.4249 -0.2051,-0.9655 -0.4216,-1.8835 -0.4812,-2.0398 -0.1639,-0.4303 -0.9986,-4.5519 -1.4196,-7.0101 -0.8001,-4.6732 -1.1514,-7.7036 -1.8892,-16.2938 -0.7911,-9.212 -0.2779,-27.3932 1.1474,-40.6399 0.112,-1.042 0.3283,-3.1719 0.4807,-4.733 0.1523,-1.5612 0.4449,-3.9485 0.6504,-5.305 0.2054,-1.3565 0.4598,-3.0633 0.5655,-3.7927 0.4804,-3.3151 1.5541,-9.6808 1.9816,-11.7468 0.7494,-3.623 1.428,-6.7493 1.6226,-7.4756 0.099,-0.3691 0.3904,-1.5664 0.6479,-2.6606 0.2574,-1.0941 0.7252,-3.055 1.0394,-4.3577 1.2841,-5.3225 1.5878,-5.1937 -7.3698,-3.1246 -10.1381,2.3418 -14.1671,3.4752 -20.5567,5.7826 -1.7715,0.6397 -4.1459,1.4961 -5.2765,1.903 -1.1305,0.4069 -2.7504,1.0467 -3.5997,1.4217 -0.8494,0.375 -1.8001,0.7918 -2.1127,0.9265 -1.5546,0.6693 -8.3608,3.7741 -8.5258,3.8894 -0.1042,0.073 -1.0421,0.5842 -2.0841,1.1366 -1.0421,0.5523 -2.0652,1.1097 -2.2735,1.2387 -0.2085,0.1289 -1.4448,0.7837 -2.7473,1.455 -1.3025,0.6713 -2.7093,1.4174 -3.1262,1.6581 -0.4167,0.2406 -1.7383,0.9519 -2.9366,1.5808 -1.1984,0.6289 -2.733,1.4821 -3.4103,1.8961 -2.6246,1.6041 -3.9572,2.3753 -5.8984,3.4146 -1.1078,0.593 -3.0877,1.7803 -4.3999,2.6385 -1.312,0.8582 -2.7928,1.8089 -3.2906,2.1126 -11.4464,6.9844 -29.4494,21.4049 -40.9311,32.7859 -5.9123,5.8603 -6.2292,6.0493 -7.4275,4.4286 -0.7969,-1.0778 -0.6741,-1.3984 2.0205,-5.2738 10.6149,-15.2674 32.1009,-37.4481 48.1056,-49.6614 1.1449,-0.8736 2.3333,-1.7822 2.6411,-2.0191 3.1702,-2.4402 4.511,-3.4358 5.4173,-4.0226 0.5877,-0.3804 1.3976,-0.948 1.8,-1.2612 0.4022,-0.3134 1.6693,-1.2092 2.8156,-1.9909 1.1462,-0.7817 2.894,-1.984 3.8839,-2.672 0.99,-0.688 2.4394,-1.6551 3.2209,-2.1492 0.7815,-0.4942 2.3172,-1.47 3.4125,-2.1685 1.0952,-0.6985 2.502,-1.5457 3.126,-1.8826 1.9664,-1.0615 3.1618,-1.7264 5.1135,-2.844 4.9429,-2.8307 15.9289,-7.9772 21.883,-10.2514 1.6151,-0.6169 3.1072,-1.2028 3.3156,-1.3019 1.451,-0.6899 6.0037,-2.3879 8.6205,-3.215 4.7239,-1.4933 4.8035,-1.5193 5.2102,-1.7075 1.2028,-0.5562 12.0225,-3.8689 15.0624,-4.6116 7.9785,-1.9496 12.6945,-0.5743 16.2248,4.7315 2.8387,4.266 2.9057,7.8163 0.2694,14.2737 -2.741,6.7145 -6.0927,16.1664 -6.8525,19.3252 -0.2131,0.8858 -0.5836,2.2499 -0.8235,3.0314 -0.2399,0.7815 -0.584,1.9752 -0.7646,2.6524 -0.1805,0.6774 -0.4,1.4447 -0.4875,1.7052 -0.1494,0.4448 -1.3994,5.5403 -1.9752,8.0522 -0.5596,2.4409 -1.2398,5.7822 -1.6007,7.8627 -0.2079,1.1984 -0.5029,2.8183 -0.6556,3.5998 -0.1527,0.7815 -0.4557,2.572 -0.6734,3.9787 -0.2178,1.4068 -0.4754,3.0694 -0.5725,3.6946 -0.097,0.6252 -0.223,1.4352 -0.2795,1.7999 -2.4243,15.6279 -2.8728,36.4364 -1.0455,48.5025 1.9607,12.9468 8.2616,27.6355 16.2343,37.8451 2.9208,3.7401 2.9562,3.9441 1.1076,6.3659 -0.635,0.8319 -1.6846,2.499 -3.4769,5.523 -1.7723,2.9903 -1.6432,2.9649 -5.7239,1.1246 z"
|
||||
id="path21281" /><path
|
||||
style="display:inline;fill:#000000;fill-opacity:1;stroke-width:0.71608"
|
||||
d="m -1571.8105,-906.44907 c -1.0547,-0.65454 -1.3054,-1.68463 -0.94,-3.86175 0.2379,-1.41654 0.7097,-5.88837 1.1581,-10.97628 0.8133,-9.22935 1.067,-11.27594 2.4537,-19.79887 0.1013,-0.62523 0.3166,-1.94673 0.4777,-2.93667 0.4792,-2.9466 0.8115,-4.75966 1.236,-6.74439 0.2208,-1.0319 0.5684,-2.68613 0.7723,-3.67607 0.6246,-3.03085 2.6171,-10.75914 3.4192,-13.26241 1.6799,-5.24257 3.4547,-10.55742 3.7646,-11.27304 0.3425,-0.79122 2.0249,-5.06696 3.4713,-8.82247 0.4641,-1.2052 1.1407,-2.78248 1.5034,-3.50506 0.3627,-0.72259 1.1739,-2.55321 1.8027,-4.06804 0.6286,-1.51484 1.7153,-3.9447 2.4146,-5.39968 0.6993,-1.4551 1.7363,-3.6685 2.3045,-4.919 0.5682,-1.2504 1.4429,-3.0409 1.9438,-3.9787 0.5009,-0.9379 1.5935,-3.0267 2.4277,-4.6419 3.0705,-5.9442 6.3383,-11.2849 11.7084,-19.1358 1.8857,-2.7567 3.0674,-4.3946 4.7246,-6.5481 0.8336,-1.0834 1.8141,-2.3719 2.1788,-2.8635 4.1072,-5.5347 16.4116,-19.086 24.9999,-27.5336 12.9724,-12.7598 23.566,-21.8905 31.9564,-27.5434 0.6378,-0.4298 2.0871,-1.4313 3.2209,-2.2257 10.1055,-7.0808 16.533,-8.3386 21.8208,-4.2698 3.6021,2.7718 4.4487,4.9992 4.3681,11.4929 -0.1413,11.3874 0.1722,15.6696 1.7267,23.588 1.7288,8.8065 2.063,10.3445 2.4948,11.4807 0.1949,0.5133 0.3546,1.1347 0.3546,1.381 0,0.2464 0.1342,0.8209 0.2984,1.2769 0.1641,0.456 0.4973,1.4684 0.7404,2.2499 1.2782,4.1093 2.5916,7.5374 4.5583,11.8984 1.4749,3.2706 2.0342,4.4268 3.5472,7.3322 0.4882,0.9378 1.5167,3.0266 2.2853,4.6419 1.5516,3.2605 4.8531,9.2879 6.4109,11.7043 0.5561,0.8625 1.4799,2.3487 2.053,3.3027 3.7694,6.2741 13.5463,12.8354 22.5461,15.13059 3.196,0.81504 4.3536,1.55881 3.9753,2.55393 -0.1003,0.26379 -0.487,1.56324 -0.8591,2.88767 -0.3722,1.32442 -0.9655,3.26062 -1.3184,4.30266 -0.58,1.71309 -1.0603,3.36793 -1.6757,5.77369 -0.5482,2.14332 -6.7881,1.27333 -15.422,-2.1502 -8.0086,-3.17554 -17.6559,-12.92694 -27.2498,-27.54384 -4.4414,-6.7667 -7.3082,-11.5271 -9.2697,-15.392 -1.5617,-3.0775 -4.6293,-9.6326 -5.4654,-11.6792 -0.4625,-1.132 -1.1114,-2.6974 -1.4421,-3.4791 -2.766,-6.5376 -6.2829,-18.1636 -7.3074,-24.1564 -0.3002,-1.7559 -0.5918,-3.1052 -1.0543,-4.8788 -0.2984,-1.1444 -0.3933,-1.1092 -5.381,1.9983 -0.8336,0.5192 -1.8263,1.2222 -2.2059,1.5621 -0.3797,0.3397 -1.1469,0.914 -1.7051,1.2762 -0.5582,0.362 -1.3134,0.9325 -1.678,1.2676 -0.3648,0.3351 -1.6383,1.4328 -2.8301,2.4392 -2.658,2.2445 -5.3855,4.6523 -7.0221,6.1986 -0.6772,0.6401 -2.7217,2.5194 -4.5431,4.1761 -21.9692,19.9833 -41.2206,42.1321 -50.6218,58.24075 -0.5777,0.98994 -1.7789,3.05012 -2.6692,4.57818 -0.8904,1.52806 -2.6622,4.89576 -3.9375,7.48379 -1.2752,2.58803 -3.0553,6.19751 -3.9556,8.02109 -0.9004,1.82358 -2.0531,4.25344 -2.5616,5.3997 -0.5084,1.14624 -1.5101,3.30344 -2.2259,4.79376 -0.7159,1.49033 -1.6053,3.45127 -1.9763,4.35765 -0.615,1.50217 -0.9401,2.24076 -1.9767,4.48991 -0.5089,1.10425 -1.6261,3.89962 -2.3852,5.96809 -0.3633,0.98994 -0.945,2.52459 -1.2927,3.41033 -0.3476,0.88574 -0.9309,2.37776 -1.2961,3.3156 -0.8338,2.14107 -4.9012,14.44931 -5.4472,16.48327 -0.9205,3.42976 -3.2479,13.27335 -3.494,14.77811 -0.9547,5.83668 -1.8912,7.28064 -3.9095,6.028 z"
|
||||
id="path21279" /><path
|
||||
style="display:inline;fill:#000000;fill-opacity:1;stroke-width:0.71608"
|
||||
d="m -1051.2372,-905.15276 c -1.2128,-0.7415 -1.3505,-1.20128 -3.0447,-10.16625 -0.256,-1.35467 -0.5894,-2.97457 -0.741,-3.5998 -0.1515,-0.62523 -0.5832,-2.45829 -0.9591,-4.07345 -0.6624,-2.84563 -1.7035,-6.50494 -3.0185,-10.60993 -0.3505,-1.09414 -1.035,-3.26823 -1.5211,-4.8313 -2.3498,-7.55702 -3.8122,-11.08546 -9.1874,-22.16716 -2.5982,-5.35645 -3.5948,-7.47553 -4.5895,-9.75733 -0.5224,-1.19836 -1.4012,-3.07404 -1.953,-4.16819 -0.5518,-1.09415 -1.5178,-3.05509 -2.1465,-4.35765 -0.6289,-1.30256 -1.8404,-3.60453 -2.6921,-5.11549 -0.8519,-1.51097 -2.3639,-4.19661 -3.3602,-5.96809 -5.4984,-9.77688 -8.1194,-14.0045 -11.6615,-18.8096 -3.7994,-5.154 -8.4351,-10.9504 -10.7163,-13.3991 -4.9116,-5.2723 -6.4436,-6.9063 -8.2561,-8.8064 -3.3825,-3.5455 -11.8124,-11.9301 -16.2939,-16.2061 -2.2914,-2.1864 -5.0623,-4.8313 -6.1575,-5.8774 -3.6359,-3.4732 -11.5809,-10.0951 -16.0115,-13.3453 -1.0421,-0.7644 -2.2818,-1.7105 -2.755,-2.1025 -0.8091,-0.6703 -4.9304,-3.3655 -6.4716,-4.2322 -1.3351,-0.7508 -2.1,0.4074 -2.8046,4.2462 -0.4155,2.2637 -1.4048,6.6847 -1.7172,7.6733 -0.099,0.3126 -0.4361,1.6768 -0.7495,3.0314 -0.3136,1.3547 -0.7805,3.1024 -1.0379,3.8839 -0.2573,0.7816 -0.8463,2.572 -1.3089,3.9788 -2.5234,7.6721 -5.3912,14.0913 -11.3421,25.388 -0.5214,0.9899 -1.4266,2.5913 -2.0114,3.5585 -0.5847,0.9673 -1.2283,2.033 -1.4302,2.3683 -0.6609,1.098 -2.8252,4.3842 -3.3339,5.0621 -0.2737,0.3647 -1.1661,1.6009 -1.9832,2.7472 -1.3797,1.9352 -3.5465,4.6994 -7.4859,9.5499 -5.7859,7.12376 -13.6661,13.4112 -20.0807,16.02195 -0.6773,0.27567 -1.8284,0.78419 -2.5578,1.13005 -0.7295,0.34584 -2.4345,0.9869 -3.7893,1.42456 -1.3546,0.43764 -2.6761,0.88618 -2.9366,0.99673 -2.5596,1.08615 -4.7828,0.35241 -5.1012,-1.68359 -0.1276,-0.81576 -0.3585,-1.95212 -0.5131,-2.52524 -0.1547,-0.57313 -0.4434,-1.63886 -0.6415,-2.36829 -2.6894,-9.89996 -2.675,-9.06013 -0.1708,-10.02123 3.9174,-1.50353 5.4635,-2.18474 8.4457,-3.72104 1.7878,-0.921 3.6299,-1.9572 4.0934,-2.3026 0.4636,-0.3453 1.6305,-1.1766 2.593,-1.8474 6.1024,-4.2521 11.0526,-10.4225 16.2206,-20.2192 0.5962,-1.1301 1.5781,-2.9499 2.182,-4.044 0.604,-1.0942 1.5389,-2.9698 2.0775,-4.1682 0.5386,-1.1984 1.5227,-3.2973 2.1868,-4.6643 0.6639,-1.3671 1.4526,-3.1574 1.7524,-3.9788 0.2999,-0.8212 0.9905,-2.6442 1.5346,-4.0509 1.1175,-2.8893 2.4311,-7.0308 3.0345,-9.5679 0.2232,-0.9379 0.6529,-2.6003 0.955,-3.6946 0.6533,-2.3661 1.7288,-7.6513 2.2556,-11.0834 0.7297,-4.755 1.3694,-10.6082 2.0191,-18.4727 0.4939,-5.9779 0.6948,-7.1517 1.5301,-8.939 2.5612,-5.4798 7.7868,-7.9638 13.906,-6.6103 1.5611,0.3453 8.495,3.9855 9.7521,5.1198 0.2085,0.188 1.7005,1.2135 3.3157,2.2789 1.6152,1.0655 3.1638,2.096 3.4413,2.2903 0.2776,0.1941 1.4712,1.0065 2.6525,1.8053 5.8384,3.9476 14.7552,11.1304 20.3363,16.3816 0.6252,0.5883 1.5204,1.4017 1.9893,1.8074 4.5567,3.9431 17.3336,17.3297 23.1693,24.275 8.5254,10.1465 13.9509,17.4905 18.5143,25.0611 0.6594,1.0941 1.5719,2.5712 2.0276,3.2825 0.731,1.1411 1.8009,3.044 2.6806,4.7677 0.1591,0.3116 0.4851,0.8552 0.7246,1.2082 0.4257,0.6273 5.0629,9.9065 7.3031,14.6139 0.6198,1.3025 1.7128,3.57013 2.4288,5.03911 2.0609,4.22846 5.1798,11.371 6.1555,14.0966 0.786,2.19598 0.9256,2.56314 2.053,5.39969 0.8712,2.19209 2.8402,7.95218 4.6628,13.64133 0.5074,1.58381 1.298,4.57484 1.8028,6.82066 0.2342,1.04205 0.7233,3.04562 1.0868,4.45238 1.5578,6.02916 2.2082,9.40886 3.4451,17.90424 0.6436,4.42041 1.2381,10.03592 1.5244,14.39919 0.3392,5.17256 0.7692,9.79107 1.1527,12.38379 0.2983,2.0167 0.1909,2.42655 -0.8699,3.31907 -0.6998,0.58886 -0.8569,0.60328 -1.6027,0.14728 z"
|
||||
id="path21277" /><path
|
||||
style="display:inline;fill:#000000;fill-opacity:1;stroke-width:0.71608"
|
||||
d="m -1524.6154,-780.78748 c -0.8444,-0.46733 -4.9487,-8.46179 -7.1559,-13.9384 -0.735,-1.82358 -1.5662,-3.82715 -1.8471,-4.45239 -0.281,-0.62522 -0.7864,-1.86147 -1.1229,-2.7472 -0.3367,-0.88574 -1.0594,-2.76143 -1.6061,-4.16819 -2.6659,-6.86063 -6.3122,-18.68126 -7.393,-23.96706 -0.085,-0.41681 -0.4684,-2.20723 -0.8515,-3.97872 -0.3832,-1.77147 -0.8549,-4.07345 -1.0484,-5.11549 -0.1934,-1.04205 -0.5233,-2.74722 -0.7329,-3.78926 -0.4116,-2.04514 -1.1927,-7.49489 -1.5345,-10.70465 -0.1166,-1.09415 -0.2907,-2.67144 -0.3872,-3.50506 -1.5314,-13.23132 -2.0562,-45.40144 -0.855,-52.40895 0.7139,-4.16531 3.4229,-10.44385 7.3068,-16.93447 0.9977,-1.66728 2.2904,-3.84137 2.8726,-4.83132 4.2349,-7.19922 14.5483,-21.51103 19.64,-27.25427 0.6151,-0.69362 1.8315,-2.12942 2.7031,-3.19066 1.4483,-1.76311 3.2212,-3.82542 6.307,-7.33691 0.6333,-0.72063 1.4551,-1.65847 1.8263,-2.08408 8.5053,-9.75158 26.5817,-28.05284 32.7912,-33.19894 1.5106,-1.2519 4.2382,-3.2887 4.4042,-3.2887 0.043,0 0.6625,-0.3553 1.3766,-0.7896 6.5868,-4.0062 12.6237,-1.4734 16.9602,7.1156 6.1139,12.10981 22.6254,24.42593 38.0408,28.37518 4.6331,1.18692 12.7273,1.37594 18.1475,0.42379 3.5814,-0.62914 3.6764,-0.50378 3.8755,5.11353 0.082,2.30482 0.237,4.6595 0.3451,5.23262 0.985,5.22329 0.4784,5.83008 -6.0051,7.1936 -9.8694,2.0756 -18.3529,1.41914 -29.8049,-2.30637 -4.7285,-1.53823 -13.0235,-5.40727 -16.3323,-7.61777 -5.8468,-3.90622 -8.6799,-6.202 -14.3829,-11.65513 -7.092,-6.78131 -6.8261,-6.89037 -22.91,9.39259 -4.1669,4.21838 -8.2028,8.45933 -11.063,11.62525 -4.2273,4.67879 -14.137,16.6436 -16.8861,20.38803 -0.5267,0.71747 -2.441,3.26545 -4.254,5.66215 -2.7303,3.60937 -7.7461,10.91483 -11.9675,17.43059 -4.9454,7.63321 -7.4094,14.57972 -7.9173,22.32032 -0.5833,8.88979 -0.4109,35.28451 0.2749,42.09705 0.1469,1.45886 0.3577,4.05925 0.4685,5.77862 0.1899,2.94863 1.1437,12.08686 1.5423,14.77811 0.1004,0.67733 0.3497,2.42513 0.5541,3.88399 0.5027,3.58842 1.0897,7.22117 1.6993,10.51519 0.2025,1.09415 0.5476,2.96983 0.7669,4.16818 0.2195,1.19836 0.5981,3.03141 0.8416,4.07345 0.2435,1.04205 0.7998,3.42928 1.2361,5.30496 0.4363,1.87569 0.8719,3.66611 0.968,3.97873 0.096,0.31261 0.4355,1.50623 0.7544,2.65247 0.7699,2.76789 2.4393,7.86098 2.7325,8.33638 1.1206,1.81751 -0.6567,4.37589 -2.3779,3.42321 z"
|
||||
id="path21267" /><path
|
||||
style="display:inline;fill:#000000;fill-opacity:1;stroke-width:0.71608"
|
||||
d="m -1097.9379,-779.80916 c -1.5217,-0.76164 -1.5219,-0.74568 0.099,-6.41702 2.0228,-7.07604 3.1431,-12.12399 4.2621,-19.20436 3.7688,-23.8461 4.9839,-39.66869 5.2306,-68.11191 0.1888,-21.77417 0.081,-22.38837 -6.0881,-34.54459 -4.493,-8.85397 -9.3296,-16.42058 -17.218,-26.93612 -2.8761,-3.8341 -8.9588,-11.40904 -11.4715,-14.28588 -1.3108,-1.50077 -2.98,-3.42996 -3.7094,-4.28712 -6.9198,-8.13138 -22.334,-24.34391 -24.94,-26.2317 -0.7498,-0.54319 -0.8815,-0.57166 -2.643,-0.57166 -2.616,0 -2.0764,-0.32663 -8.2068,4.96805 -1.0524,0.90885 -2.457,2.05983 -3.1216,2.55775 -0.6645,0.49791 -1.9325,1.48954 -2.8178,2.20361 -0.8852,0.71408 -2.6009,1.94393 -3.8125,2.73302 -1.2117,0.78909 -2.923,1.90263 -3.8031,2.47451 -1.3652,0.88717 -4.8952,2.76907 -9.3888,5.0053 -6.7795,3.37386 -12.2222,5.1714 -20.5567,6.78898 -2.9982,0.58192 -11.483,0.46369 -14.5886,-0.20329 -4.9485,-1.06274 -6.1602,-1.36976 -8.088,-2.04933 -4.2288,-1.49071 -3.9708,-0.90056 -3.7243,-8.52251 0.2764,-8.54566 0.028,-8.21009 5.4652,-7.37133 8.5133,1.31317 21.891,-0.86397 32.3035,-5.25721 7.8248,-3.30145 22.1897,-15.31752 26.6041,-22.25404 8.0597,-12.66469 13.6596,-13.81619 23.7486,-4.88339 0.6085,0.5388 1.5708,1.3633 2.1385,1.8322 0.5676,0.4689 2.3633,2.1741 3.9903,3.78924 1.6271,1.61517 3.8011,3.74663 4.8313,4.73658 1.8519,1.77949 7.212,7.363 8.8135,9.18089 0.8257,0.9371 1.5732,1.76305 4.8185,5.3235 3.3087,3.63027 5.4951,6.09566 6.9979,7.89087 3.4173,4.08236 6.8911,8.40952 9.475,11.80279 1.0316,1.35466 2.3484,3.07024 2.9262,3.81241 0.5779,0.74217 1.5622,2.05768 2.1874,2.92334 0.6252,0.86567 1.5545,2.13412 2.0651,2.81879 0.9338,1.25213 1.2132,1.6624 4.4851,6.58414 1.7856,2.6859 3.5028,5.38793 5.5773,8.77568 0.6062,0.98995 1.4196,2.26883 1.8076,2.84195 7.6515,11.30182 10.6721,18.58023 11.7548,28.3247 0.8511,7.65988 0.6759,22.00663 -0.4835,39.59775 -0.3185,4.83145 -0.7768,10.37169 -1.0503,12.69401 -0.8074,6.85862 -1.2343,9.74693 -2.4638,16.67274 -2.2601,12.73024 -4.7741,21.89077 -9.0472,32.96654 -2.2607,5.85946 -2.5652,6.57714 -5.063,11.93616 -0.1457,0.31262 -0.5649,1.22341 -0.9315,2.024 -0.7166,1.56464 -2.5404,4.84492 -3.4434,6.19326 -0.3051,0.45553 -0.6802,1.02595 -0.8336,1.26762 -0.2173,0.34249 -0.9448,0.8518 -1.1984,0.83889 -0.022,-10e-4 -0.4212,-0.19359 -0.8891,-0.42781 z"
|
||||
id="path21265" /><path
|
||||
style="display:inline;fill:#000000;fill-opacity:1;stroke-width:0.71608"
|
||||
d="m -1372.6609,-723.60939 c -1.855,-1.08537 -4.8912,-2.66017 -6.0674,-3.14684 -0.3672,-0.15195 -1.305,-0.64271 -2.0841,-1.09057 -0.779,-0.44786 -1.7574,-1.00342 -2.1743,-1.23458 -14.7165,-8.16137 -26.5442,-17.60623 -38.668,-30.87807 -1.0471,-1.14624 -2.5693,-2.80878 -3.3827,-3.69452 -6.0598,-6.59929 -15.1394,-19.26533 -19.6251,-27.37738 -0.3458,-0.62524 -0.9971,-1.75268 -1.4472,-2.50545 -1.1856,-1.98224 -5.1055,-9.33118 -6.041,-11.32535 -4.9318,-10.51271 -5.3147,-11.36642 -6.799,-15.15703 -0.6936,-1.77148 -1.3829,-3.51928 -1.5316,-3.88399 -4.1146,-10.08764 -8.8787,-28.0974 -11.8529,-44.80798 -0.1113,-0.62522 -0.2824,-1.52044 -0.3802,-1.98935 -0.2293,-1.09929 -1.5686,-8.81206 -1.9575,-11.27305 -0.9185,-5.81186 -1.4482,-9.36218 -1.7234,-11.55054 -0.1697,-1.35097 -0.3385,-2.50452 -0.3748,-2.56345 -0.6387,-1.03341 -1.0457,-17.89571 -0.4939,-20.46299 1.4224,-6.61767 6.253,-10.04152 14.1674,-10.04152 5.877,0 13.7905,-0.52996 18.5345,-1.24122 8.7162,-1.30683 14.3143,-2.50047 20.854,-4.44658 2.0938,-0.62307 3.8675,-1.13287 3.9415,-1.13287 0.3724,0 6.2057,-2.27581 8.3605,-3.26173 1.3547,-0.61983 3.1451,-1.4396 3.9787,-1.82169 3.0726,-1.40835 9.8708,-5.08706 13.7795,-7.45654 3.1123,-1.88663 3.5776,-1.96379 4.2304,-0.70151 0.3327,0.64336 1.4487,3.19759 1.9891,4.55215 0.1927,0.48321 0.6158,1.42104 0.9401,2.08409 0.5875,1.20113 0.9563,2.03753 2.0651,4.68286 1.2859,3.06795 1.1036,3.3249 -6.1075,8.61006 -9.0907,6.66273 -18.42,11.26102 -29.117,14.35129 -0.6774,0.19567 -1.9562,0.57649 -2.8421,0.84625 -6.3059,1.92056 -12.5797,3.58867 -15.3463,4.08041 -1.0943,0.19447 -3.4814,0.66044 -5.3051,1.03548 -2.6726,0.54967 -3.9401,0.70737 -6.5365,0.81327 -3.6681,0.14963 -3.9083,1.71404 -2.2743,14.81475 0.2952,2.36737 0.4021,3.21795 0.9405,7.48378 0.4065,3.22214 0.9662,7.17231 1.4228,10.04154 0.2156,1.35466 0.4788,3.14509 0.5851,3.97872 0.1062,0.83364 0.2305,1.64359 0.2763,1.79991 0.083,0.28256 0.2587,1.38253 0.7418,4.64184 0.1389,0.93783 0.4251,2.55775 0.6358,3.59979 0.2106,1.04204 0.4899,2.53406 0.6203,3.3156 0.1306,0.78154 0.5298,2.82773 0.8872,4.54711 0.3574,1.71937 0.7294,3.59506 0.8267,4.16818 0.097,0.57314 0.3364,1.72411 0.5312,2.55775 0.1948,0.83364 0.5018,2.19777 0.6823,3.03141 0.4337,2.00305 1.7379,6.74135 2.2162,8.05217 0.3996,1.09491 1.1859,3.73481 1.4952,5.02076 0.1723,0.71552 0.5158,1.84549 1.4979,4.92605 0.2326,0.72942 0.49,1.58202 0.572,1.89462 0.082,0.31262 0.6755,2.06041 1.3187,3.88399 0.6432,1.82358 1.3351,3.84353 1.5376,4.48878 0.2024,0.64525 0.7493,2.09463 1.2155,3.22087 0.466,1.12623 0.8477,2.10569 0.8483,2.17657 6e-4,0.0709 0.2612,0.71032 0.5791,1.42097 0.5705,1.27492 0.7175,1.61726 1.897,4.41823 0.3291,0.78153 1.1807,2.57196 1.8924,3.97872 0.7116,1.40676 1.5829,3.19719 1.936,3.97872 0.3532,0.78154 1.0113,2.06042 1.4627,2.84195 0.4513,0.78153 1.4695,2.57196 2.2628,3.97872 6.593,11.69136 15.602,23.93781 25.7851,35.05063 9.5484,10.42028 15.4447,16.05809 25.8561,24.72247 2.2491,1.8717 2.3682,2.03268 2.3682,3.19815 0,2.09239 -0.9685,2.29585 -3.5997,0.75619 z"
|
||||
id="path21263" /><path
|
||||
style="display:inline;fill:#000000;fill-opacity:1;stroke-width:0.71608"
|
||||
d="m -1254.2051,-722.65362 c -1.6526,-0.72227 -1.2581,-2.7138 0.8463,-4.27161 5.6438,-4.17796 13.9202,-11.64804 22.097,-19.94413 8.5309,-8.65531 18.7748,-20.97388 23.3325,-28.05765 0.4022,-0.62522 1.4323,-2.20251 2.2888,-3.50507 2.1285,-3.23636 5.2013,-8.11401 5.2013,-8.25616 0,-0.064 0.1595,-0.34274 0.3544,-0.61934 0.6114,-0.86732 4.4924,-8.53149 5.6755,-11.20756 0.6218,-1.40676 1.558,-3.46435 2.0803,-4.5724 0.9365,-1.98682 1.31,-2.90177 3.7029,-9.06893 1.4092,-3.63197 1.711,-4.49825 2.772,-7.95744 0.4314,-1.40676 0.8575,-2.7709 0.9467,-3.03141 0.2126,-0.62077 1.1774,-3.88455 1.68,-5.68389 0.4577,-1.6378 1.3455,-5.27987 1.8244,-7.48379 0.1811,-0.83363 0.584,-2.58143 0.8952,-3.88398 1.3142,-5.50072 2.6887,-12.23464 3.6546,-17.90425 0.2486,-1.45886 0.7154,-4.05923 1.0375,-5.77861 0.6987,-3.73001 1.1776,-6.37065 1.8043,-9.94681 0.2556,-1.45886 0.5553,-3.16403 0.6659,-3.78925 0.5375,-3.03905 2.0932,-12.96551 2.3606,-15.06231 1.6926,-13.27309 1.856,-12.4299 -2.4573,-12.68298 -3.3912,-0.19897 -5.997,-0.48133 -7.1034,-0.76973 -0.3648,-0.095 -2.3778,-0.51951 -4.4736,-0.94319 -19.2696,-3.89569 -36.4831,-10.59305 -48.1024,-18.7155 -0.7294,-0.50991 -2.5798,-1.79863 -4.112,-2.86384 -4.8618,-3.37978 -4.8587,-3.32882 -0.7619,-12.52725 3.0548,-6.85891 3.0497,-6.85713 9.1736,-3.16868 2.9739,1.79121 4.4591,2.61223 9.1522,5.05926 4.0054,2.08844 10.8696,4.92111 15.1571,6.25491 1.042,0.32417 2.5587,0.80325 3.3706,1.06461 3.549,1.14264 11.2705,2.95702 14.7569,3.46754 0.6588,0.0965 2.3487,0.34929 3.7554,0.56186 5.7738,0.8724 12.2027,1.30926 20.9356,1.42259 14.5004,0.18817 18.0672,5.91463 16.1219,25.88297 -1.3253,13.60387 -2.1984,19.80697 -3.9998,28.41943 -0.2506,1.19835 -0.7167,3.58558 -1.0356,5.30497 -0.319,1.71937 -0.8816,4.57552 -1.2504,6.34701 -0.7571,3.63751 -0.8708,4.12471 -3.582,15.34649 -0.9586,3.96733 -2.0322,7.74735 -3.6324,12.78873 -1.5436,4.86313 -1.8818,5.83664 -3.2246,9.28369 -0.6698,1.71938 -1.3444,3.48857 -1.4992,3.93155 -0.84,2.40519 -4.0902,9.73005 -5.7376,12.93065 -0.295,0.57312 -1.2563,2.44881 -2.136,4.16818 -0.8798,1.71938 -2.0745,3.93609 -2.6548,4.92604 -0.5803,0.98994 -1.7672,3.03614 -2.6374,4.5471 -3.5102,6.09423 -11.617,17.64916 -15.6188,22.26189 -0.5424,0.62524 -1.4675,1.72409 -2.0558,2.44192 -0.998,1.21775 -2.4563,2.85582 -5.4124,6.07945 -1.8797,2.04973 -7.949,8.23829 -9.0164,9.19341 -0.524,0.46893 -1.629,1.44939 -2.4554,2.17883 -0.8264,0.72943 -2.0431,1.81259 -2.7038,2.40701 -3.2543,2.92779 -8.4457,6.9981 -12.1927,9.55965 -1.1949,0.81686 -3.0218,2.06744 -4.0595,2.77906 -4.5775,3.13877 -8.3453,5.40371 -17.6123,10.58723 -5.5026,3.07787 -5.136,2.92803 -6.116,2.49973 z"
|
||||
id="path21251" /><path
|
||||
style="display:inline;fill:#f0b116;fill-opacity:1;stroke-width:0.71608"
|
||||
d="m -1307.2962,-907.92432 c 5.8064,-0.59544 7.8147,-1.00764 12.5522,-2.57613 4.2944,-1.42185 8.87,-3.62563 14.2567,-6.86678 6.4938,-3.90724 13.6267,-11.43595 18.3424,-19.36028 0.1237,-0.20796 0.3647,-0.59162 0.5354,-0.85259 1.1448,-1.7502 3.829,-7.5377 5.0538,-10.89729 0.8322,-2.28253 1.2356,-3.72692 2.5122,-8.99712 1.8832,-7.77515 2.0463,-19.63405 0.3795,-27.61476 -1.9465,-9.32015 -4.8114,-17.20193 -7.8092,-21.48533 -0.1936,-0.2767 -0.352,-0.5489 -0.352,-0.605 0,-0.3455 -3.5929,-5.3288 -4.9875,-6.9177 -10.2926,-11.7266 -23.8495,-19.4263 -37.6416,-21.379 -5.448,-0.7713 -19.9353,-0.2318 -21.6137,0.805 -0.06,0.037 -0.953,0.2921 -1.9838,0.5664 -2.9979,0.7975 -7.2761,2.2951 -8.6112,3.0141 -0.6774,0.3648 -1.9561,1.0129 -2.842,1.4403 -2.5459,1.2283 -3.0101,1.4882 -5.0207,2.8107 -3.9566,2.6025 -12.4444,10.2311 -14.5716,13.0966 -0.4262,0.5741 -1.3347,1.7677 -2.0188,2.6524 -1.1516,1.4892 -3.398,4.9105 -3.398,5.1752 0,0.064 -0.325,0.6182 -0.7223,1.2329 -0.3973,0.6146 -0.8728,1.5341 -1.0569,2.0431 -0.1839,0.509 -0.7474,1.7355 -1.2522,2.72541 -1.9703,3.86443 -3.4839,8.25685 -4.4396,12.88347 -0.269,1.30256 -0.5862,2.83721 -0.705,3.41033 -0.8952,4.32026 -0.7684,16.13844 0.2338,21.78823 0.2125,1.19836 0.5122,2.90352 0.6659,3.78926 1.7048,9.82062 7.4186,22.39482 13.2584,29.17729 5.4937,6.38047 9.8672,10.1928 14.1301,12.31723 0.8698,0.43343 2.0598,1.0782 2.6446,1.43282 1.6125,0.97786 7.6407,3.87 8.0664,3.87 0.3801,0 1.8456,0.40791 4.4169,1.22939 0.7816,0.24968 2.0179,0.55478 2.7473,0.67801 0.7294,0.12324 1.4806,0.3044 1.6692,0.40259 1.1835,0.61617 11.7551,1.62025 14.2457,1.35304 0.2084,-0.0223 1.7003,-0.17617 3.3156,-0.34179 z"
|
||||
id="path21272" /><path
|
||||
style="display:inline;fill:#985289;fill-opacity:1;stroke-width:0.71608"
|
||||
d="m -1217.7495,-1051.685 c 0.2256,-0.4349 0.3684,-1.4225 0.4858,-3.3629 0.091,-1.5109 0.2939,-3.6851 0.45,-4.8312 1.4151,-10.3986 1.5639,-26.4284 0.3735,-40.2652 -0.049,-0.5708 -0.1398,-1.8477 -0.2013,-2.8377 -0.061,-0.9899 -0.1502,-2.2262 -0.1968,-2.7472 -0.046,-0.521 -0.2147,-2.6951 -0.3734,-4.8314 -0.1587,-2.1361 -0.4987,-5.3759 -0.7555,-7.1995 -0.2568,-1.8236 -0.7225,-5.3619 -1.0348,-7.8628 -0.3124,-2.5009 -0.742,-5.5275 -0.9548,-6.7259 -0.5178,-2.9164 -1.277,-7.2826 -1.6306,-9.3783 -0.3249,-1.925 -0.8521,-4.5335 -1.3976,-6.9154 -0.589,-2.5717 -0.9336,-4.229 -1.2171,-5.8531 -0.1455,-0.8332 -0.4947,-2.0905 -0.7761,-2.7938 -1.7507,-4.3761 2.0554,-5.1067 9.0031,-3.9969 1.7764,0.2837 3.1253,0.6956 4.6444,1.0865 9.4816,2.7152 19.2492,5.0043 28.4168,8.7035 8.6259,3.4361 17.1419,7.2847 25.388,11.7429 2.375,1.2983 7.1398,4.4313 10.1363,6.6647 3.2272,2.4056 4.9495,2.6829 3.1139,0.5013 -0.2538,-0.3015 -3.3239,-3.2854 -4.8265,-4.4979 -0.4545,-0.3648 -1.0864,-0.8828 -1.4042,-1.1513 -0.3177,-0.2684 -1.459,-1.0784 -2.5361,-1.7999 -2.2452,-1.5038 -3.6749,-2.4889 -5.2628,-3.6262 -3.0312,-2.1712 -3.9258,-2.779 -5.846,-3.9724 -0.3572,-0.2221 -3.1891,-1.9679 -5.0476,-2.9577 -1.4671,-0.7814 -9.4465,-5.5474 -12.1993,-6.9444 -4.6782,-2.4616 -17.3614,-8.7704 -33.4401,-14.1486 -3.445,-1.1644 -5.9042,-1.8939 -9.189,-2.726 -2.0842,-0.5279 -4.2721,-1.0958 -4.8623,-1.2616 -6.4763,-1.8215 -10.378,2.9089 -7.7478,9.3934 0.1941,0.4785 0.4596,1.2963 0.5902,1.8173 0.1304,0.521 0.2999,1.0326 0.3764,1.1367 0.077,0.1043 0.4952,1.1274 0.9303,2.2736 0.4351,1.1463 0.9596,2.4417 1.1655,2.8786 0.206,0.4369 0.4883,1.2043 0.627,1.7052 0.3444,1.2421 1.3941,4.0412 1.6157,4.3081 0.099,0.1195 0.2614,0.5549 0.3605,0.9677 0.099,0.4127 0.4525,1.4751 0.7851,2.3607 0.3327,0.8859 0.7196,2.0368 0.8599,2.5579 0.4365,1.6219 1.1991,4.8734 1.4219,6.0627 0.1172,0.6252 0.3251,1.6483 0.4621,2.2736 0.1373,0.6252 0.3428,1.6909 0.4569,2.3683 0.4827,2.8633 1.1917,6.5772 1.3563,7.1048 0.1796,0.5756 0.5879,2.3891 1.4287,6.3471 0.8019,3.7744 2.0725,11.3353 2.6586,15.82 0.404,3.0914 0.3674,2.7931 0.534,4.3578 0.078,0.7294 0.2574,2.1361 0.3993,3.126 0.3641,2.5401 0.6153,4.679 0.8455,7.1996 0.2403,2.6305 0.3003,3.2443 0.6853,7.0102 0.4279,4.1849 0.5436,15.1848 0.2402,22.8303 -0.3113,7.8433 -0.2926,9.6345 0.1069,10.2443 0.4011,0.6121 0.5997,0.5808 0.9816,-0.1555 z"
|
||||
id="path21284" /><path
|
||||
style="display:inline;fill:#985289;fill-opacity:1;stroke-width:0.71608"
|
||||
d="m -1405.616,-1053.4513 c 0.312,-0.376 0.2615,-1.4618 -0.1972,-4.2491 -1.7144,-10.4147 -0.6072,-29.6521 2.857,-49.6393 0.2257,-1.3025 0.5179,-3.1356 0.6494,-4.0733 0.8044,-5.7413 1.7895,-10.9696 2.8738,-15.2519 0.8421,-3.3257 1.0755,-4.319 1.7589,-7.4837 0.2025,-0.9379 0.6736,-2.984 1.0471,-4.5472 0.3733,-1.563 0.8543,-3.6945 1.0686,-4.7365 0.2316,-1.1251 0.657,-2.4333 1.0475,-3.2209 0.6361,-1.2826 1.3706,-3.3267 2.0427,-5.6839 0.1781,-0.6252 0.8395,-2.1598 1.4697,-3.4103 1.0647,-2.1129 1.478,-3.1615 3.6588,-9.2836 0.4454,-1.2505 0.9676,-2.5721 1.1605,-2.9367 0.9121,-1.7253 -0.01,-5.9466 -1.6528,-7.5927 -0.9669,-0.9668 -3.1907,-1.1914 -5.3857,-0.5439 -0.3126,0.092 -0.8668,0.2014 -1.2315,0.2427 -0.3647,0.042 -0.791,0.12 -0.9473,0.1747 -0.1563,0.054 -1.0515,0.276 -1.9894,0.4917 -1.807,0.4156 -2.1263,0.4833 -4.0735,0.8652 -10.4605,2.5271 -20.2397,7.0816 -30.2154,11.0148 -3.2145,1.0811 -6.1141,2.673 -9.0981,4.2484 -0.8336,0.4398 -1.7288,0.9361 -1.9894,1.1028 -0.2605,0.1668 -0.8146,0.4857 -1.2315,0.7087 -0.4168,0.2231 -1.1415,0.6227 -1.6104,0.8881 -0.4689,0.2656 -1.492,0.8452 -2.2735,1.2879 -0.7815,0.4429 -1.8047,1.0081 -2.2736,1.2559 -0.469,0.2478 -1.1935,0.6628 -1.6104,0.9222 -0.4169,0.2594 -1.0573,0.6329 -1.4231,0.8301 -0.3659,0.1974 -1.374,0.7936 -2.2401,1.3252 -0.8662,0.5317 -1.6123,0.9665 -1.6579,0.9665 -0.1062,0 -2.1987,1.3464 -5.0994,3.281 -2.1815,1.455 -3.5593,2.5103 -6.4417,4.9337 -0.7295,0.6132 -2.0243,1.5682 -2.8774,2.1221 -0.8531,0.5539 -1.7269,1.1616 -1.942,1.3506 -4.433,3.8951 -2.7137,4.7633 2.1123,1.0667 2.6573,-2.0354 12.8868,-7.643 17.201,-9.4292 0.469,-0.1942 1.2788,-0.5458 1.8,-0.7815 0.3047,-0.138 8.464,-3.4405 9.7572,-4.0201 4.0687,-1.7679 16.6441,-5.573 22.1672,-7.0412 1.6151,-0.4295 3.4056,-0.9169 3.9787,-1.0834 1.5444,-0.4486 4.7972,-1.1271 8.4311,-1.7585 1.7715,-0.3078 3.9029,-0.6917 4.7367,-0.8532 5.3344,-1.0334 6.3323,0.7796 4.2707,7.7603 -0.092,0.3126 -0.3121,1.2078 -0.4884,1.9893 -0.1763,0.7815 -0.6866,2.7426 -1.1338,4.3576 -0.9973,3.6025 -1.1421,4.217 -1.6965,7.1997 -0.2422,1.3025 -0.9077,4.6702 -1.479,7.4838 -0.5715,2.8135 -1.2244,6.2239 -1.451,7.5784 -0.2267,1.3548 -0.535,3.1878 -0.6855,4.0736 -0.1503,0.8856 -0.3532,2.2072 -0.4508,2.9366 -0.098,0.7295 -0.3958,2.7486 -0.6626,4.487 -0.2666,1.7384 -0.6078,4.4667 -0.7582,6.0628 -0.1505,1.5961 -0.4463,4.5219 -0.6574,6.5018 -0.9168,8.5943 -1.3076,26.2731 -0.6983,31.5831 0.063,0.5525 0.2378,2.8376 0.3875,5.078 0.1631,2.442 0.3949,4.4783 0.5788,5.0844 0.1688,0.556 0.3763,1.8777 0.461,2.937 0.1454,1.8158 0.267,2.2176 1.0851,3.5833 0.1483,0.2476 0.7646,0.1535 1.0215,-0.156 z"
|
||||
id="path21282" /><path
|
||||
style="display:inline;fill:#985289;fill-opacity:1;stroke-width:0.71608"
|
||||
d="m -1548.2398,-987.38482 c 0.4745,-0.50736 1.1295,-1.38126 1.4553,-1.94199 0.3259,-0.56074 0.6691,-1.14741 0.7625,-1.30371 0.093,-0.1563 0.324,-0.66636 0.5125,-1.13346 1.4925,-3.69977 4.3377,-8.80252 7.7073,-13.82282 0.7949,-1.1842 1.4453,-2.1794 1.4453,-2.2115 0,-0.032 1.1724,-1.6307 2.6051,-3.5523 1.4328,-1.9217 2.733,-3.6844 2.8894,-3.9172 0.3416,-0.5087 4.2475,-5.3849 4.8508,-6.0557 0.2341,-0.2605 0.8366,-0.9426 1.3386,-1.5157 0.502,-0.5731 1.5163,-1.6815 2.2538,-2.463 0.7375,-0.7816 2.195,-2.4015 3.239,-3.5998 1.0438,-1.1984 2.6577,-2.9661 3.5863,-3.9283 5.9289,-6.1435 8.8047,-9.0873 9.5511,-9.7771 0.4689,-0.4334 2.2603,-2.1523 3.9808,-3.8196 1.7205,-1.6675 3.6509,-3.5028 4.2898,-4.0786 0.6389,-0.5759 1.5449,-1.5176 2.0135,-2.0928 0.4685,-0.5753 1.3515,-1.423 1.9622,-1.884 0.6106,-0.4611 1.6219,-1.3415 2.2473,-1.9564 0.6254,-0.6149 1.8772,-1.7832 2.7818,-2.5962 0.9046,-0.813 2.226,-2.0264 2.9367,-2.6963 0.7105,-0.6701 2.2298,-2.0191 3.376,-2.9977 1.1462,-0.9786 2.4007,-2.0678 2.7878,-2.4202 0.3869,-0.3525 0.952,-0.8219 1.2557,-1.0431 0.3036,-0.2211 1.4477,-1.1269 2.5425,-2.0126 1.0948,-0.8858 2.4054,-1.9262 2.9125,-2.312 0.507,-0.3859 1.3908,-1.0671 1.964,-1.5141 10.6223,-8.2831 14.2924,-10.0768 17.0767,-8.3453 1.0385,0.6458 1.6801,3.2202 1.6801,6.7414 0,0.8713 0.077,1.8313 0.17,2.1335 0.093,0.3021 0.2756,1.1888 0.4049,1.9703 0.4971,3.0072 1.2964,6.6138 1.8688,8.431 0.5662,1.7981 1.1631,3.9151 1.8163,6.4418 0.1616,0.6252 0.3776,1.2848 0.48,1.4657 0.1024,0.181 0.186,0.5017 0.186,0.7126 0,0.211 0.1635,0.745 0.3631,1.1867 0.1997,0.4418 0.5522,1.3573 0.7832,2.0346 0.2311,0.6774 0.5718,1.5726 0.7568,1.9894 0.1853,0.4168 0.3875,1.0563 0.4494,1.4209 0.062,0.3648 0.2474,0.919 0.4119,1.2316 0.1647,0.3126 0.6363,1.4515 1.0482,2.5309 0.4118,1.0793 1.2204,2.9075 1.7966,4.0624 0.5763,1.155 1.2567,2.5962 1.5119,3.2027 0.8664,2.0582 5.8144,10.7252 6.3599,11.1399 0.069,0.052 0.6232,0.8781 1.2322,1.8353 1.0459,1.6441 3.2449,4.9699 4.1106,6.2166 1.3619,1.9615 3.5329,5.2228 3.5329,5.3074 0,0.055 0.4095,0.6315 0.9099,1.2805 0.5005,0.649 1.0434,1.3933 1.2064,1.6538 0.163,0.2605 0.8682,1.1557 1.567,1.9893 0.6988,0.8336 1.4347,1.8317 1.6353,2.2181 0.416,0.8012 1.7336,1.6659 2.5384,1.6659 0.705,0 0.5911,-1.1844 -0.2141,-2.2259 -0.6366,-0.8234 -0.814,-1.0771 -2.0387,-2.9129 -0.5129,-0.7687 -1.0817,-1.5682 -1.2642,-1.7766 -0.6259,-0.7149 -3.4461,-5.3512 -4.7252,-7.768 -0.5516,-1.042 -1.2021,-2.1915 -1.4456,-2.5543 -0.2435,-0.3629 -0.4428,-0.753 -0.4428,-0.8671 0,-0.1141 -0.3624,-0.8829 -0.8053,-1.7085 -1.4465,-2.6963 -2.6186,-5.2026 -3.1656,-6.769 -0.5311,-1.5206 -2.0645,-5.4653 -2.3713,-6.1001 -0.1512,-0.3126 -0.4399,-0.9946 -0.6418,-1.5157 -0.2017,-0.521 -0.6368,-1.571 -0.9668,-2.3334 -0.3299,-0.7623 -0.9714,-2.4249 -1.4253,-3.6945 -1.3543,-3.7874 -1.7917,-4.9356 -2.0703,-5.4345 -0.2673,-0.4786 -0.6724,-1.8022 -1.1886,-3.8841 -0.155,-0.6251 -0.4853,-1.8188 -0.734,-2.6524 -0.2487,-0.8337 -0.7134,-2.624 -1.0328,-3.9788 -0.3193,-1.3545 -0.6723,-2.804 -0.7843,-3.2208 -0.2455,-0.9138 -0.2426,-0.8952 -0.6278,-3.9787 -0.1692,-1.3547 -0.3864,-2.7614 -0.4826,-3.1262 -0.096,-0.3647 -0.2194,-1.1319 -0.2734,-1.7052 -0.1823,-1.9329 -0.6274,-8.2332 -0.6559,-9.2836 -0.015,-0.5732 -0.1149,-2.193 -0.221,-3.5998 -0.106,-1.4068 -0.1805,-3.5808 -0.1655,-4.8312 0.037,-3.0537 -0.1931,-7.1112 -0.4291,-7.5787 -0.3257,-0.6454 -1.7529,-1.8512 -2.0699,-1.9893 -0.4611,-0.201 -0.7996,-0.6909 -2.9084,-0.59 -1.7376,0.083 -6.6203,2.0008 -9.5065,3.7338 -2.0191,1.2123 -3.3798,1.9813 -3.5452,2.1164 -0.8281,0.6766 -1.6979,1.2016 -2.8117,1.9904 -1.0874,0.7703 -1.4924,1.1562 -2.1879,1.7326 -0.5965,0.5643 -1.7239,1.5209 -2.5054,2.1258 -0.7816,0.6048 -1.5179,1.1877 -1.6363,1.2951 -0.8827,0.8002 -2.4055,2.0442 -3.546,2.8971 -0.7449,0.5569 -1.8232,1.4604 -2.3963,2.0076 -0.573,0.5472 -1.3404,1.1971 -1.7051,1.4442 -0.3647,0.2471 -1.1431,0.8819 -1.7297,1.4107 -0.5867,0.5288 -1.7375,1.5559 -2.5578,2.2823 -0.8201,0.7265 -2.0879,1.9457 -2.8174,2.7094 -2.6641,2.7895 -6.3887,6.4937 -7.1858,7.1469 -0.9144,0.7492 -6.9603,6.815 -9.2974,9.3279 -0.8337,0.8963 -2.5815,2.723 -3.884,4.0595 -2.9889,3.0664 -4.507,4.7225 -5.4943,5.9935 -0.4281,0.5511 -1.1201,1.3184 -1.538,1.7052 -0.4178,0.3869 -0.8763,0.9164 -1.0191,1.1769 -0.1426,0.2606 -0.9917,1.3263 -1.8869,2.3683 -4.7636,5.5451 -6.7131,8.0627 -9.6831,12.5046 -0.9059,1.3546 -1.9344,2.858 -2.2858,3.341 -0.3514,0.4829 -0.6394,0.9518 -0.6399,1.042 -4e-4,0.09 -0.4907,0.8147 -1.0893,1.6099 -0.5988,0.7951 -1.6427,2.3954 -2.3201,3.556 -0.6773,1.1606 -1.9354,3.3078 -2.7955,4.7715 -1.3339,2.2696 -6.0445,11.5795 -7.7089,15.2358 -0.2847,0.6252 -0.7597,1.6483 -1.0557,2.27353 -3.1557,6.66548 -4.7319,10.2463 -4.7328,10.75201 0,0.80537 0.5779,0.65706 1.5681,-0.40146 z"
|
||||
id="path21280" /><path
|
||||
style="display:inline;fill:#985289;fill-opacity:1;stroke-width:0.71608"
|
||||
d="m -1073.8029,-987.09522 c -0.2085,-1.27219 -0.482,-2.2738 -0.8278,-3.03123 -0.198,-0.43355 -0.4916,-1.08666 -0.6523,-1.45138 -0.1609,-0.36472 -0.3727,-0.79101 -0.4707,-0.94731 -0.098,-0.15631 -0.5328,-1.05153 -0.9664,-1.98937 -1.1716,-2.45971 -2.0579,-4.97585 -3.5356,-7.29429 -0.121,-0.1564 -0.6584,-1.1795 -1.1942,-2.2736 -1.1727,-2.3951 -1.3912,-2.8022 -2.4028,-4.4774 -0.4321,-0.7157 -1.3597,-2.4096 -2.0612,-3.7643 -0.7014,-1.3546 -1.3377,-2.5482 -1.4138,-2.6524 -0.076,-0.1042 -0.4842,-0.8289 -0.9067,-1.6105 -0.4225,-0.7815 -1.0683,-1.9325 -1.4351,-2.5577 -0.3669,-0.6252 -0.8386,-1.4997 -1.0482,-1.9432 -0.5408,-1.1442 -5.7659,-9.0685 -7.3667,-11.1723 -0.4936,-0.6486 -1.5795,-2.1298 -2.4131,-3.2915 -0.8336,-1.1617 -1.7159,-2.3361 -1.9607,-2.6099 -0.2448,-0.2737 -0.8203,-1.0669 -1.2789,-1.7624 -0.4587,-0.6956 -1.7097,-2.2303 -2.78,-3.4104 -1.8795,-2.0723 -3.5959,-4.0701 -4.7798,-5.5637 -2.1676,-2.7347 -14.2706,-15.5588 -17.1359,-18.1572 -0.359,-0.3255 -2.2748,-2.2119 -4.2573,-4.1917 -1.9826,-1.9799 -4.1745,-4.0687 -4.8711,-4.6418 -0.6965,-0.5732 -2.5621,-2.1321 -4.1457,-3.4643 -2.4687,-2.0769 -11.4131,-8.9561 -14.171,-10.8988 -0.4895,-0.3449 -1.2419,-0.9418 -1.6717,-1.3263 -0.4299,-0.3845 -1.2825,-0.9929 -1.8947,-1.3519 -2.7876,-2.0959 -5.5744,-3.6163 -8.756,-4.8618 -3.8438,-1.5265 -6.4561,-1.3706 -8.3341,0.4975 -1.1404,1.1343 -1.1133,0.9971 -1.2673,6.438 -0.1196,4.2279 -0.3708,8.1391 -0.6606,10.2852 -0.1014,0.7518 -0.2222,1.6652 -0.2684,2.0299 -0.046,0.3647 -0.2574,1.8567 -0.4694,3.3156 -0.2119,1.4589 -0.4782,3.4197 -0.5917,4.3576 -0.1136,0.9379 -0.3264,2.2168 -0.473,2.842 -0.1467,0.6252 -0.531,2.5435 -0.8542,4.2629 -0.9956,5.2981 -2.8717,11.6423 -5.4067,18.2831 -0.2784,0.7295 -0.7381,1.9657 -1.0214,2.7473 -0.5141,1.4179 -2.1056,5.4595 -2.5739,6.5364 -0.136,0.3127 -0.5414,1.2505 -0.9011,2.0842 -0.3595,0.8336 -0.8263,1.8993 -1.0372,2.3682 -0.2109,0.469 -0.9542,2.1314 -1.6518,3.6946 -1.141,2.5568 -2.3999,5.0735 -5.1179,10.231 -0.9403,1.7843 -1.3125,2.417 -2.7943,4.7515 -0.495,0.7797 -0.9,1.4581 -0.9,1.5074 0,0.049 -0.4476,0.6788 -0.9946,1.3988 -1.1682,1.5376 -1.6478,2.1887 -2.0369,2.7652 -0.1561,0.2316 -0.5136,0.7521 -0.7941,1.1566 -0.7201,1.0387 -0.7861,1.8723 -0.1483,1.8723 0.464,0 3.0386,-2.4983 4.0687,-3.9482 0.2084,-0.2933 0.5494,-0.7289 0.7578,-0.9679 0.784,-0.8992 1.0344,-1.2438 1.3651,-1.8798 0.187,-0.3597 0.6955,-1.0665 1.1299,-1.5709 0.4344,-0.5043 1.0739,-1.3128 1.4209,-1.7968 0.3472,-0.4839 1.2019,-1.6349 1.8995,-2.5577 1.25,-1.6537 2.5486,-3.4145 3.613,-4.8987 0.5239,-0.7308 2.1255,-3.1219 3.5922,-5.3635 0.6158,-0.9411 3.298,-5.3098 3.7447,-6.0991 0.088,-0.1562 0.7721,-1.5204 1.5194,-3.0313 0.7472,-1.511 1.4202,-2.8325 1.4955,-2.9368 0.075,-0.1041 0.3796,-0.8288 0.6764,-1.6103 0.47,-1.2376 1.2426,-3.0953 2.0881,-5.0208 0.6611,-1.5059 0.9385,-2.2065 1.4623,-3.6946 1.056,-2.999 1.4437,-4.07 1.9545,-5.3996 0.7763,-2.0199 1.8005,-5.35 2.0688,-6.726 0.132,-0.6773 0.3756,-1.743 0.5413,-2.3683 0.9102,-3.4354 1.4072,-6.5059 1.5487,-9.5678 0.2417,-5.2331 0.8061,-7.1291 2.3278,-7.8203 2.1755,-0.9882 5.1064,-0.1505 8.7253,2.4935 3.0894,2.2574 4.5547,3.2503 5.3397,3.6187 0.469,0.22 1.1937,0.7328 1.6105,1.1398 0.4168,0.4069 1.0754,0.8719 1.4634,1.0335 0.8381,0.3488 4.774,3.6266 5.6935,4.257 0.4031,0.2763 0.62,0.4798 0.7922,0.5827 0.1288,0.077 0.7013,0.4507 1.3721,0.9034 0.6046,0.4969 1.3124,0.9973 1.5729,1.1119 0.2605,0.1144 0.9,0.5835 1.421,1.0423 0.521,0.4588 1.2883,1.0644 1.7052,1.3459 0.6838,0.4617 2.4522,1.9606 5.968,5.0582 0.6773,0.5968 1.9562,1.7076 2.8419,2.4685 0.8858,0.7611 3.0738,2.8429 4.8624,4.6262 1.7885,1.7834 5.6219,5.5871 8.5187,8.4528 7.1129,7.0364 11.0669,11.2398 13.9759,14.857 0.5098,0.6339 1.4476,1.7113 2.0841,2.3943 1.712,1.8371 2.2126,2.4194 3.2492,3.779 0.5163,0.6773 1.4931,1.8413 2.1706,2.5866 1.7833,2.585 4.0616,4.8036 5.7789,7.4295 0.1043,0.1633 0.5732,0.8812 1.0421,1.5954 0.4689,0.7144 0.9378,1.446 1.0421,1.6261 0.1041,0.1802 0.4546,0.6644 0.7788,1.0762 1.696,2.9736 3.6613,5.7482 5.3849,8.70596 0.316,0.52102 0.7207,1.24571 0.8993,1.61044 0.3263,0.66622 1.3013,1.94784 3.5274,6.347 2.1518,4.25234 3.9333,6.42391 3.5996,4.38788 z"
|
||||
id="path21278" /><path
|
||||
style="display:inline;fill:#812973;fill-opacity:1;stroke-width:0.71608"
|
||||
d="m -1257.546,-1026.1934 c 0.6031,-0.6361 0.9273,-1.0595 1.8353,-2.3965 0.8999,-1.3251 4.7147,-8.2521 5.1155,-9.2887 0.141,-0.3646 0.319,-0.7483 0.3956,-0.8526 0.077,-0.1041 0.4471,-0.9993 0.8234,-1.9893 0.3763,-0.9899 0.8463,-2.2262 1.0446,-2.7472 4.7917,-12.5948 6.1783,-29.6549 3.357,-41.3029 -0.9629,-3.9756 -1.1208,-4.5922 -1.5762,-6.1575 -0.2576,-0.8857 -0.855,-2.8041 -1.3274,-4.2629 -0.4724,-1.4588 -0.9704,-3.0361 -1.1066,-3.5051 -2.0915,-7.2017 -5.9507,-14.1466 -11.3704,-20.462 -9.2906,-10.8261 -19.217,-18.4629 -29.3973,-22.6161 -4.136,-1.974 -8.4005,-3.4284 -12.8558,-4.5535 -3.473,-0.8336 -13.2154,-0.8312 -16.5691,0 -0.5731,0.1428 -1.4257,0.3521 -1.8946,0.4652 -1.9029,0.4591 -5.2317,1.3855 -5.5516,1.5451 -0.1878,0.093 -0.9746,0.336 -1.7487,0.5388 -0.774,0.2026 -1.7714,0.5684 -2.2164,0.8126 -0.445,0.2443 -1.4209,0.675 -2.1688,0.9571 -0.7479,0.2821 -1.4148,0.7082 -1.5985,0.8005 -1.0377,0.5218 -2.6866,1.1875 -3.5783,1.7035 -0.4689,0.2714 -1.5772,0.8799 -2.4629,1.3523 -0.8858,0.4725 -1.7384,0.9639 -1.8947,1.092 -0.1563,0.1282 -1.3926,0.9409 -2.7471,1.8059 -2.5197,1.6087 -4.4044,3.046 -6.9091,5.2683 -0.7789,0.6911 -1.845,1.6335 -2.3691,2.0942 -1.4987,1.3175 -5.6598,5.6044 -7.4854,7.7117 -3.4825,4.0196 -6.8733,9.1388 -8.9651,13.5349 -3.5094,7.3748 -5.0589,11.7482 -7.2125,20.3554 -1.2036,4.8107 -1.6275,9.3482 -1.6285,17.4305 -7e-4,5.3576 0.05,6.1544 0.7294,11.4625 0.623,4.868 2.3114,11.5479 3.7114,14.6835 0.2327,0.521 0.5262,1.2883 0.6522,1.7052 0.3681,1.2176 0.7938,2.1783 1.6374,3.6944 0.4348,0.7816 0.9873,1.9094 1.2277,2.5063 0.2404,0.5969 1.0001,1.7904 1.688,2.6524 1.562,1.9569 2.3013,3.3245 2.9505,4.1498 1.6195,2.0588 1.8123,2.3259 4.1569,-0.085 1.0457,-1.0751 2.7112,-2.5944 3.7012,-3.3763 0.9899,-0.7819 1.9276,-1.544 2.084,-1.6934 2.1254,-2.032 12.4121,-7.9433 13.8227,-7.9433 0.1169,0 0.529,-0.1598 0.9156,-0.3553 0.3866,-0.1955 1.8539,-0.7509 3.2607,-1.2344 1.4067,-0.4836 3.1546,-1.0963 3.884,-1.3618 0.7294,-0.2655 1.8378,-0.6413 2.463,-0.8352 0.6253,-0.1939 1.5205,-0.4799 1.9893,-0.6356 1.3066,-0.4338 4.825,-1.2345 6.726,-1.5307 0.9379,-0.1461 2.0035,-0.3593 2.3683,-0.4738 2.3607,-0.741 15.5243,-0.8001 19.7041,-0.088 5.1718,0.8807 6.0151,1.065 11.1783,2.4441 1.9253,0.5143 2.6047,0.7456 4.7366,1.6127 1.0942,0.4449 2.5009,1.0162 3.1262,1.2694 1.8824,0.762 7.4729,3.6337 8.7127,4.4754 0.6378,0.4329 2.3872,1.5675 3.1188,2.1031 1.7928,1.3128 3.0385,2.1835 4.5487,3.3861 0.5486,0.4371 1.3362,1.1459 1.8064,1.5817 0.4702,0.4357 1.0741,0.962 1.9411,1.6489 1.6058,1.272 2.1852,1.7286 2.7442,2.1014 1.2472,0.8317 1.6522,1.6687 2.4773,0.7985 z"
|
||||
id="path21276-14-5" /><path
|
||||
style="display:inline;fill:#6d2361;fill-opacity:1;stroke-width:0.71608"
|
||||
d="m -1266.7895,-849.43329 c 0.5355,-0.39077 1.6797,-1.21739 2.5426,-1.83693 0.8631,-0.61953 2.1659,-1.60301 2.8954,-2.18549 0.7294,-0.58249 1.5448,-1.19686 1.8121,-1.36527 1.6596,-1.04601 4.7513,-4.36249 7.4678,-8.01086 0.4807,-0.64546 0.9728,-1.25106 3.0844,-3.79521 0.1729,-0.20841 0.6589,-0.89545 1.0799,-1.52675 5.1167,-7.67235 4.8088,-9.09303 -4.3032,-19.86164 -1.2246,-1.44735 -2.7426,-3.35301 -3.3734,-4.2348 -0.6308,-0.8818 -1.2281,-1.70117 -1.3273,-1.82084 -1.2908,-1.55591 -8.5973,-11.73258 -10.0137,-13.94728 -1.5488,-2.42196 -1.2465,-2.51023 -9.5836,2.79801 -0.8337,0.53077 -2.0995,1.32539 -2.8133,1.76581 -1.5579,0.96155 -1.6837,2.29848 -0.3186,3.38729 0.065,0.0521 0.3236,0.39313 0.5741,0.75785 0.2505,0.36472 0.5029,0.70575 0.561,0.75785 0.058,0.0521 0.4422,0.64891 0.8537,1.32624 0.4114,0.67733 1.0997,1.70043 1.5296,2.27355 0.4299,0.57312 0.839,1.16993 0.9093,1.32624 0.071,0.15631 0.5102,0.75311 0.9775,1.32624 1.6455,2.01797 3.4702,4.47538 4.9239,6.6312 0.8081,1.19835 1.5272,2.22145 1.5982,2.27355 0.1737,0.12754 2.6671,3.96245 2.6671,4.10199 0,0.0606 0.3197,0.54508 0.7105,1.07665 0.3907,0.53156 0.8064,1.13979 0.9235,1.35162 0.1173,0.21183 0.6434,1.09888 1.1693,1.97123 1.6317,2.70629 1.8455,5.95544 1.019,7.79233 -1.4201,3.15641 -2.539,6.52626 -3.7065,9.82355 -0.2724,0.76585 -1.0478,2.48736 -1.7231,3.82559 -2.4441,4.84341 -2.474,5.72407 -0.1362,4.01828 z"
|
||||
id="path21271" /><path
|
||||
style="display:inline;fill:#6d2361;fill-opacity:1;stroke-width:0.71608"
|
||||
d="m -1360.5688,-848.69619 c 0.035,-0.2338 -0.1948,-0.80398 -0.521,-1.2965 -0.3203,-0.48356 -0.504,-1.04067 -0.5824,-1.19682 -1.0557,-2.10404 -2.0403,-5.59536 -3.2309,-9.2115 -0.8697,-3.39263 -1.0995,-4.44692 -1.5056,-8.25149 -0.2906,-2.72343 0.7082,-4.66206 2.8473,-7.73189 1.1187,-1.60539 2.5854,-3.78534 4.8441,-7.1996 0.6549,-0.98995 1.4089,-2.04762 1.6758,-2.35039 0.2666,-0.30277 0.4872,-0.60117 0.49,-0.66312 0,-0.062 0.3516,-0.49091 0.7751,-0.95328 0.4237,-0.46234 0.9969,-1.14274 1.2739,-1.51196 0.277,-0.36923 0.6446,-0.84351 0.8168,-1.05398 0.1723,-0.21047 0.8531,-1.06473 1.513,-1.89837 0.6599,-0.83364 1.2862,-1.61877 1.3919,-1.74474 0.1058,-0.12596 0.4906,-0.62397 0.8555,-1.10666 0.3646,-0.48269 1.7927,-2.22918 3.1733,-3.88106 3.0229,-3.61653 3.0584,-3.95483 0.516,-4.92144 -0.2531,-0.0962 -1.3293,-0.75331 -2.3915,-1.46014 -1.0621,-0.70681 -2.8181,-1.85314 -3.9022,-2.54738 -1.084,-0.69424 -2.1138,-1.38298 -2.2884,-1.53052 -1.2114,-1.02354 -2.1925,-1.28463 -2.5421,-0.67648 -0.9294,1.61649 -3.2702,4.8717 -6.2417,8.67948 -0.4473,0.57313 -1.6135,2.10778 -2.5916,3.41032 -0.9781,1.30256 -1.984,2.62407 -2.2351,2.93667 -0.2511,0.31263 -0.6285,0.78154 -0.8386,1.04206 -0.572,0.70951 -2.0223,2.38107 -3.2786,3.77877 -0.6141,0.6831 -1.8495,2.1372 -2.7455,3.23135 -0.8959,1.09415 -1.9,2.28776 -2.2311,2.65248 -0.3312,0.36472 -0.798,0.9189 -1.0374,1.23151 -0.2393,0.31261 -0.4863,0.61103 -0.5488,0.66313 -2.75,2.29064 -3.6562,7.31753 -2.0075,11.13601 0.8388,1.94262 2.4099,4.66651 2.975,5.15779 0.06,0.0521 0.4803,0.64892 0.9342,1.32626 2.5655,3.82826 5.1557,6.9409 7.4826,8.99167 0.9379,0.82653 2.1072,1.88607 2.5986,2.35453 0.4913,0.46846 1.0455,0.93331 1.2315,1.03299 0.2831,0.15176 2.2094,1.69445 2.5169,2.01576 1.765,1.84365 2.6901,2.35308 2.8085,1.54654 z"
|
||||
id="path21270" /><path
|
||||
style="display:inline;fill:#812973;fill-opacity:1;stroke-width:0.71608"
|
||||
d="m -1542.7376,-871.23997 c 0.2862,-0.71515 0.3795,-1.94635 0.6059,-7.98636 0.3653,-9.74366 2.0798,-19.54708 4.4068,-25.19856 0.4076,-0.98996 1.1027,-2.73252 1.5447,-3.87237 1.2218,-3.15114 4.0398,-8.5793 6.3448,-12.2215 4.396,-6.94599 8.186,-12.56318 11.3827,-16.86998 1.3546,-1.82507 2.6392,-3.57623 2.8546,-3.89147 0.2155,-0.31523 0.5298,-0.74153 0.6984,-0.94732 0.1686,-0.20577 0.8479,-1.09883 1.5094,-1.98457 1.3806,-1.84865 3.2151,-4.21831 3.3734,-4.35765 0.059,-0.0521 0.5291,-0.64891 1.0442,-1.32625 0.515,-0.67732 1.5341,-1.90806 2.2646,-2.73496 0.7306,-0.82689 1.9252,-2.19642 2.6546,-3.04337 0.7295,-0.84697 1.7526,-1.99705 2.2736,-2.55575 0.521,-0.5587 1.4702,-1.57641 2.1094,-2.26158 0.6392,-0.68517 1.4791,-1.62942 1.8666,-2.09834 0.3874,-0.46893 1.4509,-1.66254 2.3633,-2.65249 0.9122,-0.98994 2.0126,-2.21084 2.4452,-2.7131 0.4325,-0.50226 1.8728,-1.97506 3.2005,-3.27287 3.4847,-3.40602 8.8565,-8.74429 10.2086,-10.14491 1.7687,-1.83199 3.8756,-3.82394 4.6153,-4.36366 0.3648,-0.26605 0.9616,-0.76408 1.3263,-1.10671 0.3648,-0.34263 1.132,-0.94417 1.7052,-1.33677 0.5731,-0.3926 1.2422,-0.9045 1.5455,-1.11477 0.282,-0.19555 0.6671,-0.43095 0.8166,-0.53453 0.135,-0.0936 0.4514,-0.21475 0.764,-0.42178 0.3127,-0.20703 0.4612,-0.17118 0.9836,-0.37768 2.2253,-0.87975 4.476,0.11177 6.1894,1.57586 0.3272,0.40939 1.064,1.27474 1.637,1.92299 0.5732,0.64828 1.4425,1.68744 1.9319,2.30928 1.2944,1.64486 2.1747,2.5513 3.5625,3.66878 0.6774,0.54536 1.6578,1.44392 2.179,1.99682 0.5767,0.6121 1.7993,1.51779 3.126,2.31576 1.1984,0.72078 2.5199,1.65154 2.9367,2.06837 0.4168,0.41683 1.2268,1.01548 1.7999,1.33036 1.8397,1.01067 7.0653,3.59861 8.3363,4.12849 4.1139,2.01877 8.5144,3.56127 12.9783,4.62318 0.521,0.0928 1.5868,0.31849 2.3683,0.50167 2.9593,0.69362 3.9531,-0.25782 1.5541,-1.48799 -0.2817,-0.14444 -1.0732,-0.56358 -1.759,-0.93143 -0.6857,-0.36784 -2.0072,-0.98636 -2.9366,-1.37447 -6.1224,-2.55672 -14.0957,-7.14843 -16.6574,-9.59277 -0.521,-0.49715 -1.2457,-1.14719 -1.6105,-1.44454 -2.1172,-1.7262 -5.7038,-5.35554 -8.5522,-8.65448 -0.3502,-0.40558 -1.2722,-1.41431 -2.0488,-2.24163 -1.7108,-1.82231 -2.0356,-2.65361 -2.2824,-3.01532 -1.2058,-1.76765 -1.7477,-2.63188 -2.5598,-4.92227 -1.559,-3.69329 -2.2226,-4.54719 -3.5978,-5.47479 -0.4462,-0.301 -1.1291,-0.257 -1.7301,-0.3396 -1.1835,-0.03 -2.6585,-0.083 -4.3961,0.6424 -4.2764,2.2443 -4.4754,2.3756 -7.0415,4.66753 -0.6589,0.58851 -1.421,1.51352 -1.8841,1.86936 -0.4632,0.35582 -1.1874,1.03063 -1.6094,1.49955 -0.422,0.46892 -2.171,2.21671 -3.8866,3.88398 -5.6083,5.44995 -8.9789,8.87071 -10.7135,10.8728 -0.9379,1.08242 -2.3446,2.62265 -3.1262,3.42272 -0.7815,0.80008 -2.1027,2.21644 -2.9358,3.14746 -0.8331,0.93103 -1.9415,2.12332 -2.463,2.64954 -0.5215,0.52622 -1.4145,1.50668 -1.9842,2.17882 -0.5699,0.67213 -1.4117,1.5631 -1.8708,1.97992 -1.9676,1.7866 -2.8699,2.74685 -4.0058,4.26292 -0.6637,0.88573 -1.3537,1.78095 -1.5334,1.98935 -0.1797,0.20841 -0.6603,0.7626 -1.0681,1.23151 -1.4238,1.63741 -5.0422,6.27716 -5.9271,7.60002 -0.1563,0.23368 -0.7132,0.9003 -1.2376,1.48137 -0.5244,0.58107 -1.334,1.56767 -1.7992,2.19246 -0.4652,0.62478 -1.6177,2.11644 -2.5612,3.3148 -1.6506,2.09676 -5.5239,7.81878 -8.0593,11.90625 -0.6686,1.07769 -1.546,2.48445 -1.9496,3.12613 -0.4039,0.64169 -1.3744,2.31768 -2.1568,3.72444 -0.7825,1.40676 -1.7935,3.1266 -2.2469,3.82186 -0.4534,0.69527 -0.9868,1.67649 -1.1854,2.18051 -0.1987,0.504 -0.536,1.25666 -0.7496,1.67255 -1.4969,2.91424 -3.2808,7.9129 -4.0226,11.27137 -0.1264,0.57312 -0.3049,1.34046 -0.3964,1.70516 -1.0738,4.28096 -1.0368,31.97216 0.046,34.34866 0.324,0.71124 0.6487,0.64037 0.9915,-0.21641 z"
|
||||
id="path21268" /><path
|
||||
style="display:inline;fill:#812973;fill-opacity:1;stroke-width:0.71608"
|
||||
d="m -1078.2395,-870.79523 c 0.7098,-7.13011 0.2636,-31.53813 -0.6564,-35.89493 -0.093,-0.44397 -2.6652,-7.38571 -5.8012,-13.55489 -2.6861,-5.28448 -3.3397,-6.45631 -4.5271,-8.11617 -1.2048,-1.68457 2.9545,4.03021 -4.8475,-7.74839 -1.1226,-1.69496 -2.3903,-3.50803 -2.817,-4.02904 -0.4268,-0.52102 -1.0546,-1.33099 -1.3953,-1.79991 -0.3407,-0.46892 -1.1011,-1.49202 -1.6897,-2.27354 -0.5886,-0.78154 -1.5187,-2.01778 -2.0669,-2.74722 -0.5481,-0.72944 -1.2546,-1.66727 -1.5699,-2.0841 -0.5298,-0.70052 -3.2613,-4.41584 -4.6346,-6.30389 -3.2216,-4.42897 -12.6092,-16.84587 -22.6349,-26.9449 -3.4964,-3.52219 -6.2044,-6.37773 -8.264,-8.71446 -1.0968,-1.24432 -2.8294,-2.94055 -4.5507,-4.45515 -1.8669,-1.64264 -2.084,-1.86732 -3.8454,-3.97872 -1.7014,-2.03966 -2.5666,-2.88156 -5.0597,-3.70856 -0.7207,-0.2391 -4.0827,-0.3408 -4.9339,-0.1491 -2.2674,0.5104 -3.5159,1.4734 -4.387,3.38401 -0.8915,1.9552 -0.9137,2.0117 -1.37,3.47936 -1.7346,3.28744 -4.1996,6.62796 -6.8429,9.33273 -0.7561,0.71659 -1.688,1.6013 -2.0708,1.96601 -0.3829,0.36471 -1.1544,1.04678 -1.7145,1.5157 -0.56,0.46892 -1.4063,1.2077 -1.8805,1.64173 -1.6622,1.52141 -3.0268,2.49602 -10.5875,7.56197 -3.0309,2.03077 -3.4789,2.31622 -4.3423,2.76676 -0.03,0.0156 -1.8058,1.23781 -4.1876,2.32977 -1.1149,0.59434 -2.9536,1.42519 -3.1541,1.42519 -0.084,0 -0.6941,0.25578 -1.3557,0.56838 -0.6617,0.31262 -1.275,0.5684 -1.3629,0.5684 -0.088,0 -0.4074,0.11936 -0.71,0.26524 -0.3026,0.14589 -1.0463,0.49593 -1.6527,0.77785 -1.1309,0.52574 -1.6101,1.12184 -1.3813,1.71808 0.2476,0.64512 3.4959,0.23053 7.8836,-1.00616 0.8857,-0.24965 1.9088,-0.5279 2.2735,-0.61833 1.4779,-0.3664 5.6207,-1.88788 7.768,-2.85287 4.4301,-1.99081 12.5209,-6.68979 15.0747,-8.75506 0.8508,-0.68804 2.5045,-1.97868 3.2086,-2.50409 1.2827,-0.95731 5.108,-4.65017 7.7679,-7.49895 3.5334,-3.78443 6.7745,-4.49663 9.3768,-2.06043 0.3639,0.34064 1.151,0.97546 1.7491,1.4107 1.4877,1.08252 5.5623,4.79321 7.6241,6.94318 2.8062,2.9263 6.459,6.712 9.6693,10.02119 4.595,4.73639 7.9926,8.59798 12.2446,13.91698 0.5831,0.72944 1.8606,2.22829 2.839,3.33078 0.9783,1.10249 3.0575,3.56479 4.6207,5.47176 1.563,1.90699 3.3702,4.1086 4.0161,4.89249 1.168,1.41764 5.5534,7.3874 6.2239,8.47213 0.1931,0.31262 1.5064,2.3035 2.9182,4.42418 1.4119,2.12069 2.8147,4.25214 3.1173,4.73658 0.3027,0.48443 0.9102,1.43496 1.3503,2.11228 1.6435,2.53022 2.9389,4.71285 4.2169,7.10487 0.7238,1.35466 1.5413,2.84667 1.8168,3.31559 1.0481,1.78405 1.8025,3.38892 2.5828,5.49443 0.4441,1.19835 0.9748,2.60511 1.1792,3.12614 1.6288,4.15067 2.5061,7.60396 3.297,12.9782 0.2684,1.82358 0.5194,3.52875 0.5578,3.78926 0.2807,1.90278 0.6632,6.91398 0.8317,10.89412 0.2169,5.1239 0.4391,7.07044 0.9083,7.95744 0.6754,1.27705 0.8975,0.91971 1.1778,-1.89462 z"
|
||||
id="path21266" /><path
|
||||
style="display:inline;fill:#812973;fill-opacity:1;stroke-width:0.71608"
|
||||
d="m -1427.4952,-780.23842 c -0.066,-0.26406 -0.6617,-1.39373 -1.3231,-2.51039 -2.653,-4.47862 -6.2867,-11.44353 -7.6191,-14.60376 -0.3793,-0.89993 -1.0283,-2.40098 -1.4418,-3.33566 -0.9896,-2.23618 -2.1411,-5.22374 -3.3612,-8.72103 -0.5453,-1.56307 -1.1456,-3.2256 -1.3337,-3.69452 -0.5822,-1.45044 -1.2685,-3.60656 -2.9242,-9.18688 -0.4944,-1.66612 -0.9747,-3.17098 -1.0673,-3.34412 -0.4258,-0.79558 -1.5016,-4.0549 -1.5016,-4.54935 0,-0.30354 -0.1113,-0.82623 -0.2474,-1.16155 -0.136,-0.33532 -0.4006,-1.29173 -0.588,-2.12537 -0.1874,-0.83363 -0.4881,-2.06988 -0.6685,-2.74722 -0.7629,-2.86666 -1.3739,-5.26023 -1.5234,-5.96807 -0.088,-0.41681 -0.3295,-1.39729 -0.5363,-2.17882 -0.4471,-1.68801 -1.4363,-6.56762 -2.0164,-9.94681 -0.1431,-0.83363 -0.444,-2.32565 -0.6687,-3.3156 -0.2247,-0.98994 -0.5297,-2.3932 -0.6778,-3.11834 -0.148,-0.72516 -0.394,-1.74826 -0.5467,-2.27356 -0.1526,-0.52531 -0.4076,-1.93557 -0.5668,-3.13393 -0.1591,-1.19834 -0.4188,-2.90351 -0.5772,-3.78926 -0.2878,-1.61166 -0.744,-5.01553 -1.4343,-10.70466 -0.2022,-1.66727 -0.4921,-3.79872 -0.6441,-4.73657 -0.585,-3.60923 -1.3977,-10.37009 -1.6169,-13.45186 -0.6689,-9.40111 1.4723,-13.19364 7.7654,-13.75441 2.1828,-0.1945 5.4548,-0.76039 9.7573,-1.6874 0.9379,-0.20208 2.2594,-0.4594 2.9367,-0.57184 2.6892,-0.44638 6.2309,-1.16444 7.5785,-1.5365 2.4255,-0.66961 2.6028,-0.73581 6.6313,-2.47614 1.8571,-0.8023 2.9351,-1.4068 5.9207,-3.31997 1.6016,-1.02635 2.6472,-2.51542 1.7661,-2.51542 -0.348,0 -2.9272,0.69728 -6.1711,1.66843 -1.4068,0.42115 -2.9415,0.82206 -3.4103,0.89092 -0.4689,0.0689 -1.3216,0.24216 -1.8947,0.38513 -0.9428,0.23514 -2.3933,0.47904 -7.9575,1.33787 -10.0538,1.55184 -18.2839,1.72407 -26.1458,0.54715 -6.6202,-0.99103 -8.5693,0.97199 -7.6202,7.67506 0.1253,0.88573 0.3115,3.01719 0.4135,4.73656 0.3952,6.65485 1.0277,14.16501 1.4201,16.86219 0.5264,3.61822 1.2554,8.01942 1.355,8.18059 0.046,0.0736 0.2948,1.35375 0.554,2.8447 0.2591,1.49093 0.6862,3.86177 0.9489,5.26853 0.2627,1.40676 0.6054,3.32507 0.7616,4.26291 0.2589,1.55653 0.579,3.09324 1.598,7.67325 0.197,0.88574 0.4557,2.16461 0.5748,2.84195 0.1191,0.67732 0.2962,1.44546 0.3937,1.70696 0.1761,0.47274 0.7343,2.93123 1.5695,6.9136 0.2404,1.14625 0.6531,2.76615 0.9173,3.59979 0.2641,0.83364 0.6689,2.19777 0.8996,3.03141 0.2308,0.83364 0.5702,1.85676 0.7545,2.27362 0.1841,0.41686 0.3991,1.0563 0.4778,1.42097 0.079,0.36468 0.2641,0.89997 0.412,1.18952 0.148,0.28955 0.6399,1.95209 1.0933,3.69452 0.4533,1.74244 1.054,3.76488 1.3348,4.49431 0.281,0.72943 0.8937,2.47723 1.3617,3.88399 1.0628,3.19377 3.3308,9.04569 4.0485,10.44531 0.087,0.16998 0.5568,1.27834 1.0435,2.46303 0.4868,1.18467 0.9471,2.23922 1.0228,2.34342 0.076,0.1042 0.2529,0.48786 0.3939,0.85258 0.8084,2.09342 3.8715,8.00474 5.4128,10.44628 0.2514,0.39847 0.4573,0.77535 0.4573,0.83747 0,0.0622 0.4065,0.7246 0.9033,1.47211 0.4969,0.74753 1.008,1.57228 1.1358,1.83278 0.1277,0.26052 0.6705,1.15573 1.206,1.98937 0.5357,0.83364 1.1902,1.89936 1.4546,2.36828 0.7343,1.30211 5.185,7.96679 6.3853,9.56157 1.6458,2.18686 3.7314,3.6869 3.4242,2.46288 z"
|
||||
id="path21264" /><path
|
||||
style="display:inline;fill:#812973;fill-opacity:1;stroke-width:0.71608"
|
||||
d="m -1194.7853,-780.1521 c 2.1923,-2.10664 6.1213,-7.42853 8.2772,-11.21191 0.9164,-1.6081 1.2324,-2.11477 3.3378,-5.35124 3.1986,-4.91726 4.0506,-6.37827 6.2424,-10.70465 1.2935,-2.55301 2.5372,-5.06813 2.7642,-5.58915 0.2267,-0.52102 0.6849,-1.58675 1.0181,-2.36829 0.3332,-0.78154 0.7553,-1.76201 0.938,-2.17883 1.3324,-3.0396 2.8522,-6.98255 4.5276,-11.74669 1.0884,-3.09505 2.9791,-9.18527 3.1469,-10.13627 0.065,-0.36471 0.2725,-1.17467 0.4626,-1.79989 0.4298,-1.41305 1.4193,-4.70962 1.905,-6.34702 0.2009,-0.67732 0.4933,-1.78568 0.6497,-2.46301 0.1564,-0.67733 0.5031,-2.12672 0.7703,-3.22087 0.6395,-2.61793 2.0454,-8.97072 2.8511,-12.88348 0.354,-1.71938 0.7344,-3.42453 0.8452,-3.78926 0.4172,-1.37282 2.0398,-10.61296 2.1958,-12.50455 0.056,-0.67733 0.3076,-2.38249 0.5593,-3.78925 0.2515,-1.40677 0.5434,-3.36771 0.6485,-4.35766 0.1049,-0.98994 0.3567,-2.78036 0.5593,-3.97872 3.8712,-22.89397 2.8792,-26.41354 -6.9973,-24.82731 -6.2063,0.99676 -20.7722,0.69409 -27.3774,-0.56888 -1.0197,-0.19496 -3.9937,-0.74938 -6.4418,-1.20083 -0.8336,-0.15375 -2.6666,-0.45883 -4.0733,-0.67797 -1.4069,-0.21915 -2.8136,-0.47608 -3.1262,-0.57097 -0.6394,-0.19409 -3.6538,-0.86857 -4.593,-1.0277 -0.5731,-0.0971 -0.5986,-0.079 -0.3807,0.26981 0.1284,0.20564 0.2862,0.37389 0.3507,0.37389 1.2035,0 2.0655,3.24173 19.3064,8.15076 4.2795,1.20844 9.0922,1.94859 15.3141,2.35516 3.6958,0.2415 5.2294,0.8093 6.5163,2.41246 2.4232,3.01901 2.6974,7.10045 1.3091,19.47976 -0.2045,1.82358 -0.4691,4.38133 -0.588,5.68389 -0.455,4.98503 -1.3988,11.55273 -2.287,15.91489 -0.3077,1.51097 -0.8137,4.0261 -1.1245,5.58916 -0.5784,2.90983 -1.8205,8.92228 -2.368,11.4625 -0.1684,0.78154 -0.3837,1.87182 -0.4782,2.42286 -0.221,1.28722 -0.9407,4.61225 -1.0302,4.75902 -0.038,0.0618 -0.3814,1.64709 -0.7638,3.52278 -0.8278,4.06011 -1.1576,5.29252 -3.4222,12.78873 -0.1417,0.46894 -0.5258,1.74781 -0.8534,2.84195 -0.3277,1.09416 -0.7524,2.45829 -0.9438,3.03141 -0.1912,0.57312 -0.6471,1.97988 -1.0131,3.12614 -0.366,1.14625 -1.1018,3.27771 -1.6353,4.73657 -0.5334,1.45886 -1.3009,3.63295 -1.7055,4.83131 -2.2837,6.76422 -3.7336,10.3713 -5.854,14.56423 -1.6135,3.19059 -1.4241,2.87254 -4.4717,7.5082 -0.959,1.45886 -2.0711,3.20665 -2.471,3.88399 -0.4,0.67732 -0.7751,1.27413 -0.8336,1.32623 -0.1404,0.12514 -0.7091,1.08138 -1.0883,1.83004 -0.673,1.32864 0.2121,1.59478 1.4257,0.42866 z"
|
||||
id="path21262" /><path
|
||||
style="display:inline;fill:#000000;fill-opacity:1;stroke-width:0.71608"
|
||||
d="m -1273.7037,-977.54923 c -0.772,-0.47069 -1.0237,-0.8741 -1.7784,-2.85028 -2.3054,-6.03708 -11.9745,-9.16172 -18.1556,-5.8672 -2.0578,1.09679 -4.9207,4.85312 -5.3221,6.01429 -0.6057,1.75171 -1.9555,3.17543 -3.3116,1.81937 -0.529,-0.52902 -0.021,-3.8741 0.9303,-6.13066 5.9705,-14.15649 23.3562,-13.47962 29.0968,1.13279 0.4222,1.0744 1.1272,4.11765 1.1325,4.88772 0.01,1.10354 -1.4779,1.67321 -2.5919,0.99397 z"
|
||||
id="path21275" /><path
|
||||
style="display:inline;fill:#000000;fill-opacity:1;stroke-width:0.71608"
|
||||
d="m -1354.8435,-977.87889 c -1.6707,-1.43007 -0.6421,-5.87088 2.361,-10.19386 7.0117,-10.09294 18.5658,-9.86933 25.6798,0.497 2.0724,3.01978 3.6886,8.04135 2.877,8.93823 -1.0773,1.19052 -2.6788,0.56325 -3.0747,-0.28432 -0.5216,-1.11631 -2.4548,-4.72705 -4.3919,-6.25286 -7.586,-5.97524 -17.0614,-3.29825 -20.7104,5.85112 -0.6548,1.64176 -1.0982,2.14494 -1.8903,2.14494 -0.017,0 -0.4005,-0.31511 -0.8505,-0.70025 z"
|
||||
id="path21274" /><path
|
||||
style="display:inline;fill:#000000;fill-opacity:1;stroke-width:0.71608"
|
||||
d="m -1314.6853,-934.56573 c 0,0.0665 -3.1068,-0.30747 -4.912,-0.52467 -0.1929,-0.0232 -0.9132,-0.13398 -1.6947,-0.29027 -1.2597,-0.25194 -1.3953,-0.2116 -3.1507,-0.83734 -0.3125,-0.11144 -1.421,-0.47049 -2.463,-0.7979 -9.4379,-2.96537 -18.6541,-11.35821 -21.1051,-19.21954 -1.2012,-3.85268 -0.8806,-4.07451 3.5747,-2.47362 0.7788,0.27982 2.1003,0.58344 2.9366,0.67473 0.8365,0.0913 1.8193,0.25162 2.184,0.3563 0.3647,0.10469 1.6436,0.31785 2.8419,0.47371 1.1984,0.15586 2.7757,0.40839 3.5052,0.56117 0.7294,0.15278 2.3283,0.37049 3.5529,0.48379 1.2247,0.1133 2.8445,0.33866 3.5997,0.5008 0.7552,0.16213 2.0552,0.32707 2.8888,0.36656 0.8338,0.0394 2.283,0.12906 3.2209,0.19907 4.655,0.34753 16.2868,0.0317 20.9357,-0.56822 1.1983,-0.15468 2.7329,-0.28504 3.4103,-0.28969 0.6773,-0.005 1.9562,-0.13871 2.8419,-0.29788 0.8858,-0.15919 3.0598,-0.53911 4.8314,-0.84429 2.3425,-0.40355 3.7375,-0.75702 5.1155,-1.29615 2.3947,-0.93695 2.9873,-1.06659 3.5413,-0.77474 2.9049,1.53048 -3.8173,13.28525 -9.9576,17.412 -0.5071,0.34075 -1.4846,1.04554 -2.1725,1.56619 -1.9371,1.46617 -5.0104,2.90117 -7.7997,3.64196 -0.6774,0.17988 -1.5749,0.44618 -1.9945,0.59178 -0.4195,0.1456 -1.6558,0.44242 -2.7472,0.6596 -1.7204,0.34234 -2.8441,0.46959 -6.9103,0.78248 -0.4169,0.0321 -2.2499,0.007 -4.0735,-0.0558 z"
|
||||
id="path21273" /><path
|
||||
id="path21276-14"
|
||||
style="display:inline;fill:#6d2361;fill-opacity:1;stroke-width:0.720242"
|
||||
d="m -1245.0685,-1055.6205 a 86.1772,81.849525 0 0 1 -25.2215,20.4684 c 1.3705,1.0078 2.5102,1.8362 3.7749,2.8552 0.5487,0.4422 1.3363,1.1592 1.8065,1.6 0.4702,0.441 1.0743,0.9732 1.9413,1.6682 1.6057,1.2868 2.1849,1.7488 2.7438,2.126 1.2474,0.8413 1.6524,1.6882 2.4775,0.8079 v 0 c 0.6031,-0.6437 0.9274,-1.0717 1.8354,-2.4244 0.8999,-1.3407 4.7148,-8.3481 5.1155,-9.3968 0.141,-0.3689 0.319,-0.7571 0.3957,-0.8625 0.077,-0.1054 0.447,-1.0111 0.8233,-2.0126 0.3763,-1.0014 0.8464,-2.252 1.0446,-2.7792 1.3959,-3.7118 2.4649,-7.8224 3.263,-12.0539 z m -133.0717,2.3338 c 0.8022,4.0023 1.9581,8.1841 2.9725,10.4828 0.2326,0.527 0.526,1.3033 0.652,1.725 0.3682,1.2319 0.7939,2.2039 1.6375,3.7375 0.4348,0.7906 0.9873,1.9318 1.2278,2.5356 0.2404,0.6038 0.9998,1.8114 1.6878,2.6833 1.5618,1.9797 2.3012,3.3632 2.9503,4.1981 1.6195,2.0828 1.8125,2.3532 4.1571,-0.086 1.0457,-1.0876 2.7113,-2.6246 3.7012,-3.4157 0.99,-0.791 1.9279,-1.5619 2.0841,-1.713 0.4811,-0.4653 1.4143,-1.1458 2.534,-1.8984 a 86.1772,81.849525 0 0 1 -23.6043,-18.2495 z" /><path
|
||||
id="path21276-1"
|
||||
style="display:inline;fill:#985289;fill-opacity:1;stroke-width:0.71608"
|
||||
d="m -1311.1821,-1147.2592 c -3.2889,3e-4 -6.5629,0.2086 -8.2398,0.6244 -0.5732,0.1427 -1.4257,0.352 -1.8946,0.4651 -1.9029,0.459 -5.2315,1.3853 -5.5514,1.5449 -0.1878,0.093 -0.9749,0.336 -1.7488,0.5388 -0.7741,0.2026 -1.7713,0.5687 -2.2163,0.8131 -0.445,0.2442 -1.421,0.6748 -2.1688,0.9568 -0.7479,0.2821 -1.4149,0.7081 -1.5986,0.8004 -1.0377,0.5217 -2.6866,1.1878 -3.5783,1.7038 -0.469,0.2712 -1.5773,0.8797 -2.4631,1.3521 -0.8857,0.4724 -1.7382,0.9637 -1.8946,1.092 -0.1563,0.1282 -1.3925,0.9408 -2.7473,1.8058 -2.5194,1.6087 -4.4043,3.0459 -6.909,5.2684 -0.7789,0.6911 -1.8449,1.6336 -2.369,2.0943 -1.4987,1.3175 -5.6597,5.6042 -7.4852,7.7114 -3.0994,3.5774 -6.0728,8.0025 -8.1759,12.0368 0.5837,-0.6509 1.1617,-1.3213 1.7548,-1.9282 2.0589,-2.1073 6.752,-6.394 8.4421,-7.7114 0.5912,-0.4607 1.7935,-1.4034 2.6718,-2.0945 2.8249,-2.2223 4.9508,-3.6595 7.7924,-5.2683 1.5279,-0.865 2.9218,-1.6777 3.098,-1.8058 0.1763,-0.1282 1.1381,-0.6197 2.1371,-1.092 0.9989,-0.4725 2.249,-1.0808 2.7779,-1.3522 1.0056,-0.516 2.865,-1.182 4.0353,-1.7036 0.2072,-0.092 0.9593,-0.5183 1.8028,-0.8004 0.8435,-0.2821 1.9442,-0.7128 2.446,-0.957 0.5019,-0.2443 1.6268,-0.6102 2.4997,-0.813 0.8729,-0.2027 1.7606,-0.4451 1.9724,-0.5388 0.3607,-0.1596 4.115,-1.0859 6.2611,-1.5449 0.5289,-0.1131 1.4902,-0.3225 2.1367,-0.4651 3.7823,-0.8314 14.7699,-0.8337 18.6867,0 5.0249,1.125 9.8346,2.5794 14.4992,4.5533 11.4814,4.1533 22.6764,11.7898 33.1545,22.6161 0.3957,0.4087 0.7633,0.8274 1.1441,1.2415 -2.0368,-3.9403 -4.5999,-7.7496 -7.6894,-11.3498 -9.2906,-10.8261 -19.2173,-18.463 -29.3975,-22.6163 -4.1359,-1.9739 -8.4004,-3.4283 -12.8557,-4.5533 -1.7365,-0.4169 -5.0404,-0.6246 -8.3293,-0.6244 z" /></g></g></svg>
|
||||
|
After Width: | Height: | Size: 67 KiB |
@@ -308,11 +308,28 @@ def generate_fake_data(
|
||||
# Select random IPs from the pool
|
||||
selected_ips = random.sample(FAKE_IPS, min(num_ips, len(FAKE_IPS)))
|
||||
|
||||
for ip in selected_ips:
|
||||
app_logger.info(f"\nGenerating data for IP: {ip}")
|
||||
# Create a varied distribution of request counts for better visualization
|
||||
# Some IPs with very few requests, some with moderate, some with high
|
||||
request_counts = []
|
||||
for i in range(len(selected_ips)):
|
||||
if i < len(selected_ips) // 5: # 20% high-traffic IPs
|
||||
count = random.randint(1000, 10000)
|
||||
elif i < len(selected_ips) // 2: # 30% medium-traffic IPs
|
||||
count = random.randint(100, 1000)
|
||||
else: # 50% low-traffic IPs
|
||||
count = random.randint(5, 100)
|
||||
request_counts.append(count)
|
||||
|
||||
random.shuffle(request_counts) # Randomize the order
|
||||
|
||||
for idx, ip in enumerate(selected_ips):
|
||||
current_logs_count = request_counts[idx]
|
||||
app_logger.info(
|
||||
f"\nGenerating data for IP: {ip} ({current_logs_count} requests)"
|
||||
)
|
||||
|
||||
# Generate access logs for this IP
|
||||
for _ in range(logs_per_ip):
|
||||
for _ in range(current_logs_count):
|
||||
path = random.choice(FAKE_PATHS)
|
||||
user_agent = random.choice(FAKE_USER_AGENTS)
|
||||
is_suspicious = random.choice(
|
||||
@@ -358,7 +375,7 @@ def generate_fake_data(
|
||||
if cred_id:
|
||||
total_credentials += 1
|
||||
|
||||
app_logger.info(f" ✓ Generated {logs_per_ip} access logs")
|
||||
app_logger.info(f" ✓ Generated {current_logs_count} access logs")
|
||||
app_logger.info(f" ✓ Generated {credentials_per_ip} credential attempts")
|
||||
|
||||
# Fetch geolocation data from API
|
||||
|
||||