📅 Updated October 2026 ⏱ 18 min read

Complete Guide to SFTP — SSH File Transfer Protocol

Master secure file transfers over SSH: from basic connections to advanced automation, key-based authentication, server hardening, and troubleshooting.

Introduction to SFTP

SFTP, which stands for SSH File Transfer Protocol (sometimes called Secure File Transfer Protocol), is a network protocol that provides secure file access, file transfer, and file management capabilities over any reliable data stream. Despite sharing the "FTP" acronym with the older File Transfer Protocol, SFTP is an entirely different protocol built from the ground up as an extension of the Secure Shell (SSH) protocol. It was designed to address the fundamental security weaknesses inherent in traditional FTP, which transmits data — including usernames and passwords — in plain text across the network.

SFTP was first defined in the late 1990s as part of SSH version 2.0 and has since become the de facto standard for secure file transfers across the internet. Unlike FTP, which requires multiple ports and complex firewall configurations, SFTP operates entirely over a single TCP connection on port 22 — the same port used by SSH. This makes SFTP significantly easier to configure in firewalled environments and dramatically reduces the attack surface compared to FTP or even FTPS (FTP over SSL/TLS).

The core advantage of SFTP is that every aspect of the file transfer session is encrypted — authentication credentials, commands, and data all travel through an encrypted SSH tunnel. This means that even if someone intercepts your network traffic, they cannot read the filenames, file contents, or passwords being transmitted. For organizations handling sensitive data, financial records, healthcare information, or any regulated content, SFTP is often a compliance requirement rather than just a best practice.

💡 SFTP vs FTPS — Don't confuse them!

SFTP and FTPS are completely different protocols. SFTP runs over SSH on port 22 using a single connection. FTPS is traditional FTP with a TLS/SSL encryption layer, still using multiple ports and the legacy FTP command structure. When in doubt, choose SFTP — it is simpler to configure, more firewall-friendly, and provides stronger security guarantees out of the box.

Key Advantages of SFTP Over FTP

  • Full encryption — all data, commands, and credentials are encrypted in transit using strong cryptographic algorithms
  • Single port operation — uses only TCP port 22, eliminating the need for complex firewall rules required by FTP's active/passive modes
  • Built-in authentication — supports password, public key, keyboard-interactive, and multi-factor authentication methods natively
  • Resume support — can resume interrupted transfers without restarting from the beginning
  • File system operations — supports remote directory listing, file permissions, symbolic links, and file locking
  • Platform independent — works across Windows, Linux, macOS, and virtually every modern operating system
  • No separate data channel — unlike FTP which opens separate connections for each transfer, SFTP multiplexes everything over one connection

How SFTP Works

Understanding the internals of SFTP helps you troubleshoot connection issues, optimize transfer performance, and configure servers correctly. SFTP operates as a subsystem of the SSH protocol, which means it piggybacks on an existing SSH connection rather than establishing its own independent protocol handshake.

The SSH Connection Layer

When you initiate an SFTP session, the following sequence occurs under the hood. First, your SFTP client establishes a TCP connection to the remote server on port 22 (the default SSH port). The SSH protocol then performs a key exchange to establish a shared secret, which is used to derive encryption keys for the session. During this exchange, the server presents its host key — a cryptographic fingerprint that uniquely identifies the server. Your client verifies this fingerprint against its known hosts database to prevent man-in-the-middle attacks.

After the transport layer is secured, the authentication phase begins. The client presents credentials — typically a password or a public key signature — to prove its identity. Once authenticated, the client requests the SFTP subsystem, which the SSH server spawns as a child process. From this point forward, all SFTP commands and file data flow through the encrypted SSH channel.

The SFTP Subsystem

The SFTP subsystem is a binary protocol that communicates using structured packets rather than human-readable text commands like FTP. Each packet contains a request ID, a type code (such as SSH_FXP_OPEN, SSH_FXP_READ, SSH_FXP_WRITE), and the associated data payload. This binary design is more efficient than text-based protocols because it eliminates parsing overhead and supports features like pipelining — sending multiple requests without waiting for individual responses.

