Skip to main content

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

FieldRequiredDefaultDescription
idYUnique identifier
nameYDevice name
descriptionN-Optional description
typeYMust be ftp
tagsN-Optional tags
pipelinesN-Optional pre-processor pipelines
statusNtrueEnable/disable the device

Connection

FieldRequiredDefaultDescription
addressN"0.0.0.0"Listen address
portYListen port
max_auth_triesN3Failed authentications per connection before disconnect
timeoutN30Idle timeout in seconds

Appearance

FieldRequiredDefaultDescription
bannerN"(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.

FieldRequiredDefaultDescription
credentialsN-Accepted username/password pairs. Omit to reject every login.
credentials[].usernameYUsername to accept. An entry with an empty username is discarded.
credentials[].passwordN-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_tries is reached.

Both fields accept plain text, ${ENV_VAR} environment references, and $secret{...} vault tokens.

warning

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:

CommandPhaseResponse
SYSTAny215 UNIX Type: L8
FEATAny211 no-features
OPTSAny200
NOOPAny200
TYPEAny200 Switching to <arg> mode.
AUTHAny530
PWDPost-auth257 "/" is the current directory
CWD / CDUPPost-auth250
PASVPost-auth502
LIST / NLSTPost-auth226 Directory send OK.
RETR / STOR / DELEPost-auth550 Failed to open file.
UnrecognizedPost-auth200 OK

Logged Events

Every connection generates one or more of the following event types:

event_typeEmitted when
auth_attemptA USER/PASS pair is submitted
session_openA session opens after a successful authentication
session_commandA command is entered on the control channel after authentication
session_closeThe 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:

FieldDescription
usernameUsername submitted in the attempt
passwordPassword submitted in the attempt, in cleartext
successWhether the attempt or session matched an accepted credential
session_idIdentifier of the emulated session
commandCommand entered on the control channel
argumentArgument string submitted with the command

Examples

The following are commonly used configuration types.

Basic

Creating a minimal FTP honeypot on the standard port...

devices:
- id: 1
name: basic_ftp
type: ftp
properties:
port: 21

Anonymous Access

Accepting an anonymous FTP login with any password...

devices:
- id: 2
name: ftp_anonymous
type: ftp
properties:
port: 21
credentials:
- username: ftp
password: ""

With Pre-Processing

Routing captured attempts through a pre-processing pipeline before ingestion...

devices:
- id: 3
name: ftp_preprocessed
type: ftp
pipelines:
- decoy-honeypot-enrich
properties:
port: 21

A failed login is logged with the cleartext credential before pipeline processing...

{
"timestamp": "2026-08-03T09:14:22.481937204Z",
"event_type": "auth_attempt",
"source_ip": "203.0.113.44",
"source_port": "51422",
"local_addr": "10.0.4.12:21",
"username": "admin",
"password": "admin123",
"success": false
}