SFTP (SSH File Transfer Protocol)

Secure file transfer protocol running over SSH. Provides encrypted communication, authentication, and file system operation capabilities. Secure alternative to FTP.

File ServerSFTPSecure File TransferSSHOpenSSHSecurityEncrypted Communication

Server

SFTP

Overview

SFTP (SSH File Transfer Protocol) is a secure file transfer protocol built on the SSH protocol foundation. It is included as standard with OpenSSH and provides encrypted secure file transfer through SSH connections. Unlike traditional FTP, all communication is encrypted, protecting both user authentication information and data from eavesdropping. Using port 22, it can utilize SSH's powerful authentication features (public key authentication, multi-factor authentication) directly, making it widely adopted as a file transfer solution that meets modern cybersecurity requirements.

Details

SFTP 2025 edition leverages the latest features of OpenSSH 9.9 and later, significantly improving security and usability. It provides standard support for secure user isolation through chroot jail environments, multi-factor authentication with FIDO2/WebAuthn support, and fast, secure key exchange using the Ed25519 encryption algorithm. In addition to basic file transfer protocol functions, it offers advanced features such as directory synchronization, recursive transfer, resume functionality, and bandwidth limiting. Operations in Docker and Kubernetes environments have been standardized, expanding utilization in container-based microservice architectures. It also supports integration with REST APIs and automation in CI/CD pipelines, playing a crucial role in modern DevOps environments.

Key Features

  • Complete Communication Encryption: SSH-based encryption protects both data and commands
  • Strong Authentication: Supports password authentication, public key authentication, and multi-factor authentication
  • chroot Jail: Restricts users to specific directories to enhance security
  • Unified Port: Uses SSH (port 22) for simplified firewall configuration
  • Platform Support: Wide support from Linux, macOS, Windows to embedded devices
  • Resume Functionality: Supports resuming interrupted transfers for large files

Pros and Cons

Pros

  • SSH-based, allowing utilization of existing security infrastructure
  • All communication is encrypted, providing complete protection from man-in-the-middle attacks and data eavesdropping
  • Utilizes mature OpenSSH security features (key authentication, MFA, etc.)
  • Single port (22) supports both file transfer and remote access
  • Simple firewall configuration, easy to deploy in corporate networks
  • High cross-platform compatibility with low device dependency

Cons

  • More complex configuration compared to FTP, requiring technical knowledge for initial setup
  • Encryption overhead results in lower pure file transfer speeds compared to FTP
  • For large file high-speed transfers, Rsync or GridFTP may be superior
  • Older client software may not support the latest SSH features
  • Risk of security holes due to configuration errors (permission settings, chroot settings, etc.)
  • Compatibility issues may arise when integrating with legacy systems

Reference Pages

Code Examples

OpenSSH SFTP Server Installation and Basic Configuration

# Installation on Ubuntu/Debian
sudo apt update
sudo apt install openssh-server

# Installation on CentOS/RHEL/Fedora
sudo dnf install openssh-server

# macOS (Homebrew)
brew install openssh

# Service check and startup
sudo systemctl status ssh
sudo systemctl enable ssh
sudo systemctl start ssh

# SFTP-specific configuration (/etc/ssh/sshd_config)
sudo cp /etc/ssh/sshd_config /etc/ssh/sshd_config.bak

# Basic SFTP configuration
sudo tee -a /etc/ssh/sshd_config << 'EOF'

# SFTP subsystem configuration
Subsystem sftp internal-sftp

# SFTP-only user group
Match Group sftponly
    ChrootDirectory /srv/sftp/%u
    ForceCommand internal-sftp
    AllowTcpForwarding no
    X11Forwarding no
    PermitTunnel no
EOF

# SSH configuration test
sudo sshd -t

# SSH service restart
sudo systemctl restart ssh

# Port check
sudo netstat -tlnp | grep :22

SFTP-Only User and chroot Environment Setup

# Create SFTP-only group
sudo groupadd sftponly

# Create SFTP-only user
sudo useradd -M -d /srv/sftp/testuser -s /bin/false -G sftponly testuser
sudo passwd testuser

# Create chroot directory structure
sudo mkdir -p /srv/sftp/testuser/{upload,download,shared}

# chroot permission settings (Important: root directory must be owned by root)
sudo chown root:root /srv/sftp/testuser
sudo chmod 755 /srv/sftp/testuser

# User directory permission settings
sudo chown testuser:sftponly /srv/sftp/testuser/upload
sudo chown testuser:sftponly /srv/sftp/testuser/download
sudo chown testuser:sftponly /srv/sftp/testuser/shared
sudo chmod 755 /srv/sftp/testuser/{upload,download,shared}