SFTP supports protocol versions 1 through 6, with version 3 being the most widely implemented and version 6 adding features like file locking and improved error reporting. Most modern servers and clients negotiate version 3 or higher automatically during the initial handshake.

💡 Encryption in action

A typical SFTP session uses AES-256-CTR or ChaCha20-Poly1305 for symmetric encryption, HMAC-SHA2-256 for message integrity, and Curve25519 or RSA-2048+ for key exchange. These algorithms ensure that even nation-state adversaries cannot practically decrypt your file transfers.

Connection Flow Diagram

Client                          Server
  │                               │
  │──── TCP SYN (port 22) ───────►│
  │◄─── TCP SYN-ACK ─────────────│
  │──── TCP ACK ─────────────────►│
  │                               │
  │──── SSH Version Exchange ────►│
  │◄─── SSH Version Exchange ─────│
  │                               │
  │──── Key Exchange Init ───────►│
  │◄─── Key Exchange Reply ───────│
  │──── New Keys ────────────────►│
  │◄─── New Keys ─────────────────│
  │                               │
  │==== Encrypted Channel ========│
  │                               │
  │──── Auth Request ────────────►│
  │◄─── Auth Success ─────────────│
  │                               │
  │──── Channel Open ────────────►│
  │◄─── Channel Confirm ──────────│
  │──── Subsystem: sftp ─────────►│
  │◄─── SSH_FXP_VERSION ──────────│
  │                               │
  │──── SFTP Commands ───────────►│
  │◄─── SFTP Responses ───────────│

Setting Up an SFTP Connection

Windows 10 and later include a built-in OpenSSH client that provides native SFTP support directly from PowerShell or Command Prompt. This eliminates the need to install third-party software for basic SFTP operations. For users who prefer a graphical interface, WinSCP remains the most popular Windows SFTP client, offering drag-and-drop file transfers, session management, and scripting capabilities.

Using Windows Built-in OpenSSH Client

The OpenSSH client is included by default on Windows 10 version 1803 and later. You can verify its installation and connect to a remote server directly from PowerShell:

PowerShell
# Verify OpenSSH client is installed
Get-WindowsCapability -Online | Where-Object Name -like 'OpenSSH.Client*'

# Connect to a remote server via SFTP
sftp [email protected]

# Connect using a specific port
sftp -P 2222 [email protected]

# Connect with verbose output for debugging
sftp -v [email protected]

If the OpenSSH client is not installed, you can add it through PowerShell with administrator privileges:

PowerShell (Administrator)
# Install the OpenSSH Client feature
Add-WindowsCapability -Online -Name OpenSSH.Client~~~~0.0.1.0

# Install the OpenSSH Server (if you want to receive SFTP connections)
Add-WindowsCapability -Online -Name OpenSSH.Server~~~~0.0.1.0

# Start and enable the SSH server service
Start-Service sshd
Set-Service -Name sshd -StartupType 'Automatic'

Using WinSCP for Graphical SFTP

WinSCP is a free, open-source SFTP and SCP client for Windows that provides a graphical interface resembling a two-pane file manager. It supports SFTP, SCP, FTP, FTPS, WebDAV, and S3 protocols. WinSCP also includes a powerful scripting engine and a .NET assembly for integration into custom applications and automation workflows.

To connect with WinSCP, launch the application and enter your server details in the Login dialog: select SFTP as the file protocol, enter your hostname, port number (default 22), username, and password or key file. WinSCP will verify the server's host key on first connection and store it for future sessions. Once connected, you can drag and drop files between your local machine and the remote server, edit files in place, synchronize directories, and manage permissions through the graphical interface.

⚠️ First connection host key verification

When connecting to a server for the first time, both the command-line client and WinSCP will display the server's host key fingerprint and ask you to verify it. Always confirm this fingerprint with your server administrator to prevent man-in-the-middle attacks. Once accepted, the fingerprint is cached locally so you are not prompted again unless the server's key changes — which could indicate a security incident.

