This guide explains how to reproduce FTP packets by telnet.
First of all, you need to build ftp server. This time, we use stilliard/pure-ftpd.

Table of Contents

Step 1: Pull the Image

Use this command.

$ docker pull stilliard/pure-ftpd

Step 2: Create the Shared Directory

Create the shared directory and sample file.

$ cd ~/
$ mkdir shared
$ cd $_
$ echo "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum." > lorem.txt

The last command, echo "Lorem ipsum... is to create sample file. You can copy and paste existed files.

Step 3: Create Container

If shared directory is placed at ~/shared, the command is like as below. You can change ieng(Username) and password(password).

$ docker run -d --rm --name ieng -p 21:21 -p 30000-30009:30000-30009 -e "PUBLICHOST=localhost" -e "FTP_USER_NAME=ieng" -e "FTP_USER_PASS=password" -e "FTP_USER_HOME=/mnt" -v ~/shared:/mnt stilliard/pure-ftpd

This container will be removed when it exits because it sets –rm. If you want to continue, run again.

Step 4: Connect to FTP Server by telnet

Connect to FTP server by telnet.

$ telnet localhost 21
Trying ::1...
Connected to localhost.
Escape character is '^]'.
220---------- Welcome to Pure-FTPd [privsep] [TLS] ----------
220-You are user number 1 of 5 allowed.
220-Local time is now 17:29. Server port: 21.
220-This is a private system - No anonymous login
220-IPv6 connections are also welcome on this server.
220 You will be disconnected after 15 minutes of inactivity.

FTP said No anonymous login. Look the packets of assignment. You’ll see the TCP streams like as follows.
The TCP steram of anonymous login
As you see, authentication is required. To authenticate, type username after USER and password after PASS like as follows.

USER ieng
331 User ieng OK. Password required
PASS password
230 OK. Current directory is /

To list directory contents, use LIST.

LIST    
425 No data connection

As you can see, they said error. Modern FTP requires passive mode. Therefore, you need to get the port number to get the response. To get it, use EPSV.

EPSV
229 Extended Passive mode OK (|||30003|)

30003 is port number. The output will show its connection.

Anyway, type LIST.

LIST

The output is nothing and the screen looks freeze. But it’s OK. Open another shell and connect it.

$ telnet localhost 30003
Trying ::1...
Connected to localhost.
Escape character is '^]'.
-rw-r--r--    1 1000       ftpgroup          446 Jul 17 02:12 lorem.txt
Connection closed by foreign host.

You get the directory contents. Back to the shell of telnet localhost 21. Output should be changed.

150 Accepted data connection
226-Options: -l 
226 1 matches total

To download lorem.txt, use RETR.

RETR /lorem.txt

The output is nothing and the screen looks freeze. Open another shell and connect it.

$ telnet localhost 30003
Trying ::1...
Connected to localhost.
Escape character is '^]'.
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
Connection closed by foreign host.

You got the contents of lorem.txt.

Finally, stop the container.

$ docker stop ieng

When you want to retry, follow Step. 3. You can’t docker start ieng.