Metadata-Version: 2.4
Name: trapster
Version: 1.2.2
Summary: Trapster Daemon
Home-page: https://trapster.cloud/
Author: 0xBallpoint
Author-email: contact@ballpoint.fr
License: AGPL3
Keywords: trapster,honeypot,ballpoint,deceptive,security,network
Platform: linux
Classifier: Development Status :: 5 - Production/Stable
Classifier: Intended Audience :: Developers
Classifier: Framework :: AsyncIO
Classifier: Topic :: System :: Networking
Classifier: Topic :: Security
Classifier: Topic :: System :: Networking :: Monitoring
Classifier: Natural Language :: English
Classifier: Operating System :: POSIX :: Linux
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.11
Classifier: License :: OSI Approved :: GNU Affero General Public License v3 or later (AGPLv3+)
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: httpx>=0.27.0
Requires-Dist: psutil>=5.9.8
Requires-Dist: pyasn1>=0.4.8
Requires-Dist: redis>=5.0.4
Requires-Dist: cryptography>=43.0.1
Requires-Dist: asyncssh>=2.14.2
Requires-Dist: scapy>=2.5.0
Requires-Dist: jinja2>=3.1.4
Requires-Dist: PyYAML>=6.0.2
Requires-Dist: fastapi>=0.115.9
Requires-Dist: hypercorn>=0.17.0
Provides-Extra: ai
Requires-Dist: openai<1.99.0; extra == "ai"
Requires-Dist: openai-agents>=0.2.5; extra == "ai"
Dynamic: author
Dynamic: author-email
Dynamic: classifier
Dynamic: description
Dynamic: description-content-type
Dynamic: home-page
Dynamic: keywords
Dynamic: license
Dynamic: license-file
Dynamic: platform
Dynamic: provides-extra
Dynamic: requires-dist
Dynamic: summary

<p align="right">
  <a href="https://trapster.cloud">
    <img src="https://github.com/user-attachments/assets/8b658484-c2ea-4c52-86b5-fe346dc37622" width="25%" alt="Trapster logo" />
  </a>
</p>



<h1 align="center" >Trapster Community </h1>
<p align="center"><a href="https://trapster.cloud/">🌐 Website</a> · <a href="https://docs.trapster.cloud/">📚 Documentation</a> · <a href="https://discord.gg/nNJv8Hj5EE">💬 Discord</a></p>
<br />

Trapster Community is a low-interaction honeypot designed to be deployed on internal networks or to capture credentials. It is built to monitor and detect suspicious activities, providing a deceptive layer to network security.