SSH Key Authentication

Password authentication is convenient but inherently less secure than key-based authentication. SSH key authentication uses a cryptographic key pair: a private key that stays on your local machine and a public key that is placed on the remote server. When you connect, the server challenges your client to prove it possesses the private key without ever transmitting the key itself. This approach is immune to brute-force password attacks and eliminates the risk of password interception.

Generating an SSH Key Pair on Windows

Windows 10 and later include ssh-keygen as part of the built-in OpenSSH client. You can generate a key pair directly from PowerShell:

PowerShell
# Generate an Ed25519 key pair (recommended — fastest and most secure)
ssh-keygen -t ed25519 -C "yourname@yourmachine"

# Generate an RSA 4096-bit key pair (wider compatibility)
ssh-keygen -t rsa -b 4096 -C "yourname@yourmachine"

# Keys are saved to:
#   Private key: C:\Users\YourName\.ssh\id_ed25519
#   Public key:  C:\Users\YourName\.ssh\id_ed25519.pub

When prompted, you can optionally set a passphrase to protect your private key. A passphrase adds a second layer of security — even if someone obtains your private key file, they cannot use it without the passphrase. For automated scripts, you may choose to skip the passphrase, but for interactive use a strong passphrase is highly recommended.

Deploying Your Public Key to the Server

After generating the key pair, you need to copy the public key to the remote server's ~/.ssh/authorized_keys file. On Linux/macOS you can use ssh-copy-id, but on Windows you can achieve the same result manually:

PowerShell
# Display your public key
Get-Content $env:USERPROFILE\.ssh\id_ed25519.pub

# Copy the public key to the remote server in one command
type $env:USERPROFILE\.ssh\id_ed25519.pub | ssh user@server "mkdir -p ~/.ssh && chmod 700 ~/.ssh && cat >> ~/.ssh/authorized_keys && chmod 600 ~/.ssh/authorized_keys"

# Test the connection — should not prompt for a password
sftp user@server

Key File Permissions

SSH is strict about file permissions on key files. If your private key has overly permissive access, SSH will refuse to use it. On the server side, the .ssh directory and authorized_keys file must also have correct permissions:

~/.ssh/                      drwx------  (700)
├── authorized_keys          -rw-------  (600)
├── id_ed25519               -rw-------  (600)  ← Private key
├── id_ed25519.pub           -rw-r--r--  (644)  ← Public key
├── known_hosts              -rw-r--r--  (644)
└── config                   -rw-------  (600)

Essential SFTP Commands

Once connected to an SFTP session, you interact with the remote server using a set of built-in commands. These commands are similar to standard Unix shell commands but operate within the SFTP subsystem. Understanding these commands is essential for efficient file management, whether you are transferring individual files, managing directory structures, or modifying permissions on a remote server.

Navigation and Listing

SFTP Session
# Show current remote directory
sftp> pwd
Remote working directory: /home/username

# Show current local directory
sftp> lpwd
Local working directory: C:\Users\YourName

# List remote files with details
sftp> ls -la
drwxr-xr-x    5 user   group    4096 Oct 10 09:15 .
drwxr-xr-x    3 root   root     4096 Sep 01 12:00 ..
-rw-r--r--    1 user   group     220 Sep 01 12:00 .bash_logout
-rw-r--r--    1 user   group    3526 Sep 01 12:00 .bashrc
drwxr-xr-x    2 user   group    4096 Oct 10 09:15 documents
drwxr-xr-x    2 user   group    4096 Oct 05 14:30 backups

# Change remote directory
sftp> cd documents

# Change local directory
sftp> lcd C:\Users\YourName\Downloads

# List local files
sftp> lls

File Transfer Commands

The most frequently used SFTP operations are downloading and uploading files. The get command downloads files from the remote server to your local machine, while put uploads files from your local machine to the remote server. Both commands support recursive transfers for entire directories and can resume interrupted transfers.

SFTP Session
# Download a single file
sftp> get report.pdf
Fetching /home/user/report.pdf to report.pdf
/home/user/report.pdf                  100%  2.4MB  12.1MB/s   00:00

