Python · SQL · Web Dev · Java · AI/ML tracks launching soon — your one platform for all of IT

FTP, FTPS, and SFTP

From the original two-channel design of FTP to the encrypted simplicity of SFTP: how file transfer protocols work, why FTP is dangerous, and what to use in 2026.

25–35 min May 2026
Chapter 1

The Protocol That Predates Encryption

1971. The ARPAnet has around 23 nodes. Abhay Bhushan publishes RFC 114 — the first File Transfer Protocol. The internet's design philosophy at the time: trust your neighbours, encryption is someone else's problem. FTP was built to solve a real problem — moving files between incompatible time-sharing systems — and it worked. It worked so well that 50 years later, millions of systems still run it. The problem? The world it was designed for no longer exists.

FTP defined the baseline for file transfer: separate control and data channels, a text-based command protocol, and a small vocabulary of operations (get, put, list, delete). Every subsequent file transfer protocol either built on FTP semantics or explicitly reacted against FTP's weaknesses.

Understanding FTP is not just archaeology. It is the prerequisite for understanding why FTPS, SFTP, and SCP were designed the way they were, and why they make the different choices they do.

WOW: FTP's RFC 959 (1985) has not been formally deprecated despite being 40 years old. It is still technically a "full standard" in the IETF standards track. The US NIST and NCSC have both recommended against using FTP over untrusted networks since at least 2009, but the RFC itself lives on.

Chapter 2

FTP: Two Channels, One Design Mistake

Most network protocols use a single TCP connection. FTP uses two: a long-lived control channel for commands, and a short-lived data channel for each transfer. This design made sense in 1971 — it separated signaling from data cleanly. But it created a firewall nightmare and, combined with the total lack of encryption, made FTP the worst protocol still in common use.

The Control Channel (Port 21)

The control channel is a persistent TCP connection to port 21 on the server. Commands (USER, PASS, LIST, RETR, STOR) and responses (3-digit numeric codes like 220, 331, 230) flow over this channel as ASCII text for the lifetime of the session. The control channel stays open even while file data is transferring on a separate connection.

The Data Channel: Active vs. Passive Mode

This is where FTP's fundamental complexity lives. To transfer a directory listing or a file, FTP must open a second TCP connection — the data channel. There are two modes:

Active Mode (PORT)

In active mode, the server initiates the data connection. The client sends a PORT command specifying its IP address and a port it is listening on. The server then connects from its port 20 to the client's specified port. Problem: most clients are behind NAT/firewalls that block inbound connections. Active mode is essentially broken in modern internet environments.

Passive Mode (PASV)

In passive mode, the client initiates both connections. The client sends PASV. The server responds with an IP:port for the client to connect to. The client makes a second TCP connection to that address for data. This works through client-side firewalls but requires the server to open a range of high ports — typically 49152–65535 — in the firewall. NAT devices still need to track the embedded IP in the PASV response (FTP Application Layer Gateways handle this).

# Active mode data channel:
Client: PORT 192,168,1,100,204,98     # client IP + port 52322
Server: connects FROM :20 TO client:52322
# Firewall must allow inbound TCP to client (breaks NAT)

# Passive mode data channel:
Client: PASV
Server: 227 Entering Passive Mode (192,168,1,1,195,149)
# Port = 195*256 + 149 = 50069
Client: connects TO server:50069
# Server's firewall must allow inbound to port 50069

FTP Response Codes

FTP responses are three-digit codes where the first digit indicates category: 1xx (positive preliminary — action started), 2xx (positive completion), 3xx (positive intermediate — more input needed), 4xx (transient negative — retry may succeed), 5xx (permanent negative).