Visit the [Trapster website](https://trapster.cloud) to learn more about our commercial version, which includes advanced features like pre-configured hardened OS, automatic deployment, webhook, SIEM integration and much more...

## Features

- **Deceptive Security**: Mimics network services to lure and detect potential intruders.
- **Asynchronous Framework**: Utilizes Python's `asyncio` for efficient, non-blocking operations.
- **Configuration Management**: Easily configurable through `trapster.conf`.
- **Expandable Services**: Add and configure as many services as needed with minimal effort.
- **HTTP Honeypot Engine with AI capabilities**: Clone any website using YAML configuration, and use AI to generate responses to some HTTP requests.

## Supported Protocols

| Protocol | Notes |
|----------|-------------|
| FTP (21) | Capture FTP login attempts |
| SSH (22) | Capture SSH login attempts |
| Telnet (23) | Capture TELNET login attempts |
| DNS (53) | Works as a proxy to a real DNS server, and log queries |
| HTTP/HTTPS (80/443) | Copy website, features custom YAML configuration templating engine |
| SNMP (161) | Log SNMP queries |
| LDAP (389) | Capture LDAP login attempts and queries |
| LDAPS (636) | Capture LDAP login attempts and queries over TLS |
| Rsync (873) | Capture RSYNC login attempts |
| MSSQL (1433) | Capture MSSQL login attempts |
| MySQL (3306) | Capture MySQL login attempts |
| RDP (3389) | Capture RDP login attempts |
| PostgreSQL (5432) | Capture POSTGRES login attempts |
| VNC (5900) | Capture VNC login attempts |

## Documentation and installation guide

https://docs.trapster.cloud/community/

## Quick start
Quick start with a demo configuration file:
```bash
git clone https://github.com/0xBallpoint/trapster-community
cd trapster-community
docker compose up --build
```
For a quick start with AI responses for HTTP (port 8081), just add a `.env` file, and run `docker compose up` again:
```
AI_MODEL=o4-mini
AI_BASE_URL=https://api.openai.com/v1/
AI_API_KEY=<YOUR_OPENAI_API_KEY>
```

## Configuration wizard

You can start from the example **`trapster/data/trapster.conf`**, or run the helper script to create **`./trapster.generated.conf`** interactively.

```bash
bash scripts/trapster-wizard.sh
```

From a checkout, with a venv:

```bash
python3 -m venv venv
source venv/bin/activate
pip install -r requirements.txt
bash scripts/trapster-wizard.sh
python main.py -c ./trapster.generated.conf
```

Or install the package in editable mode (`pip install -e .`) and run `trapster -c ./trapster.generated.conf`.

The example configuration listens on well-known ports; binding them usually requires elevated privileges. Run as **root**, or use **`sudo -E`** (keeps your environment, e.g. an activated venv) when starting Trapster with Python.

## Logs

Trapster now separates:

- **format**: how events are structured (`default` or `ecs`)
- **output**: where events are sent (`terminal`, `file`, `api`, `redis`)

This lets you combine them freely, for example:
- default JSON -> terminal
- default JSON -> API
- ECS -> API

### Event types
Each module can generate up to 4 event actions: `connection`, `data`, `login`, and `query`.
- `connection`: a connection has been made to the module
- `data`: raw payload received (hex-encoded in the `data` field)
- `login`: authentication attempt
- `query`: processed protocol request which is not an authentication attempt

### Formats

#### `default`
The original Trapster event structure:
```json
{
  "device": "trapster-1",
  "logtype": "ftp.login",
  "dst_ip": "10.0.0.10",
  "dst_port": 21,
  "src_ip": "10.0.0.50",
  "src_port": 49152,
  "timestamp": "2026-05-08 10:00:00.123456",
  "data": "68656c6c6f",
  "extra": {
    "username": "admin",
    "password": "admin"
  }
}
```

#### `ecs`
Elastic Common Schema format, with protocol details under `trapster.<protocol>.*`:
```json
{
  "@timestamp": "2026-05-08T10:00:00.123456Z",
  "ecs": { "version": "8.11.0" },
  "event": {
    "category": ["authentication", "network"],
    "type": ["start", "info"],
    "action": "login",
    "outcome": "failure",
    "dataset": "trapster.ftp"
  },
  "network": {
    "transport": "tcp",
    "protocol": "ftp",
    "application": "ftp",
    "type": "ipv4"
  },
  "trapster": {
    "raw": "68656c6c6f",
    "login": {
      "username": "admin",
      "password": "admin"
    },
    "ftp": {}
  }
}
```

### Configuration examples

#### 1) Default JSON -> terminal
```json
"logger": {
  "output": "terminal",
  "format": "default",
  "kwargs": {}
}
```

#### 2) ECS -> API
```json
"logger": {
  "output": "api",
  "format": "ecs",
  "kwargs": {
    "url": "https://example.local/ingest",
    "headers": {
      "Authorization": "Bearer <token>"
    }
  }
}
```

#### 3) Default JSON -> file
```json
"logger": {
  "output": "file",
  "format": "default",
  "kwargs": {
    "logfile": "/var/log/trapster-community.log",
    "mode": "a"
  }
}
```

### Retrocompatibility
Existing logger configuration still works (`name` + `kwargs`):
```json
"logger": {
  "name": "JsonLogger",
  "kwargs": {}
}
```

And also:
- `FileLogger`
- `ApiLogger`
- `RedisLogger`
- `EcsLogger`

## HTTP Engine

### Configuration
The HTTP module can emulate any website. It works with YAML configuration files to match requests using regular expressions, and can generate responses using either a template or an AI model.

The configuration are stored in [trapster/data/http](trapster/data/http), each folder represent a website.

`demo_api` ([trapster/data/http/demo_api](trapster/data/http/demo_api)) is a reference skin: every entry in its `config.yaml`
and template exists specifically to demonstrate one capability of the HTTP engine, so it's the
place to look when writing your own. It shows, among others:

- **`http_version: "2"`**: advertise HTTP/2 over ALPN (only takes effect when the skin is served over HTTPS).
- **Custom reason phrases**: override the HTTP/1.1 status line's reason (`reason:`), either a fixed string or a per-request Jinja expression.
- **ETags & conditional GET**: `etag()` generates IIS-style or hashed ETags from a per-deployment seed; a matching `If-None-Match` on a later request gets an automatic `304`.
- **Deploy-time `vars`**: values resolved once at startup from a random per-deployment seed, so they're identical across every request but unique per deployment.
- **Per-request templating**: `.j2` files re-render on every request (`request.form`, `request.query_string`, `uuid()`, `quote` filter, etc.), while inline `content`/`headers` are frozen at startup unless they reference `request`.
- **Static file serving, regex path/query matching, `default`/`errors`/`unknown_method` fallbacks.**

**Structure:**
- config.yaml: contains the configuration for the website.
- files/: contains the static files for the website.
- templates/: contains the templates for the website, it supports [jinja2](https://jinja.palletsprojects.com/en/3.1.x/) syntax.

Documentation : https://docs.trapster.cloud/community/modules/web/

### Example: Fortigate

The default HTTPS server shows a fortigate login page:
![image](https://github.com/user-attachments/assets/5b351089-c7b9-471b-ac33-fcc79454e73c)

If someone tries to login, you will get a log like this one:
```json
{
   "device":"trapster-1",
   "logtype":"https.login",
   "dst_ip":"127.0.0.1",
   "dst_port":8443,
   "src_ip":"127.0.0.1",
   "src_port":45182,
   "timestamp":"2025-02-28 18:53:18.498008",
   "data":"616a61783d3126757365726e616d653d61646d696e267365637265746b65793d61646d696e2672656469723d253246",
   "extra":{
      "method":"POST",
      "target":"/logincheck",
      "headers":{
         "host":"127.0.0.1:8443",
         "connection":"keep-alive",
         "content-length":"47",
         "cache-control":"no-store, no-cache, must-revalidate",
         "sec-ch-ua-platform":"\"Linux\"",
         "pragma":"no-cache",
         "sec-ch-ua":"\"Not(A:Brand\";v=\"99\", \"Google Chrome\";v=\"133\", \"Chromium\";v=\"133\"",
         "sec-ch-ua-mobile":"?0",
         "user-agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/132.0.0.0 Safari/537.3",
         "if-modified-since":"Sat, 1 Jan 2000 00:00:00 GMT",
         "content-type":"text/plain;charset=UTF-8",
         "accept":"*/*",
         "origin":"https://127.0.0.1:8443",
         "sec-fetch-site":"same-origin",
         "sec-fetch-mode":"cors",
         "sec-fetch-dest":"empty",
         "referer":"https://127.0.0.1:8443/login?redir=%2F",
         "accept-encoding":"gzip, deflate, br, zstd",
         "accept-language":"en-US,en;q=0.9"
      },
      "status_code":200,
      "username":"admin",
      "password":"admin"
   }
}
```

## AI support

> **Disclaimer:** AI-generated responses are not a substitute for intrusion detection. A
> motivated attacker can fingerprint them (latency, inconsistent state across requests, subtle
> phrasing) with a handful of probes, so this feature should not be relied on in a defensive or
> production deployment. It's intended for external CTI research, observing attacker tooling and
> behavior against a permissive AI-driven backend, not as a hardened detection control.

<details>
<summary>Show AI support details</summary>

To use AI, install the dependencies:
```bash
pip install trapster[ai]

# or locally
python3 -m pip install ".[ai]" 
```
Then, you need to set your environnement variables. First, copy the `example.env` file
```bash
cp example.env .env
```
Now, you can set:
```
AI_MODEL=
AI_BASE_URL=
AI_API_KEY=
AI_MEMORY_ENABLE=false
# AI_MEMORY_PATH=
```
AI_MEMORY_ENABLE and AI_MEMORY_PATH are optionnal, it allows you to set persistant data between session using a database. Sessions are based on the IP of the user, and the username. 
By default, if you set `AI_MEMORY_ENABLE=true`, then the database will be in `trapster/data/ai_memory.db`

You can also use `OPENAI_API_KEY` directly if you want to use the default `o4-mini` model:
```bash
export OPENAI_API_KEY=... && venv/bin/python3 main.py
```

### AI for SSH
Trapster can generate fake shell responses when user connect to SSH.

To enable AI for SSH, allow the users to connect with username/password combination that you can define in the configuration file `trapster.conf` like :
```
...
 "ssh": [
      {
        "port": 2222,
        "version": "SSH-2.0-OpenSSH_8.1p1 Debian-1",
        "banner": null,
        "users": {
		      "guest":"guest",
            "admin":"admin",
            "ubuntu":"ubuntu",
            "pi":"raspberry",
            "debian":"password"
        }
      }
...
```

### AI for HTTP
To generate responses, you can use the `ai` field in the configuration. It will generate a response for the corresponding URL. You can change the prompt for each URL. This enable to fast, pre-determined responses for the honeypot website, and only AI responses when the URL is unkown.
For example, this image show a request to capture SQLi attempts. Only the SQLi attempts are generated by AI.

<img src="images/sqli_ai_response_1.png" width="60%">

A full example is available in `trapster/data/demo_ai`

</details>

## Contributing

Contributions are welcome! Please follow these steps:

1. Fork the repository.
2. Create a new branch (git checkout -b feature-branch).
3. Make your changes.
4. Commit your changes (git commit -m 'Add new feature').
5. Push to the branch (git push origin feature-branch).
6. Create a pull request.

## License

Trapster is licensed under the GNU Affero General Public License v3 or later (AGPLv3+). See the LICENSE file for more details.