# Download a file to a specific local path
sftp> get report.pdf C:\Users\YourName\Documents\report.pdf

# Download an entire directory recursively
sftp> get -r documents/

# Upload a single file
sftp> put C:\Users\YourName\backup.tar.gz
Uploading C:\Users\YourName\backup.tar.gz to /home/user/backup.tar.gz
backup.tar.gz                          100%  150MB   8.5MB/s   00:17

# Upload an entire directory recursively
sftp> put -r C:\Projects\website

# Resume a partial transfer
sftp> reget large-database-dump.sql
sftp> reput large-upload-file.zip

File Management Commands

SFTP provides a comprehensive set of commands for managing files and directories on the remote server without needing to open a separate SSH session:

  • mkdir dirname — create a new remote directory
  • rmdir dirname — remove an empty remote directory
  • rm filename — delete a remote file
  • rename oldname newname — rename or move a remote file
  • chmod 755 filename — change permissions on a remote file
  • chown uid filename — change ownership of a remote file
  • chgrp gid filename — change group of a remote file
  • ln -s target linkname — create a symbolic link
  • df -h — display remote disk space usage
  • !command — execute a command on the local machine
✅ Pro tip: Local commands

Prefix any command with l to execute it locally. For example, lls lists local files, lcd changes the local directory, and lmkdir creates a local directory — all without leaving the SFTP session.

Batch File Transfers

One of SFTP's most powerful features for system administrators and DevOps engineers is its support for batch mode operations. Instead of interactively typing commands, you can create a script file containing SFTP commands and execute them in a single automated run. This is invaluable for scheduled backups, automated deployments, and any repetitive file transfer workflow.

Creating an SFTP Batch File

An SFTP batch file is a plain text file containing one SFTP command per line. Comments are not supported inside the batch file itself, so each line must be a valid SFTP command. Create a file called transfer.sftp with your desired commands:

transfer.sftp
cd /var/www/html
lcd C:\Projects\website\build
put -r assets
put index.html
put style.css
put app.js
chmod 644 index.html
chmod 644 style.css
chmod 644 app.js
chmod 755 assets
bye

Execute the batch file from PowerShell using the -b flag:

PowerShell
# Execute the batch file with key-based authentication
sftp -b transfer.sftp user@server

# Execute with a specific identity key
sftp -b transfer.sftp -i C:\Users\YourName\.ssh\id_ed25519 user@server

# Combine with logging for audit trails
sftp -b transfer.sftp user@server 2>&1 | Tee-Object -FilePath transfer.log
⚠️ Batch mode requires non-interactive auth

SFTP batch mode cannot prompt for passwords. You must use SSH key authentication (without a passphrase, or with ssh-agent) for automated batch transfers. If password auth is your only option, consider using sshpass or WinSCP's scripting interface instead.

Automating with Windows Task Scheduler

For recurring transfers like nightly backups, combine your SFTP batch file with Windows Task Scheduler. Create a PowerShell wrapper script that handles logging and error checking, then schedule it to run at your desired interval. This approach gives you enterprise-grade file transfer automation without expensive commercial tools.

SFTP Configuration and Hardening

If you are running an SFTP server (the OpenSSH server on Windows or Linux), proper configuration is critical for security. The SSH daemon configuration file — sshd_config on Linux or C:\ProgramData\ssh\sshd_config on Windows — controls every aspect of how the server handles SFTP connections, from authentication methods to directory restrictions.

Essential sshd_config Settings

The following configuration options are particularly important for securing an SFTP server. Each option should be carefully considered based on your security requirements and user base:

sshd_config
# Force SFTP-only access for a specific group
Match Group sftpusers
    ForceCommand internal-sftp
    ChrootDirectory /sftp/%u
    AllowTcpForwarding no
    X11Forwarding no
    PermitTunnel no

# Disable password authentication globally (use keys only)
PasswordAuthentication no
PubkeyAuthentication yes

# Restrict allowed authentication methods
AuthenticationMethods publickey

