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.
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