FTP is the oldest protocol you will still find running in a substation. It moves files between two machines over TCP. That is the whole job. But the way it does the job — two separate connections, plain-text commands, a server that calls you back — trips up more engineers than any other legacy protocol.
This article walks through FTP the way the specification defines it: the two-connection model, active and passive mode, transfer types, the command set, and the reply codes. Then we get practical: why FTP breaks through firewalls, why it fails security audits, and where it still earns its keep in industrial networks.
Table of Contents
The Core Idea: Two Connections, Not One
Most protocols use one TCP connection. FTP uses two, and they do different work.
The control connection carries commands and replies. Your client opens it to TCP port 21 on the server. It stays open for the whole session. Everything you type — login, directory changes, transfer requests — travels here as plain readable text.
The data connection carries the actual file. It opens only when a transfer starts and it usually closes when the transfer ends. Directory listings travel here too, not on the control connection.
The specification splits each side into two roles. The protocol interpreter (PI) handles commands and replies on the control connection. The data transfer process (DTP) handles the data connection. So a full session involves four moving parts: user-PI, server-PI, user-DTP, server-DTP.
Why does this matter in practice? Because the control connection must stay open while data moves. If a firewall or NAT device times out the idle control connection during a long transfer, the server may kill the transfer. That is one of the two classic FTP firewall failures. The other one is bigger, and it comes down to who opens the data connection.
Active vs Passive Mode: Who Calls Whom
This is the part that causes 90% of real-world FTP problems.
Active mode (the original design)
In the original model, the client tells the server where to connect using the PORT command:
PORT 192,168,1,50,195,80
The first four numbers are the client’s IP address. The last two encode the TCP port: 195 × 256 + 80 = 49,920. The client listens on that port. The server then opens the data connection to the client, from its own port 20 (the port next to 21).
Think about that from a firewall’s point of view. An outside machine is opening an inbound connection to a random high port on your internal host. Every stateless firewall blocks it. Every NAT device breaks it, because the client advertises its private IP inside the PORT command payload.
Passive mode (the fix)
The client sends PASV instead. The server picks a port, listens on it, and replies:
227 Entering Passive Mode (10,20,30,40,156,68)
Now the client opens the data connection outbound, to server port 156 × 256 + 68 = 40,004. Outbound connections pass through client-side firewalls without trouble. That is why nearly every modern client defaults to passive mode.
The trade-off moves the problem to the server side: the server firewall must allow inbound connections on a range of high ports. Server admins handle this by pinning the passive port range in the FTP server config and opening exactly that range.
Third-party transfers
The two-connection design allows one thing no modern protocol does cleanly: a client can sit at host C and move a file directly between servers A and B. The client sends PASV to server A, takes the address from the 227 reply, and hands it to server B in a PORT command. Then it sends STOR to one server and RETR to the other. Data flows A-to-B without touching C. This is called FXP today. Most servers disable it because it is also an attack vector (the “FTP bounce” attack).
Transfer Types: ASCII vs Binary
FTP was written for a world where machines disagreed about what a byte was. Some hosts stored text as 7-bit ASCII packed into 36-bit words. Others used EBCDIC. The protocol defines four representation types, set with the TYPE command:
| Type | Code | What it does |
|---|---|---|
| ASCII | TYPE A | Converts text to a standard network form. Line endings become CR+LF on the wire. This is the default. |
| EBCDIC | TYPE E | Same idea, for EBCDIC mainframes. Dead in practice. |
| Image | TYPE I | Raw bits, no conversion. What everyone calls “binary mode.” |
| Local | TYPE L n | Custom logical byte size. Dead in practice. |
The only decision that matters today: A or I.
ASCII mode rewrites line endings. Send a firmware image, a relay settings file, or a COMTRADE .dat file in ASCII mode and the transfer will “succeed” — with a corrupted file. Every 0x0A byte in the binary gets a 0x0D stuffed in front of it. The file size changes. Checksums fail. Firmware loads brick devices.
Rule of thumb: type binary (or TYPE I) before any transfer unless you know the file is plain text and you actually want line-ending conversion. Most modern clients auto-detect, but embedded FTP clients in RTUs and protection relays often do not.
Structures and Modes: The Parts Nobody Uses
The specification defines three file structures (STRU) and three transmission modes (MODE). You should know they exist, because you will see the commands in packet captures, and because the defaults explain some FTP behavior.
Structure: File (F), Record (R), or Page (P). File structure — a plain stream of bytes — is the default and the only one in real use. Record structure existed for mainframes that stored files as fixed records. Page structure existed for TOPS-20 “holey” files. If you see STRU F in a capture, the client is just confirming the default.
Mode: Stream (S), Block (B), or Compressed (C). Stream is the default and the only one in real use. Here is the interesting part: in stream mode with file structure, the only way to signal end-of-file is to close the data connection. That is why FTP opens a fresh data connection for every single transfer. Block mode wrapped data in headers with byte counts and supported restart markers for resuming failed transfers, so it could keep the connection open — but almost nobody implemented it. Modern clients resume transfers a different way, using the REST command with a byte offset plus stream mode.
The Command Set
FTP commands are short plain-text strings, four letters or fewer, terminated by CR+LF. Case does not matter: RETR, retr, and ReTr are the same command. Here are the ones that do the work:
Session and login
USER— usernamePASS— password, sent in clear textACCT— account, rarely requiredQUIT— log out and closeREIN— reset the session without closing the connection
Transfer setup
PORT— active mode: here is my address, connect to mePASV— passive mode: give me an address, I will connect to youTYPE— ASCII or ImageMODE,STRU— practically always at defaults
File operations
RETR— download a fileSTOR— upload a file, overwriting if it existsSTOU— upload with a server-generated unique nameAPPE— upload and appendDELE— delete a fileRNFR+RNTO— rename, always as a pairREST— restart a transfer at a byte offsetABOR— abort the transfer in progress
Directories
CWD— change directoryCDUP— go up one levelPWD— print the current directoryMKD/RMD— make or remove a directoryLIST— full listing, human-readable, format varies by serverNLST— names only, one per line, meant for scripts
Information
SYST— what OS is the server runningSTAT— status of the server or a transferHELP,NOOP,SITE— help text, keep-alive, and server-specific extras
One detail worth knowing: LIST output is not standardized. A UNIX server sends something like ls -l output; other systems send whatever they like. Scripts that parse LIST break when the server changes. NLST exists precisely so automated tools get clean, parseable file names.
Reading Reply Codes
Every command gets at least one numeric reply. The three digits are a small state machine, and once you learn the pattern you can read any FTP session log without a reference.
First digit — how did it go:
- 1yz — started, wait for another reply before sending a new command
- 2yz — done, success
- 3yz — accepted, but send the next command in the sequence (e.g. 331 after USER means “now send PASS”)
- 4yz — failed, temporary; retrying the same command may work
- 5yz — failed, permanent; retrying the same command will not help
Second digit — what area: 0 syntax, 1 information, 2 connections, 3 authentication, 5 file system.
The replies you will actually see:
| Code | Meaning |
|---|---|
| 220 | Service ready — the server greeting |
| 331 | Username OK, need password |
| 230 | Logged in |
| 530 | Not logged in / bad credentials |
| 227 | Entering passive mode (address follows) |
| 150 | Opening data connection, transfer starting |
| 226 | Transfer complete, closing data connection |
| 425 | Can’t open data connection — usually a firewall problem |
| 426 | Connection closed, transfer aborted |
| 550 | File not found or permission denied |
| 421 | Service not available, shutting down |
A clean download reads like this on the control connection:
220 Service ready
USER field_eng → 331 User name okay, need password
PASS ******** → 230 User logged in
TYPE I → 200 Command okay
PASV → 227 Entering Passive Mode (h1,h2,h3,h4,p1,p2)
RETR dr_20260615.cfg → 150 File status okay
→ 226 Closing data connection
QUIT → 221 Service closing control connection
Multi-line replies start with the code and a hyphen (214-Help follows) and end with the same code and a space. Your parser looks for the second occurrence of the code at the start of a line.
The Minimum Implementation
The specification defines a floor every server must meet: TYPE ASCII Non-print, MODE Stream, STRUcture File and Record, and the commands USER, QUIT, PORT, TYPE, MODE, STRU, RETR, STOR, and NOOP. Anything beyond that — including PASV, LIST, and even PASS — is technically optional.
This matters for embedded devices. The FTP server baked into an older RTU, protection relay, or power quality meter often implements little more than this minimum. If your transfer script assumes MKD, MDTM, or SIZE exists, test against the actual device first. Some embedded stacks do not even support passive mode, which forces you back into active-mode firewall rules.
Why FTP Fails Security Audits
FTP predates the idea of a hostile network. Four problems, all structural:
1. Credentials in clear text. USER and PASS cross the wire readable. Anyone with a tap or a SPAN port capture has your password. On a flat OT network, that can be the same password used on twenty other devices.
2. Data in clear text. File contents are readable in transit. Settings files, configurations, event records — all of it.
3. No integrity checking. FTP relies on TCP for bit-level correctness and offers nothing above it. No hash, no signature. You cannot prove the file that arrived is the file that was sent.
4. The bounce attack. The PORT command lets a client tell a server to open a connection to any IP and port. An attacker uses your FTP server as a relay to scan or reach hosts behind it. Modern servers refuse PORT commands pointing at third-party addresses, but embedded stacks may not.
Add the firewall pain: an application-layer gateway must parse the control connection to learn which data ports to open, and that breaks the moment you encrypt the control channel.
FTP vs FTPS vs SFTP
Three names, two protocols, one common confusion.
FTPS is FTP wrapped in TLS. Same commands, same two-connection model, now encrypted. Explicit FTPS starts plain on port 21 and upgrades with an AUTH TLS command. Implicit FTPS uses port 990 and is TLS from the first byte. FTPS fixes the eavesdropping problem but keeps the two-connection firewall problem — and makes it worse, because the firewall can no longer read the PASV replies to open data ports dynamically.
SFTP is not FTP at all. It is a file transfer subsystem running inside an SSH session. One connection, one port (22), encrypted, with integrity built in. From a firewall’s point of view it is the simplest of the three by a wide margin.
Practical guidance: for new deployments, use SFTP. Use FTPS when a counterparty or a legacy toolchain demands the FTP command set with encryption. Use plain FTP only inside a controlled network segment where the risk is understood and documented — which brings us to OT.
Where FTP Still Lives in Industrial Networks
Plenty of field devices shipped with FTP and nothing else. You will meet it when:
- Pulling disturbance records — protection relays exposing COMTRADE files over an embedded FTP server
- Firmware updates — RTUs and gateways that only accept firmware via FTP push
- Retrieving logs and configurations — meters, PQ analyzers, older HMIs and station computers
- Automated collection — a station computer polling devices on a schedule and forwarding files up to the control center
You often cannot replace the device, so you contain the protocol instead:
- Keep FTP inside one network zone. Never let it cross a zone boundary unencrypted — put a secured relay point (SFTP gateway or data diode arrangement) at the conduit.
- Use unique credentials per device, even though they travel in the clear. Shared passwords turn one capture into total compromise.
- Pin the passive port range on any server you control and firewall exactly that range.
- Force binary mode in every script. An ASCII-mode firmware transfer is a bad day.
- Log the control connection. It is plain text — that is a weakness for confidentiality but a gift for monitoring. Every command and reply is auditable.
Quick Reference
- Control connection: TCP port 21, stays open all session
- Data connection: port 20 in active mode, negotiated high port in passive mode
- Default settings: TYPE ASCII, MODE Stream, STRU File
- Switch to binary with
TYPE Ibefore any non-text transfer - 2xx replies mean success, 4xx retry later, 5xx don’t bother
- 425 almost always means a firewall is blocking the data connection
- FTPS = FTP over TLS; SFTP = a different protocol over SSH
FAQ
What port does FTP use?
Port 21 for the control connection. In active mode the server sends data from port 20. In passive mode the server assigns a high port for each transfer and tells the client in the 227 reply.
What is the difference between active and passive FTP?
In active mode the server opens the data connection to the client. In passive mode the client opens the data connection to the server. Passive mode is the default in modern clients because client-side firewalls block inbound connections.
Why did my FTP transfer corrupt the file?
Almost certainly ASCII mode. The default transfer type converts line endings, which rewrites bytes inside binary files. Send TYPE I (binary) before transferring firmware, images, archives, or measurement data.
Is FTP secure?
No. Usernames, passwords, and file contents all travel as readable text, and the protocol has no integrity checking. Use SFTP or FTPS on any network you do not fully control.
What is the difference between SFTP and FTPS?
FTPS is classic FTP with TLS encryption added — same commands, same two connections. SFTP is a separate protocol that runs over SSH on port 22 with a single connection. They are not interoperable.
Why does my firewall block FTP?
FTP negotiates a second connection on a dynamic port, and the address is carried inside the protocol payload. Stateless firewalls and NAT devices can’t track it. Fixes: use passive mode, enable FTP inspection on the firewall, or pin the server’s passive port range and open it explicitly.
What does reply code 550 mean?
Permanent failure at the file level: the file does not exist, or you lack permission. Check the path, the case of the file name, and your account’s access rights.
Can FTP resume a broken transfer?
Yes, if the server supports REST. The client sends REST <byte offset> followed by RETR or STOR, and the transfer continues from that point.