# Limit login attempts and session timeouts
MaxAuthTries 3
LoginGraceTime 30
ClientAliveInterval 300
ClientAliveCountMax 2

# Use strong crypto algorithms only
KexAlgorithms curve25519-sha256,[email protected]
Ciphers [email protected],[email protected],[email protected]
MACs [email protected],[email protected]

# Logging for audit compliance
LogLevel VERBOSE

Setting Up Chroot Jails

A chroot jail restricts SFTP users to a specific directory, preventing them from browsing the rest of the filesystem. This is essential for shared hosting environments, vendor file exchanges, and any scenario where you need to limit user access to a designated folder. The ChrootDirectory directive in sshd_config enables this feature.

For chroot to work, the chroot directory and all parent directories must be owned by root and not writable by any other user. Inside the chroot, create a writable subdirectory for the user's actual files:

/sftp/                          drwxr-xr-x  root:root
├── alice/                      drwxr-xr-x  root:root   ← ChrootDirectory
│   └── uploads/                drwxrwxr-x  alice:sftpusers  ← Writable
├── bob/                        drwxr-xr-x  root:root   ← ChrootDirectory
│   └── uploads/                drwxrwxr-x  bob:sftpusers    ← Writable
└── vendor/                     drwxr-xr-x  root:root   ← ChrootDirectory
    ├── incoming/               drwxrwx---  vendor:sftpusers ← Upload only
    └── outgoing/               dr-xr-x---  vendor:sftpusers ← Read only
🔒 Critical security note

Never set the ChrootDirectory to a path owned by the SFTP user. The chroot directory itself and every parent directory up to the root must be owned by root and must not be group-writable or world-writable. If these conditions are not met, SSH will refuse the connection with a "fatal: bad ownership or modes" error.

Troubleshooting Common Issues

Even with proper configuration, SFTP connections can fail for a variety of reasons. This section covers the most common issues and their solutions, organized by the type of error you are likely to encounter.

Connection Refused (Port 22)

A "Connection refused" error means the SSH daemon is not running on the remote server, the firewall is blocking port 22, or the server is listening on a different port. Troubleshooting steps:

  • Verify the SSH service is running: systemctl status sshd (Linux) or Get-Service sshd (Windows)
  • Check if port 22 is open: Test-NetConnection server -Port 22 from PowerShell
  • Review firewall rules: ensure both the server firewall and any network firewalls allow inbound TCP port 22
  • Confirm the correct hostname/IP and port number — try connecting with sftp -v for verbose output

Authentication Failures

If you receive "Permission denied" errors, the issue is almost always related to credentials or file permissions:

  • Wrong username or password — double-check the case-sensitive username and verify your password on the server
  • Key not accepted — ensure the public key is in the correct authorized_keys file and the file permissions are 600
  • Agent not running — if using ssh-agent with a passphrase-protected key, verify the agent has loaded your key: ssh-add -l
  • Server key policy — the server may have disabled password auth. Check with your admin or review sshd_config

Timeout and Slow Connections

Connection timeouts often indicate network issues, DNS resolution problems, or server-side configuration delays. Common fixes include:

  • Add ServerAliveInterval 60 to your local SSH config to prevent idle disconnections
  • Disable DNS lookup on the server by setting UseDNS no in sshd_config — reverse DNS lookups can add 10-30 seconds to connection time
  • Check MTU and network path issues using ping -f -l 1472 server on Windows
  • Test from a different network to rule out ISP or corporate firewall interference

"Broken pipe" During Transfers

A broken pipe error during file transfer usually indicates the connection was dropped mid-stream. This can happen due to network instability, server-side timeouts, or firewall session limits. To mitigate:

  • Use reget and reput to resume interrupted transfers
  • Configure keep-alive settings in your SSH config: ServerAliveInterval 30 and ServerAliveCountMax 3
  • For very large files, consider splitting them with split and reassembling after transfer
💡 Debug mode is your best friend

