FTP
Synopsis
Creates an emulated FTP server that logs every authentication attempt, including the cleartext password, without exposing a real system. Only the control channel is emulated — no data connection is ever opened, and post-authentication commands return decoy responses without touching a file system.
Schema
- id: <numeric>
name: <string>
description: <string>
type: ftp
tags: <string[]>
pipelines: <pipeline[]>
status: <boolean>
properties:
address: <string>
port: <numeric>
banner: <string>
max_auth_tries: <numeric>
timeout: <numeric>
credentials:
- username: <string>
password: <string>
Configuration
The following fields are used to define the device:
Device
| Field | Required | Default | Description |
|---|---|---|---|
id | Y | Unique identifier | |
name | Y | Device name | |
description | N | - | Optional description |
type | Y | Must be ftp | |
tags | N | - | Optional tags |
pipelines | N | - | Optional pre-processor pipelines |
status | N | true | Enable/disable the device |
Connection
| Field | Required | Default | Description |
|---|---|---|---|
address | N | "0.0.0.0" | Listen address |
port | Y | Listen port | |
max_auth_tries | N | 3 | Failed authentications per connection before disconnect |
timeout | N | 30 | Idle timeout in seconds |
Appearance
| Field | Required | Default | Description |
|---|---|---|---|
banner | N | "(vsFTPd 3.0.5)" | Greeting text shown after the 220 response code |
Authentication
The credentials property is the list of username/password pairs the honeypot accepts. Every login attempt is logged regardless of the outcome — the list only decides whether the attacker is granted a session afterwards.
| Field | Required | Default | Description |
|---|---|---|---|
credentials | N | - | Accepted username/password pairs. Omit to reject every login. |
credentials[].username | Y | Username to accept. An entry with an empty username is discarded. | |
credentials[].password | N | - | Password to accept. An empty value accepts any password for that username. |
Matching rules:
- Omitted or empty list: no login ever succeeds. Attempts are still logged, so the honeypot keeps collecting credentials without ever handing out a session.
- Empty password: any password is accepted for that username — useful for emulating a service that permits anonymous or unauthenticated access.
- Failed attempts are counted per connection, and the client is disconnected once
max_auth_triesis reached.
Both fields accept plain text, ${ENV_VAR} environment references, and $secret{...} vault tokens.
Credentials configured here are decoys, not access control. Anything an attacker types is written to the event stream in cleartext, including the password. Never reuse a real credential as a honeypot credential.
Details
Emulated Session
The FTP honeypot emulates the control channel only. No data connection is ever opened, no command is ever executed, and no file system is touched.
On connection, the honeypot sends 220 <banner>. USER always answers 331 Please specify the password.; PASS is checked against credentials and answers 230 Login successful. on a match or 530 Login incorrect. otherwise, disconnecting the client once max_auth_tries failures accumulate. QUIT answers 221 Goodbye. and closes the connection. Control lines are capped at 4096 bytes.
A fixed set of decoy commands is answered regardless of authentication state, so scanners and automated clients do not stall:
| Command | Phase | Response |
|---|---|---|
SYST | Any | 215 UNIX Type: L8 |
FEAT | Any | 211 no-features |
OPTS | Any | 200 |
NOOP | Any | 200 |
TYPE | Any | 200 Switching to <arg> mode. |
AUTH | Any | 530 |
PWD | Post-auth | 257 "/" is the current directory |
CWD / CDUP | Post-auth | 250 |
PASV | Post-auth | 502 |
LIST / NLST | Post-auth | 226 Directory send OK. |
RETR / STOR / DELE | Post-auth | 550 Failed to open file. |
| Unrecognized | Post-auth | 200 OK |
Logged Events
Every connection generates one or more of the following event types:
event_type | Emitted when |
|---|---|
auth_attempt | A USER/PASS pair is submitted |
session_open | A session opens after a successful authentication |
session_command | A command is entered on the control channel after authentication |
session_close | The session closes |
Event Fields
Every event carries timestamp, event_type, source_ip, source_port, and local_addr. The remaining fields depend on the event type:
| Field | Description |
|---|---|
username | Username submitted in the attempt |
password | Password submitted in the attempt, in cleartext |
success | Whether the attempt or session matched an accepted credential |
session_id | Identifier of the emulated session |
command | Command entered on the control channel |
argument | Argument string submitted with the command |
Examples
The following are commonly used configuration types.
Basic
Creating a minimal FTP honeypot on the standard port... | |
Anonymous Access
Accepting an anonymous FTP login with any password... | |
With Pre-Processing
Routing captured attempts through a pre-processing pipeline before ingestion... | |
A failed login is logged with the cleartext credential before pipeline processing... | |