SFTP (SSH File Transfer Protocol)
SSH上で動作するセキュアなファイル転送プロトコル。暗号化通信、認証、ファイルシステム操作機能を提供。FTPの安全な代替手段。
サーバー
SFTP
概要
SFTP(SSH File Transfer Protocol)は、SSHプロトコルを基盤とするセキュアなファイル転送プロトコルです。OpenSSHに標準搭載されており、SSH接続を通じて暗号化された安全なファイル転送を実現します。従来のFTPと異なり、すべての通信が暗号化されるため、ユーザー認証情報とデータの両方が盗聴から保護されます。ポート22番を使用し、SSHの強力な認証機能(公開鍵認証、多要素認証)をそのまま利用できるため、現代のサイバーセキュリティ要件に適合したファイル転送ソリューションとして広く採用されています。
詳細
SFTP 2025年版は、OpenSSH 9.9以降の最新機能を活用し、セキュリティとユーザビリティを大幅に向上させています。chroot jail環境による安全なユーザー隔離、FIDO2/WebAuthn対応による多要素認証、Ed25519暗号化アルゴリズムによる高速で安全な鍵交換を標準サポート。ファイル転送プロトコルとしての基本機能に加え、ディレクトリ同期、再帰的転送、レジューム機能、帯域制限などの高度な機能を提供します。Docker環境やKubernetes環境での運用も標準化されており、コンテナベースのマイクロサービスアーキテクチャでの活用が拡大しています。また、REST APIとの統合やCI/CDパイプラインでの自動化にも対応し、現代的なDevOps環境で重要な役割を果たしています。
主な特徴
- 完全暗号化通信: SSH基盤によりすべての通信が暗号化され、データとコマンドの両方を保護
- 強力な認証機能: パスワード認証、公開鍵認証、多要素認証に対応
- chroot Jail: ユーザーを特定ディレクトリに制限してセキュリティを強化
- ポート統一: SSH(ポート22)を使用し、ファイアウォール設定が簡潔
- プラットフォーム対応: Linux、macOS、Windows、組み込み機器まで幅広くサポート
- レジューム機能: 中断した転送の再開が可能で大容量ファイルに対応
メリット・デメリット
メリット
- SSHベースのため既存のセキュリティ基盤をそのまま活用可能
- すべての通信が暗号化され、中間者攻撃やデータ盗聴から完全に保護
- OpenSSHの成熟したセキュリティ機能(鍵認証、MFA等)を利用
- 単一ポート(22番)でファイル転送とリモートアクセス両方に対応
- ファイアウォール設定が簡潔で、企業ネットワークで導入しやすい
- プラットフォーム間の互換性が高く、デバイス依存性が低い
デメリット
- FTPに比べて設定がやや複雑で初期構築に技術知識が必要
- 暗号化オーバーヘッドにより純粋なファイル転送速度ではFTPより劣る
- 大容量ファイルの高速転送にはRsyncやGridFTPが優位な場合がある
- 古いクライアントソフトウェアでは最新のSSH機能に対応しない可能性
- 設定ミスによるセキュリティホールのリスク(権限設定、chroot設定等)
- レガシーシステムとの連携で互換性の問題が発生する場合がある
参考ページ
書き方の例
OpenSSH SFTP サーバーのインストールと基本設定
# Ubuntu/Debianでのインストール
sudo apt update
sudo apt install openssh-server
# CentOS/RHEL/Fedoraでのインストール
sudo dnf install openssh-server
# macOS (Homebrew)
brew install openssh
# サービス確認・起動
sudo systemctl status ssh
sudo systemctl enable ssh
sudo systemctl start ssh
# SFTP専用設定(/etc/ssh/sshd_config)
sudo cp /etc/ssh/sshd_config /etc/ssh/sshd_config.bak
# 基本SFTP設定
sudo tee -a /etc/ssh/sshd_config << 'EOF'
# SFTP subsystem設定
Subsystem sftp internal-sftp
# SFTP専用ユーザーグループ
Match Group sftponly
ChrootDirectory /srv/sftp/%u
ForceCommand internal-sftp
AllowTcpForwarding no
X11Forwarding no
PermitTunnel no
EOF
# SSH設定のテスト
sudo sshd -t
# SSH サービス再起動
sudo systemctl restart ssh
# ポート確認
sudo netstat -tlnp | grep :22
SFTP専用ユーザーとchroot環境の設定
# SFTP専用グループ作成
sudo groupadd sftponly
# SFTP専用ユーザー作成
sudo useradd -M -d /srv/sftp/testuser -s /bin/false -G sftponly testuser
sudo passwd testuser
# chroot ディレクトリ構造作成
sudo mkdir -p /srv/sftp/testuser/{upload,download,shared}
# chroot権限設定(重要:ルートディレクトリはroot所有である必要)
sudo chown root:root /srv/sftp/testuser
sudo chmod 755 /srv/sftp/testuser
# ユーザー用ディレクトリ権限設定
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}
# 複数ユーザー作成の自動化スクリプト
cat > /usr/local/bin/create-sftp-user << 'EOF'
#!/bin/bash
USERNAME=$1
if [ -z "$USERNAME" ]; then
echo "Usage: $0 <username>"
exit 1
fi
# ユーザー作成
sudo useradd -M -d /srv/sftp/$USERNAME -s /bin/false -G sftponly $USERNAME
echo "パスワードを設定してください:"
sudo passwd $USERNAME
# ディレクトリ作成
sudo mkdir -p /srv/sftp/$USERNAME/{upload,download,shared}
# 権限設定
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ユーザー $USERNAME を作成しました"
EOF
chmod +x /usr/local/bin/create-sftp-user
公開鍵認証の設定
# ユーザー側での鍵ペア生成(Ed25519推奨)
ssh-keygen -t ed25519 -f ~/.ssh/sftp_key -C "sftp-access"
# または RSA(互換性重視の場合)
ssh-keygen -t rsa -b 4096 -f ~/.ssh/sftp_key -C "sftp-access"
# 公開鍵をサーバーに登録
ssh-copy-id -i ~/.ssh/sftp_key.pub testuser@your-server
# サーバー側での手動設定(必要に応じて)
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
# 公開鍵追加(testuser として実行)
echo "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAI... sftp-access" >> /srv/sftp/testuser/.ssh/authorized_keys
# パスワード認証無効化(セキュリティ強化)
sudo tee -a /etc/ssh/sshd_config << 'EOF'
# 公開鍵認証のみ許可(SFTP専用グループ)
Match Group sftponly
PasswordAuthentication no
PubkeyAuthentication yes
AuthenticationMethods publickey
EOF
sudo systemctl restart ssh
高度なセキュリティ設定
# 多要素認証設定(Google Authenticator)
sudo apt install libpam-google-authenticator
# ユーザーごとのMFA設定
sudo -u testuser google-authenticator
# QRコードをスキャンして設定
# PAM設定(/etc/pam.d/sshd)
sudo tee -a /etc/pam.d/sshd << 'EOF'
auth required pam_google_authenticator.so
EOF
# SSH設定でMFA有効化
sudo tee -a /etc/ssh/sshd_config << 'EOF'
# 多要素認証設定
Match Group sftponly
AuthenticationMethods publickey,keyboard-interactive
ChallengeResponseAuthentication yes
EOF
# ファイアウォール設定(UFW使用例)
sudo ufw allow 22/tcp
sudo ufw allow from 192.168.1.0/24 to any port 22 # 特定ネットワークのみ許可
# fail2ban設定
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
クライアント側でのSFTP操作例
# 基本的なSFTP接続
sftp testuser@your-server
# 公開鍵認証での接続
sftp -i ~/.ssh/sftp_key testuser@your-server
# ポート指定での接続
sftp -P 2222 testuser@your-server
# SFTP コマンド例(接続後)
# ローカル・リモートディレクトリ表示
pwd # リモートの現在ディレクトリ
lpwd # ローカルの現在ディレクトリ
ls # リモートディレクトリ一覧
lls # ローカルディレクトリ一覧
# ファイル転送
put localfile.txt # アップロード
put localfile.txt remotefile.txt # ファイル名変更してアップロード
mput *.txt # 複数ファイルアップロード
get remotefile.txt # ダウンロード
get remotefile.txt localfile.txt # ファイル名変更してダウンロード
mget *.txt # 複数ファイルダウンロード
# ディレクトリ操作
mkdir remote-dir # リモートディレクトリ作成
rmdir remote-dir # リモートディレクトリ削除
cd upload # リモートディレクトリ移動
lcd /local/path # ローカルディレクトリ移動
# バッチモード(スクリプト化)
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クライアント プログラミング例
# Python paramiko ライブラリを使用
import paramiko
import os
def sftp_upload_file(hostname, username, private_key_path, local_file, remote_file):
"""SFTP経由でファイルをアップロード"""
try:
# SSH接続設定
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
# 秘密鍵で認証
private_key = paramiko.Ed25519Key.from_private_key_file(private_key_path)
ssh.connect(hostname, username=username, pkey=private_key)
# SFTP セッション開始
sftp = ssh.open_sftp()
# ファイルアップロード
sftp.put(local_file, remote_file)
print(f"Successfully uploaded {local_file} to {remote_file}")
# ファイル権限設定
sftp.chmod(remote_file, 0o644)
# ディレクトリ一覧取得
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()
# 使用例
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'
)
// Node.js ssh2-sftp-client ライブラリを使用
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'),
// または
// password: 'your-password'
};
try {
// 接続
await sftp.connect(config);
console.log('SFTP connection established');
// ディレクトリ一覧
const list = await sftp.list('upload');
console.log('Directory listing:', list);
// ファイルアップロード
await sftp.put('./local-file.txt', 'upload/remote-file.txt');
console.log('File uploaded successfully');
// ファイルダウンロード
await sftp.get('download/server-file.txt', './downloaded-file.txt');
console.log('File downloaded successfully');
// ディレクトリ作成
await sftp.mkdir('upload/new-folder', true);
console.log('Directory created');
// ファイル存在確認
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();
高度な運用とモニタリング
# SFTP接続ログの監視
sudo tail -f /var/log/auth.log | grep sftp
# 接続統計取得
# アクティブなSFTP接続数
sudo netstat -an | grep :22 | grep ESTABLISHED | wc -l
# SFTP利用統計取得スクリプト
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
# 自動化スクリプト(cron設定)
echo "0 */6 * * * root /usr/local/bin/sftp-stats >> /var/log/sftp-usage.log" | sudo tee -a /etc/crontab
# ログローテーション設定
sudo tee /etc/logrotate.d/sftp-usage << 'EOF'
/var/log/sftp-usage.log {
daily
missingok
rotate 30
compress
delaycompress
notifempty
copytruncate
}
EOF
# バックアップスクリプト
cat > /etc/cron.daily/sftp-backup << 'EOF'
#!/bin/bash
# SFTP設定とデータのバックアップ
BACKUP_DIR="/backup/sftp/$(date +%Y%m%d)"
mkdir -p $BACKUP_DIR
# SSH設定バックアップ
cp /etc/ssh/sshd_config $BACKUP_DIR/
cp -r /etc/ssh $BACKUP_DIR/ssh-config/
# ユーザーデータバックアップ
tar -czf $BACKUP_DIR/sftp-data.tar.gz /srv/sftp/
# ログバックアップ
grep sftp /var/log/auth.log > $BACKUP_DIR/sftp-auth.log
# 古いバックアップ削除(30日保持)
find /backup/sftp/ -type d -mtime +30 -exec rm -rf {} \;
echo "SFTP backup completed: $BACKUP_DIR"
EOF
chmod +x /etc/cron.daily/sftp-backup