When troubleshooting any SFTP issue, connect with verbose mode enabled: sftp -vvv user@server. The triple-v flag produces maximum debug output showing every step of the connection handshake, key exchange, authentication, and channel setup. This output almost always reveals the exact point of failure.

SFTP vs Other Protocols

Choosing the right file transfer protocol depends on your specific requirements for security, performance, compatibility, and features. The following comparison table provides a comprehensive overview of how SFTP stacks up against FTP, FTPS, SCP, and rsync — the five most commonly used file transfer methods.

Feature SFTP FTP FTPS SCP rsync
Encryption✅ SSH (always)❌ None✅ TLS/SSL✅ SSH (always)✅ Over SSH
Port(s) Used22 (single)21 + dynamic990 + dynamic22 (single)22 (over SSH)
Firewall Friendly✅ Excellent❌ Poor⚠️ Moderate✅ Excellent✅ Excellent
Resume Transfers✅ Yes✅ Yes✅ Yes❌ No✅ Yes
Directory Listing✅ Yes✅ Yes✅ Yes❌ No✅ Yes
Delta/Incremental❌ No❌ No❌ No❌ No✅ Yes
Remote File Mgmt✅ Full✅ Limited✅ Limited❌ Copy only⚠️ Sync only
AuthenticationPassword, Key, MFAPassword onlyPassword, CertPassword, KeyPassword, Key
Platform SupportUniversalUniversalUniversalUniversalLinux/macOS native
Best Use CaseGeneral secure transferLegacy systemsCompliance needsQuick one-off copiesIncremental backups

For most modern use cases, SFTP is the recommended default protocol. It provides the best balance of security, features, and ease of configuration. Choose SCP only when you need the simplest possible one-time copy with minimal overhead. Use rsync when you need incremental synchronization of large datasets. Resort to FTP or FTPS only when connecting to legacy systems that do not support SSH-based protocols.

Summary and Best Practices

SFTP is the gold standard for secure file transfers in modern IT environments. Its combination of strong encryption, single-port operation, comprehensive file management capabilities, and broad platform support makes it the ideal choice for everything from manual file uploads to enterprise-grade automated data pipelines. By following the practices outlined in this guide, you can ensure your SFTP deployments are secure, efficient, and maintainable.

Security Best Practices Checklist

  • Always use SSH key authentication — disable password authentication on production servers to eliminate brute-force attacks
  • Use strong key algorithms — prefer Ed25519 keys; if RSA is required, use 4096 bits minimum
  • Implement chroot jails — restrict SFTP users to their designated directories, especially for external vendors and shared hosting
  • Harden your cipher suite — disable legacy algorithms and enforce modern ciphers like ChaCha20-Poly1305 and AES-256-GCM
  • Enable verbose logging — set LogLevel VERBOSE in sshd_config for audit trail compliance and security monitoring
  • Limit authentication attempts — set MaxAuthTries 3 and LoginGraceTime 30 to slow down automated attacks
  • Use fail2ban or equivalent — automatically ban IP addresses with repeated failed login attempts
  • Keep software updated — regularly update OpenSSH to patch security vulnerabilities; subscribe to the OpenSSH security mailing list
  • Verify host keys — always confirm server host key fingerprints out-of-band before first connection
  • Rotate keys periodically — replace SSH keys annually or whenever staff turnover occurs

Performance Optimization Tips

  • Use -C flag for compression when transferring text files or other compressible data over slow connections
  • For large file transfers, use a cipher with hardware acceleration (AES-GCM on modern CPUs with AES-NI)
  • Increase the SSH buffer size with -B flag for high-latency connections
  • Use batch mode for automated transfers to avoid interactive overhead
  • Consider rsync over SSH for incremental synchronization of large datasets to minimize transfer volume
✅ You are now SFTP-ready!

With the knowledge from this guide, you can confidently set up secure SFTP connections, manage SSH keys, automate file transfers, harden your servers, and troubleshoot any issues that arise. For related topics, check out our SCP Guide for quick file copies, Server Management Guide for remote administration, and File Sync Guide for keeping directories in sync across machines.