SFTP (SSH File Transfer Protocol)

SSH上で動作するセキュアなファイル転送プロトコル。暗号化通信、認証、ファイルシステム操作機能を提供。FTPの安全な代替手段。

ファイルサーバーSFTPセキュアファイル転送SSHOpenSSHセキュリティ暗号化通信

サーバー

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