Common codes: 220 (service ready), 331 (password required), 230 (login success), 150 (data channel opening), 226 (transfer complete), 425 (can't open data connection), 530 (not logged in).

FTP Session Walkthrough (Passive Mode)

Click any step to see what it means. Yellow = data channel, white = control channel.

C ClientS ServerData channel
1S220 FTP server ready
2CUSER alice
3S331 Password required
4CPASS s3cr3t!
5S230 User logged in
6CTYPE I
7S200 Type set to I
8CPASV
9S227 Entering Passive (192,168,1,1,195,149)
10CRETR report.pdf
11S150 Opening BINARY mode data connection
12S[binary file data transfer]
13S226 Transfer complete
14CQUIT
15S221 Goodbye

Anonymous FTP

Many public FTP servers historically allowed anonymous access — username anonymous, password is your email address (convention, not enforced). Anonymous FTP was the primary distribution mechanism for open-source software before the web. ftp.gnu.org, kernel.org, and university mirrors all ran anonymous FTP. HTTP/HTTPS largely replaced it in the 2000s.


Chapter 3

Why FTP is Dangerous

A security researcher sets up a packet capture on a coffee shop Wi-Fi network. Within 20 minutes, they capture three FTP sessions — all including usernames and passwords in plaintext. The targets: a web developer uploading files to their hosting provider, a small business syncing inventory to an FTP-based ERP system, and a WordPress plugin updater. None of them knew their credentials were visible to anyone on the same network.

Cleartext Credential Transmission

USER and PASS commands are sent as ASCII text over TCP. Any network observer — on the same LAN segment, a compromised router, a malicious ISP, a coffee-shop attacker — can read your username and password. There is no optional encryption mode in plain FTP.

Cleartext Data Transmission

All file data transfers over the data channel without any encryption. If you upload a database export, a source code archive, or confidential documents via FTP, every byte is readable to network observers.

No Server Authentication

Plain FTP has no mechanism to verify that the server you connected to is the server you intended to connect to. An attacker with control of DNS or ARP can redirect your FTP client to a malicious server that collects your credentials and proxies the real server.

PORT Bounce Attack

In active mode, the PORT command specifies a destination IP and port for the server to connect to. An attacker could use an FTP server as a TCP proxy by issuing PORT commands pointing at third-party hosts — the server would then make connections on behalf of the attacker. Modern FTP servers mitigate this by refusing PORT commands that specify a different IP from the control channel source, but legacy servers remain vulnerable.

WARN: Do not use plain FTP for anything other than anonymous public downloads from trusted servers on networks you control. For any scenario involving authentication or sensitive data, use SFTP or FTPS.

Chapter 4

FTPS: FTP Over TLS

In the late 1990s, as SSL matured and FTP's security problems became undeniable, the IETF needed a way to secure FTP without breaking every existing FTP client and server. The solution: add TLS as a layer. RFC 2228 (1997) and later RFC 4217 (2005) define two modes of FTP over TLS, confusingly named Explicit and Implicit.

Explicit FTPS (FTPES)

Explicit FTPS starts with a plain FTP connection to port 21. The client then issues the AUTH TLS command to upgrade the control channel to TLS. This is analogous to SMTP's STARTTLS. The advantage: backward compatibility — clients that don't support TLS can still connect (though they get no security). The server can be configured to require TLS by rejecting non-TLS sessions.

# Explicit FTPS negotiation on port 21
Client → Server:  [TCP connect to :21]
Server → Client:  220 FTP server ready
Client → Server:  AUTH TLS
Server → Client:  234 AUTH TLS successful
[TLS handshake begins on control channel]
Client → Server:  USER alice       (now encrypted)
Client → Server:  PASS s3cr3t      (now encrypted)
Server → Client:  230 Logged in
Client → Server:  PBSZ 0           (protection buffer size = 0)
Client → Server:  PROT P           (private = encrypt data channel too)
Client → Server:  PASV
Server → Client:  227 Entering Passive (...)
[Client opens encrypted data channel]

Implicit FTPS

Implicit FTPS connects to port 990 and begins TLS immediately — no AUTH TLS command needed. The TLS handshake happens before any FTP commands are exchanged, just like HTTPS vs HTTP. This is simpler but breaks backward compatibility with plain FTP clients. Port 990 is not as widely supported as port 21.

FTPS Data Channel Protection

After securing the control channel, the client must explicitly request data channel encryption with PROT P (private/encrypted). The PBSZ 0 command sets protection buffer size to 0 (required for streaming TLS). If a client omits PROT P, data transfers may still be unencrypted even with an encrypted control channel.

WARN: FTPS still has the two-channel problem. The TLS session on the data channel is separate from the control channel TLS session. Some TLS inspection proxies and firewalls cannot correctly handle the implicit data channel reconnection, causing transfer failures. This is one major reason operators prefer SFTP over FTPS.

Chapter 5

SFTP: Not FTP at All

When SSH was being standardized in the late 1990s, the IETF SSH working group faced a design choice: how to do file transfer securely. They could wrap FTP in SSH (like FTPS wraps FTP in TLS). Instead, they designed a completely new protocol from scratch — the SSH File Transfer Protocol, or SFTP. Despite the similar name, SFTP has nothing to do with FTP. It shares no commands, no wire format, and no design philosophy.

SFTP Architecture

SFTP runs as a subsystem over an SSH connection. When you connect with an SFTP client to port 22, the SSH handshake completes normally, then the client requests the sftp subsystem via an SSH_MSG_CHANNEL_REQUEST. The server spawns sftp-server as a subprocess connected to the channel. All SFTP communication happens as SSH_MSG_CHANNEL_DATA messages within the encrypted SSH session.

The fundamental difference from FTP: one TCP connection, one SSH session, all data encrypted, firewall-friendly. There are no separate data channels, no mode switching, no PORT/PASV negotiation.

SFTP Protocol: Binary, Stateful, Request-Response

Unlike FTP's ASCII command protocol, SFTP is a binary protocol. Each message has a type byte followed by a request-id (allowing pipelining and out-of-order responses) and binary-encoded fields. Operations are stateful: you open file handles (SSH_FXP_OPEN), read/write with handles (SSH_FXP_READ, SSH_FXP_WRITE), then close them (SSH_FXP_CLOSE).

# SFTP message types (binary protocol, not text)
SSH_FXP_INIT (1)        → Client sends protocol version
SSH_FXP_VERSION (2)     ← Server responds with supported version (3–6)
SSH_FXP_OPEN (3)        → Open file handle (flags: read/write/create)
SSH_FXP_CLOSE (4)       → Close handle
SSH_FXP_READ (5)        → Read bytes from open handle
SSH_FXP_WRITE (6)       → Write bytes to open handle
SSH_FXP_LSTAT (7)       → Stat without following symlinks
SSH_FXP_FSTAT (8)       → Stat open handle
SSH_FXP_SETSTAT (9)     → Set file attributes (chmod, times)
SSH_FXP_OPENDIR (11)    → Open directory for listing
SSH_FXP_READDIR (12)    → Read directory entries
SSH_FXP_REMOVE (13)     → Delete file
SSH_FXP_MKDIR (14)      → Create directory
SSH_FXP_REALPATH (16)   → Resolve relative path
SSH_FXP_STAT (17)       → Stat following symlinks
SSH_FXP_RENAME (18)     → Rename/move file
SSH_FXP_STATUS (101)    ← Server status response (ok/error codes)

SFTP Pipelining

SFTP supports request pipelining — the client can send multiple requests without waiting for responses. Each request has a unique 32-bit request-id; responses may arrive in any order and are matched by id. Modern clients like OpenSSH's sftp and paramiko send 64 outstanding requests by default, dramatically improving throughput on high-latency links.

WOW: The reason SFTP transfers feel slow on some links is not the protocol — it is the default window size. SFTP transfers small chunks (32 KB by default) and waits for acknowledgement. Setting a larger transfer buffer (sftp -B 65536) on high-bandwidth links can multiply throughput significantly. On a 100ms latency link, 32KB window = max ~320 KB/s; 64MB window = potential gigabit speed.

SFTP Interactive Command Reference

Filter by category, then click a command to see syntax and example.

ls
List remote directory contents. -l for long format
lls
List LOCAL directory contents. l-prefix commands o
cd
Change remote working directory.
lcd
Change LOCAL working directory.
pwd
Print remote working directory.
get
Download file from remote to local. Optionally ren
mget
Download multiple files matching a glob pattern.
put
Upload file from local to remote. Optionally renam
mput
Upload multiple files matching a glob pattern.
mkdir
Create remote directory.
rm
Delete a remote file.
rmdir
Remove an empty remote directory.
chmod
Change permissions on a remote file.
stat
Show detailed file metadata: size, permissions, ti
rename
Rename or move a remote file.

Chapter 6

SCP: The Simpler Sibling

Before SFTP was widely deployed, the OpenSSH project needed a file copy tool. SCP — Secure Copy Protocol — was the answer: a thin wrapper around the SSH connection that mimicked the behavior of rcp (remote copy) with encryption. SCP was never specified in an RFC; it was simply the OpenSSH implementation. For 20 years it was the default.

SCP Legacy Protocol

The original SCP protocol used a simple in-band signalling mechanism: a single TCP-connected SSH session, where the first byte indicates direction (send or receive), and file data is prefixed by a one-line metadata header. It was simple, fast, and had a critical security flaw: the server could inject arbitrary paths in the metadata header, causing files to land in unexpected locations. This was patched in 2019 (CVE-2019-6111) but the protocol was aging poorly.

Modern SCP Uses SFTP Under the Hood

OpenSSH 9.0 (2022) switched the scp command to use the SFTP protocol internally by default. The command-line interface is unchanged, but the wire protocol is SFTP. This eliminates the path injection vulnerability and provides all of SFTP's benefits while keeping the familiar scp user@host:/path file syntax.

# scp uses SFTP protocol since OpenSSH 9.0
# -O flag forces legacy SCP protocol if needed for old servers
scp -O file.txt oldserver:/path/

# For new servers, just use scp normally (SFTP underneath)
scp -r local_dir/ user@server:/remote/

# Tune SFTP buffer size for performance
scp -l 100000 large_file.iso user@server:/iso/  # limit to 100 kbps
# (Use sftp -B 65536 for larger buffer size control)

rsync over SSH: Delta Transfers

rsync is not a protocol on its own — it is an algorithm for computing file differences and a tool that can use various transports. When used with SSH (rsync -e ssh or simply rsync user@host:/path), rsync runs the rsync daemon on the remote via the SSH channel. The rsync delta algorithm computes rolling checksums of file blocks; only changed blocks are transferred over the wire.

# rsync performance on changed files:
# File: 1 GB, changed 1 MB
# scp transfer: ~1 GB over wire
# rsync transfer: ~1 MB over wire (only the delta)

# This makes rsync ideal for:
# - Incremental backups
# - Deploying website changes (only modified files transferred)
# - Sync large media libraries
# - Mirror package repositories

Chapter 7

Protocol Comparison: When to Use What

A DevOps team is migrating a legacy application that currently uses plain FTP to push deployment artifacts to production servers. They have three options: FTPS (least code change), SFTP (most secure, best compatibility), or rsync over SSH (most efficient for large files). The right answer depends on whether the legacy FTP server can be replaced, the size and change rate of files, and the firewall topology.

File Transfer Protocol Comparator

Select a protocol to compare features and trade-offs.

Port(s)
22 (uses SSH transport)
Encryption
Always — SSH encryption (ChaCha20, AES-GCM)
Auth Methods
SSH public key, password, certificates, GSSAPI
Data Channel
Single SSH session — no separate data channel
Firewall-Friendly?
Excellent — single port 22, works through NAT
Use Case
Modern secure file transfer, automation, cloud storage
Verdict
Recommended for all new deployments

Decision Framework

Use SFTP for: all new deployments, automation that needs to connect through firewalls, environments managed by SSH keys or certificates, cloud-to-cloud or cloud-to-on-prem file transfer.

Use FTPS for: systems with existing FTP infrastructure that can add TLS but cannot be replaced with SFTP (e.g., old Windows FTP servers, EDI trading partners requiring FTP semantics), B2B file exchange where the trading partner mandates FTPS.

Use rsync over SSH for: incremental backups, large file synchronization, website deployments, any scenario where only changed portions of files need to transfer.

Avoid plain FTP: on any network other than a loopback or fully isolated, air-gapped internal network. There is no legitimate reason to use plain FTP on the internet in 2026.


Chapter 8

SFTP Server Configuration

Setting up an SFTP server is straightforward with OpenSSH — it is already installed and the sftp subsystem is enabled by default. The interesting challenges are: restricting users to their home directories (chroot jails), allowing SFTP but not SSH shell access, and managing permissions for service accounts.

SFTP-Only Users (No Shell Access)

A common pattern: create users who can transfer files via SFTP but cannot run a shell. This is done by setting their shell to /usr/sbin/nologin or /bin/false and configuring sshd to use the internal-sftp subsystem with a chroot jail.

# /etc/ssh/sshd_config

# Enable internal-sftp subsystem
Subsystem sftp internal-sftp

# SFTP-only chroot configuration
Match Group sftp-users
    ChrootDirectory /data/sftp/%u    # %u = username
    ForceCommand internal-sftp
    AllowTcpForwarding no
    X11Forwarding no
    AllowAgentForwarding no
# Set up an sftp-only user
useradd -m -s /usr/sbin/nologin -G sftp-users alice
mkdir -p /data/sftp/alice/uploads

# Chroot requires the directory to be owned by root, mode 755
chown root:root /data/sftp/alice
chmod 755 /data/sftp/alice

# User's writable directory
chown alice:alice /data/sftp/alice/uploads
chmod 755 /data/sftp/alice/uploads
WARN: ChrootDirectory ownership rules are strict: the chroot directory and every parent directory must be owned by root with no write permissions for other users. If Alice's chroot is /data/sftp/alice, then /data, /data/sftp, and /data/sftp/alice must all be root:root 755. If any component is writable by the user, the chroot fails with a cryptic "broken pipe" error.

SFTP with Key Authentication

SFTP inherits all SSH authentication methods. For automated transfers, public key auth is standard. The authorized_keys file must be placed at the path OpenSSH expects — which, with a chroot, requires special care: authorized_keys must be at the real (non-chrooted) path, not inside the chroot, unless AuthorizedKeysFile is configured accordingly.

# AuthorizedKeysFile location with chroot
# Default path: %h/.ssh/authorized_keys (%h = user's real home dir)
# With chroot at /data/sftp/alice, the .ssh/authorized_keys
# must be at /home/alice/.ssh/authorized_keys (real path)
# or configure AuthorizedKeysFile /etc/ssh/keys/%u

Chapter 9

Automating File Transfer: Scripts and Libraries

Most production file transfers are automated — CI/CD pipelines deploying artifacts, cron jobs archiving logs, ETL processes ingesting data from trading partners. Each automation needs a reliable SFTP client that handles authentication, error recovery, and often PGP encryption of the files themselves.

sftp Batch Mode

# Run sftp commands from a batch file
sftp -b commands.sftp user@server

# commands.sftp content:
cd /uploads
put /local/export_20260524.csv
ls -la
bye

Python with Paramiko

import paramiko

# Connect and transfer
client = paramiko.SSHClient()
client.load_system_host_keys()
client.set_missing_host_key_policy(paramiko.RejectPolicy())  # Never AutoAdd

client.connect(
    'sftp.partner.com',
    username='transfer_user',
    key_filename='/secrets/sftp_ed25519',
    port=22
)

sftp = client.open_sftp()
sftp.put('/local/report.csv', '/uploads/report.csv')
sftp.close()
client.close()

Node.js with ssh2

const { Client } = require('ssh2');
const fs = require('fs');

const conn = new Client();
conn.on('ready', () => {
  conn.sftp((err, sftp) => {
    if (err) throw err;
    sftp.fastPut(
      '/local/data.csv',
      '/uploads/data.csv',
      { concurrency: 8, chunkSize: 65536 },
      (err) => {
        if (err) throw err;
        conn.end();
      }
    );
  });
}).connect({
  host: 'sftp.partner.com',
  port: 22,
  username: 'transfer_user',
  privateKey: fs.readFileSync('/secrets/id_ed25519'),
  hostVerifier: (key) => key.equals(EXPECTED_HOST_KEY_FINGERPRINT),
});
WARN: Never use RejectPolicy that silently accepts any host key in production automation (equivalent of StrictHostKeyChecking=no). Always pre-load known_hosts or verify the server fingerprint in code. An automated process that accepts any host key is vulnerable to MITM.

Chapter 10

Firewall and NAT Challenges

A network administrator deploys an FTPS server behind a load balancer and NAT. The control channel connects fine. The data channel fails. The PASV response contains the server's private IP (192.168.x.x) instead of the public IP. The client connects to the private IP, which is unreachable from the internet. This misconfiguration costs 3 hours to debug because the error message says nothing about IP addresses in PASV responses.

FTP NAT Problems

The PASV response embeds the server's IP address in the payload: 227 Entering Passive (192,168,1,1,195,149). If the server is behind NAT, this IP is unreachable from the internet. Solutions: configure the FTP server's masquerade_address or pasv_address to return the public IP; or use a FTP Application Layer Gateway (ALG) in the firewall that rewrites the PASV response.

SFTP has none of this complexity. Single TCP connection, single port 22, works through any NAT without special firewall configuration.

Passive Port Ranges

FTPS servers must have a defined passive port range open in the firewall. Common configuration: ports 50000–50100 (or wider). This increases the attack surface compared to SFTP's single-port design.

# vsftpd passive port configuration
# /etc/vsftpd.conf
pasv_enable=YES
pasv_min_port=50000
pasv_max_port=50100
pasv_address=203.0.113.1    # public IP

# Firewall rule
iptables -A INPUT -p tcp --dport 21 -j ACCEPT
iptables -A INPUT -p tcp --dport 50000:50100 -j ACCEPT

SFTP Behind Firewalls

SFTP requires only port 22 inbound to the server. It works through:

— NAT without any special handling (single outbound connection from client)

— Stateful firewalls (one TCP connection, no dynamic port opening needed)

— Load balancers (sticky sessions or connection persistence on port 22)

— Web proxies that support CONNECT tunneling to port 22


Chapter 11

File Transfer Security Best Practices

A data breach post-mortem analysis reveals the initial access vector: a legacy SFTP server that accepted password authentication and had no fail2ban equivalent. An attacker used credential stuffing — testing 50,000 username/password combinations from a public breach database — and hit a valid pair after 8 hours. The company's firewall allowed all inbound TCP to port 22 with no rate limiting.

Authentication Security

For all SSH/SFTP servers: disable password authentication (PasswordAuthentication no), require public key auth. For service accounts: generate a dedicated key pair per service, store the private key in a secrets manager, rotate annually or after any suspected compromise.

Least Privilege Access

Use SFTP chroot jails to restrict users to specific directories. Use the ForceCommand internal-sftp directive to prevent shell access for SFTP-only users. Create per-service accounts rather than sharing credentials.

File Encryption in Transit and at Rest

SFTP/FTPS encrypt in transit. For sensitive data, also consider end-to-end encryption of the files themselves using PGP/GPG. Trading partners can encrypt files with your public PGP key before uploading; you decrypt after download. This protects even if the transport is compromised.

# Encrypt a file for a partner's PGP key before SFTP upload
gpg --recipient partner@company.com --output report.csv.gpg --encrypt report.csv
sftp -b - user@partner-server << 'EOF'
put report.csv.gpg /incoming/
EOF

Logging and Auditing

Enable verbose logging in sshd: LogLevel VERBOSE records every authentication attempt, file operation (with internal-sftp), and disconnection. Ship logs to a SIEM. For SFTP-only servers, internal-sftp logs file operations (open, read, write, close) to syslog — essential for compliance and incident response.


Chapter 12

Modern File Transfer Alternatives

SFTP is excellent but it is not the only answer. Large cloud-native architectures prefer pre-signed URLs over S3 or GCS — no server to maintain, built-in access control, automatic expiry. Enterprise content delivery platforms like MFT (Managed File Transfer) add scheduling, retry logic, non-repudiation, and audit trails on top of SFTP semantics.

S3 Pre-Signed URLs

AWS S3 pre-signed URLs grant time-limited access to upload or download specific objects without AWS credentials. Generate a URL that expires in 15 minutes; share it with a partner; they PUT/GET directly to S3 over HTTPS. No SFTP server required.

# Generate a 15-minute PUT pre-signed URL
aws s3 presign s3://my-bucket/incoming/data.csv   --expires-in 900   --method PUT

# Partner uploads directly:
curl -X PUT --upload-file data.csv "https://my-bucket.s3.amazonaws.com/incoming/data.csv?X-Amz-..."

# For AWS Transfer Family: managed SFTP backed by S3
# - Users connect via SFTP to AWS endpoint
# - Files land in S3 automatically
# - No EC2/server to manage

AWS Transfer Family

AWS Transfer Family provides a managed SFTP/FTPS/FTP endpoint backed by S3 or EFS. Users connect to the endpoint with standard SFTP clients; files appear in S3 buckets. No server management, automatic scaling, built-in CloudWatch metrics. Ideal for B2B file exchange with trading partners who require SFTP without the overhead of running your own server.

Managed File Transfer (MFT) Platforms

Enterprise MFT platforms (GoAnywhere, IBM Sterling, Axway) add business-level features on top of SFTP: scheduled transfers, event-driven workflows, non-repudiation receipts, audit trails, compliance reporting (PCI-DSS, HIPAA), and integration with enterprise directories. They are the right choice when FTP/SFTP is a core business process with regulatory requirements.


Chapter 13

Misconceptions About File Transfer Protocols

MISCONCEPTION: "SFTP is just FTP with encryption." — SFTP and FTP are completely different protocols with no shared design, wire format, or commands. SFTP is a file transfer subsystem of the SSH protocol (RFC draft-ietf-secsh-filexfer). FTP is RFC 959. The only thing they share is the purpose (file transfer) and two letters in the name.
MISCONCEPTION: "FTPS and SFTP are the same thing — both use S for Secure." — FTPS is FTP over TLS (RFC 4217), uses ports 990 or 21, and still has the two-channel architecture with ephemeral data ports. SFTP is SSH File Transfer Protocol, uses port 22, has a single TCP connection, and is not related to FTP. They are completely different protocols that happen to solve the same problem.
MISCONCEPTION: "Passive mode FTP is firewall-friendly." — Passive mode avoids the problem of servers needing to connect back to clients (active mode), but it still requires the server to open a range of ephemeral high ports in its firewall. It is more firewall-friendly than active mode but significantly less friendly than SFTP's single-port design.
MISCONCEPTION: "Moving to SFTP means I don't need to worry about data security." — SFTP encrypts data in transit. If your SFTP server allows password authentication, an attacker can brute-force it. If the files themselves contain sensitive data, they should be encrypted at rest as well. Transport encryption is necessary but not sufficient for a complete data security posture.
MISCONCEPTION: "SCP is deprecated and I should never use it." — The legacy SCP protocol had security issues, and those led to OpenSSH switching the scp command to use SFTP under the hood in version 9.0. The command scp is not deprecated — it is now safer. Only the legacy wire protocol is discouraged. Use scp freely; it now uses SFTP unless you force the old protocol with -O.

Chapter 14

IQ Depth Check: File Transfer Protocol Mastery

Beginner
What is the main difference between FTP and SFTP?
FTP sends all data, including credentials, in plaintext and uses two TCP connections (control on port 21, data on a separate port). SFTP encrypts everything using SSH (port 22), uses a single TCP connection, and is not related to FTP despite the similar name — it is a completely different protocol designed from scratch.
Intermediate
Explain FTP active vs. passive mode and why passive mode is more commonly used today.
In active mode, the server initiates the data connection back to the client — this breaks NAT and client-side firewalls because it requires an inbound connection to the client. In passive mode, the server opens a random high port and tells the client which port to connect to; the client initiates both connections. Passive mode works through client-side NAT and firewalls because all connections are client-initiated. It is more commonly used because most clients are behind NAT/firewalls, but it still requires the server's firewall to allow a range of high ports.
Senior
How does SFTP pipelining work, and why does it matter for performance over high-latency links?
SFTP is a request-response binary protocol where each request has a 32-bit request-id. The client can send multiple requests without waiting for responses — up to a configurable window of outstanding requests (OpenSSH default: 64). Responses arrive with matching request-ids and can be processed out of order. On a high-latency link (e.g., 100ms RTT), without pipelining you are limited to one round-trip per operation: 10 read requests × 100ms = 1 second minimum. With 64 concurrent requests, all 64 can be in flight simultaneously, reducing 64 round-trips to effectively 1. This is why tuning -B (buffer size) on sftp can dramatically improve throughput on WAN links.
PhD
Why does the OpenSSH chroot directory for SFTP need to be owned by root:root with mode 755, and what happens at the kernel level if this requirement is violated?
When sshd performs a chroot(2) syscall to jail an SFTP user, the kernel changes the process's notion of root. POSIX requires that a process doing chroot must be root (CAP_SYS_CHROOT). OpenSSH additionally enforces that the chroot directory and all ancestors are not writable by anyone other than root. The reason: if a user could write to any directory in the chroot path, they could create symlinks that escape the jail via hardlink/symlink race conditions. Specifically, a writable directory allows creating a symlink from a name inside the chroot to an absolute path outside; combined with directory traversal, this breaks the containment. The check is done in session.c (OpenSSH source) via safe_path(), which walks the directory tree verifying owner and mode. If any component fails, sshd logs "bad ownership or modes for chroot directory" and closes the connection — intentionally unhelpful to prevent information disclosure to attackers about the exact failure.

🎯 Key Takeaways

  • FTP uses two TCP channels: a persistent control channel (port 21) and a per-transfer data channel (active: server-initiated; passive: client-initiated to an ephemeral server port).
  • Plain FTP transmits credentials and data in cleartext — never use it on the internet or any untrusted network.
  • FTPS adds TLS to FTP: Explicit FTPS upgrades port 21 with AUTH TLS; Implicit FTPS uses port 990 with immediate TLS. The two-channel architecture remains.
  • SFTP is a completely separate protocol — not FTP with encryption. It runs as an SSH subsystem over a single TCP connection on port 22 with no separate data channel.
  • SFTP is firewall-friendly: single port 22, client-initiated, works through NAT without special configuration.
  • The sftp binary protocol supports pipelining (multiple outstanding requests), enabling high-throughput transfers on high-latency links with appropriate buffer tuning.
  • Modern OpenSSH scp uses SFTP internally (since version 9.0); the legacy SCP protocol had path injection vulnerabilities.
  • rsync over SSH uses delta transfer — only changed file blocks are transmitted — making it ideal for incremental backups and deployments.
  • SFTP chroot jails require the chroot directory and all ancestors to be owned by root with no world/group write permission; sshd performs this check before calling chroot(2).
  • AWS Transfer Family, S3 pre-signed URLs, and MFT platforms are modern alternatives to self-managed SFTP servers for cloud-native and enterprise file transfer.
Share

Discussion

0

Have a better approach? Found something outdated? Share it — your knowledge helps everyone learning here.

Continue with GitHub
Loading...