# Automation script for multiple user creation
cat > /usr/local/bin/create-sftp-user << 'EOF'
#!/bin/bash
USERNAME=$1
if [ -z "$USERNAME" ]; then
    echo "Usage: $0 <username>"
    exit 1
fi

# Create user
sudo useradd -M -d /srv/sftp/$USERNAME -s /bin/false -G sftponly $USERNAME
echo "Please set password:"
sudo passwd $USERNAME

# Create directories
sudo mkdir -p /srv/sftp/$USERNAME/{upload,download,shared}

# Set permissions
sudo chown root:root /srv/sftp/$USERNAME
sudo chmod 755 /srv/sftp/$USERNAME
sudo chown $USERNAME:sftponly /srv/sftp/$USERNAME/{upload,download,shared}
sudo chmod 755 /srv/sftp/$USERNAME/{upload,download,shared}

echo "SFTP user $USERNAME created successfully"
EOF

chmod +x /usr/local/bin/create-sftp-user

Public Key Authentication Setup

# Generate key pair on client side (Ed25519 recommended)
ssh-keygen -t ed25519 -f ~/.ssh/sftp_key -C "sftp-access"

# Or RSA (for compatibility-focused cases)
ssh-keygen -t rsa -b 4096 -f ~/.ssh/sftp_key -C "sftp-access"

# Copy public key to server
ssh-copy-id -i ~/.ssh/sftp_key.pub testuser@your-server

# Manual setup on server side (if needed)
sudo -u testuser mkdir -p /srv/sftp/testuser/.ssh
sudo -u testuser touch /srv/sftp/testuser/.ssh/authorized_keys
sudo chmod 700 /srv/sftp/testuser/.ssh
sudo chmod 600 /srv/sftp/testuser/.ssh/authorized_keys

# Add public key (run as testuser)
echo "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAI... sftp-access" >> /srv/sftp/testuser/.ssh/authorized_keys

# Disable password authentication (security enhancement)
sudo tee -a /etc/ssh/sshd_config << 'EOF'

# Allow public key authentication only (SFTP-only group)
Match Group sftponly
    PasswordAuthentication no
    PubkeyAuthentication yes
    AuthenticationMethods publickey
EOF

sudo systemctl restart ssh

Advanced Security Configuration

# Multi-factor authentication setup (Google Authenticator)
sudo apt install libpam-google-authenticator

# MFA setup per user
sudo -u testuser google-authenticator
# Scan QR code to configure

# PAM configuration (/etc/pam.d/sshd)
sudo tee -a /etc/pam.d/sshd << 'EOF'
auth required pam_google_authenticator.so
EOF

# Enable MFA in SSH configuration
sudo tee -a /etc/ssh/sshd_config << 'EOF'

# Multi-factor authentication settings
Match Group sftponly
    AuthenticationMethods publickey,keyboard-interactive
    ChallengeResponseAuthentication yes
EOF

# Firewall configuration (UFW example)
sudo ufw allow 22/tcp
sudo ufw allow from 192.168.1.0/24 to any port 22  # Allow specific network only

# fail2ban configuration
sudo apt install fail2ban

sudo tee /etc/fail2ban/jail.local << 'EOF'
[sshd]
enabled = true
port = ssh
filter = sshd
logpath = /var/log/auth.log
maxretry = 3
bantime = 3600
findtime = 600

[sftp]
enabled = true
port = ssh
filter = sshd
logpath = /var/log/auth.log
maxretry = 2
bantime = 7200
findtime = 300
EOF

sudo systemctl restart fail2ban

Client-Side SFTP Operations Examples

# Basic SFTP connection
sftp testuser@your-server

# Connection with public key authentication
sftp -i ~/.ssh/sftp_key testuser@your-server

# Connection with port specification
sftp -P 2222 testuser@your-server

# SFTP command examples (after connection)
# Display local/remote directories
pwd      # Remote current directory
lpwd     # Local current directory
ls       # Remote directory listing
lls      # Local directory listing

# File transfer
put localfile.txt                    # Upload
put localfile.txt remotefile.txt     # Upload with name change
mput *.txt                          # Multiple file upload
get remotefile.txt                  # Download
get remotefile.txt localfile.txt    # Download with name change
mget *.txt                          # Multiple file download

# Directory operations
mkdir remote-dir                    # Create remote directory
rmdir remote-dir                    # Remove remote directory
cd upload                          # Change remote directory
lcd /local/path                    # Change local directory

# Batch mode (scripting)
cat > sftp-script.txt << 'EOF'
cd upload
put important-file.txt
chmod 644 important-file.txt
get server-log.txt
quit
EOF

sftp -b sftp-script.txt testuser@your-server

SFTP Client Programming Examples

# Using Python paramiko library
import paramiko
import os

def sftp_upload_file(hostname, username, private_key_path, local_file, remote_file):
    """Upload file via SFTP"""
    try:
        # SSH connection setup
        ssh = paramiko.SSHClient()
        ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
        
        # Authenticate with private key
        private_key = paramiko.Ed25519Key.from_private_key_file(private_key_path)
        ssh.connect(hostname, username=username, pkey=private_key)
        
        # Start SFTP session
        sftp = ssh.open_sftp()
        
        # Upload file
        sftp.put(local_file, remote_file)
        print(f"Successfully uploaded {local_file} to {remote_file}")
        
        # Set file permissions
        sftp.chmod(remote_file, 0o644)
        
        # Get directory listing
        files = sftp.listdir('upload')
        print(f"Files in upload directory: {files}")
        
    except Exception as e:
        print(f"Error: {e}")
    finally:
        if 'sftp' in locals():
            sftp.close()
        if 'ssh' in locals():
            ssh.close()

# Usage example
sftp_upload_file(
    hostname='your-server.com',
    username='testuser',
    private_key_path='~/.ssh/sftp_key',
    local_file='./important-data.csv',
    remote_file='upload/important-data.csv'
)
// Using Node.js ssh2-sftp-client library
const Client = require('ssh2-sftp-client');
const fs = require('fs');

async function sftpOperations() {
    const sftp = new Client();
    
    const config = {
        host: 'your-server.com',
        port: 22,
        username: 'testuser',
        privateKey: fs.readFileSync('/path/to/sftp_key'),
        // or
        // password: 'your-password'
    };
    
    try {
        // Connect
        await sftp.connect(config);
        console.log('SFTP connection established');
        
        // Directory listing
        const list = await sftp.list('upload');
        console.log('Directory listing:', list);
        
        // File upload
        await sftp.put('./local-file.txt', 'upload/remote-file.txt');
        console.log('File uploaded successfully');
        
        // File download
        await sftp.get('download/server-file.txt', './downloaded-file.txt');
        console.log('File downloaded successfully');
        
        // Create directory
        await sftp.mkdir('upload/new-folder', true);
        console.log('Directory created');
        
        // Check file existence
        const exists = await sftp.exists('upload/remote-file.txt');
        console.log('File exists:', exists);
        
    } catch (error) {
        console.error('SFTP error:', error);
    } finally {
        await sftp.end();
        console.log('SFTP connection closed');
    }
}

sftpOperations();

Advanced Operations and Monitoring

# Monitor SFTP connection logs
sudo tail -f /var/log/auth.log | grep sftp

# Get connection statistics
# Number of active SFTP connections
sudo netstat -an | grep :22 | grep ESTABLISHED | wc -l

# SFTP usage statistics script
cat > /usr/local/bin/sftp-stats << 'EOF'
#!/bin/bash
echo "=== SFTP Server Statistics $(date) ==="

echo "=== Active Connections ==="
sudo netstat -an | grep :22 | grep ESTABLISHED

echo "=== Recent SFTP Logins ==="
grep "subsystem request for sftp" /var/log/auth.log | tail -10

echo "=== Failed Login Attempts ==="
grep "Failed password" /var/log/auth.log | grep sshd | tail -10

echo "=== User Activity ==="
grep "session opened" /var/log/auth.log | grep sftp | tail -10

echo "=== Disk Usage ==="
df -h /srv/sftp

echo "=== Active SFTP Sessions ==="
ps aux | grep sftp-server | grep -v grep
EOF

chmod +x /usr/local/bin/sftp-stats

# Automation script (cron configuration)
echo "0 */6 * * * root /usr/local/bin/sftp-stats >> /var/log/sftp-usage.log" | sudo tee -a /etc/crontab

# Log rotation configuration
sudo tee /etc/logrotate.d/sftp-usage << 'EOF'
/var/log/sftp-usage.log {
    daily
    missingok
    rotate 30
    compress
    delaycompress
    notifempty
    copytruncate
}
EOF

# Backup script
cat > /etc/cron.daily/sftp-backup << 'EOF'
#!/bin/bash
# SFTP configuration and data backup

BACKUP_DIR="/backup/sftp/$(date +%Y%m%d)"
mkdir -p $BACKUP_DIR

# SSH configuration backup
cp /etc/ssh/sshd_config $BACKUP_DIR/
cp -r /etc/ssh $BACKUP_DIR/ssh-config/

# User data backup
tar -czf $BACKUP_DIR/sftp-data.tar.gz /srv/sftp/

# Log backup
grep sftp /var/log/auth.log > $BACKUP_DIR/sftp-auth.log

# Remove old backups (30-day retention)
find /backup/sftp/ -type d -mtime +30 -exec rm -rf {} \;

echo "SFTP backup completed: $BACKUP_DIR"
EOF

chmod +x /etc/cron.daily/sftp-backup