最終更新:2026-01-11
sftp (SSH File Transfer Protocol) は、SSH プロトコル上で動作するセキュアなファイル転送サブシステムです。
名前が似ている ftp や ftps (FTP over SSL) とは全く異なるプロトコルであり、SSH の暗号化通信路を利用して安全にファイル操作を行います。現在、OpenSSH プロジェクトでは、設計上の制約を持つ従来の scp (rcp互換) プロトコルについて注意を促しており、可能な限りより安全な代替として、この sftp の利用を推奨しています。
1. なぜ sftp は scp より安全なのか:構造的違い
scp と sftp の最大の違いは、**「データを流し込む」か「ファイルシステムを操作するか」**という設計思想にあります。
scp の仕組み:「サーバーを信頼する」モデル
scp は古くからの rcp (Remote Copy Protocol) の設計を引き継いでいます。
基本的に、クライアントはサーバーに対して「データを送るから受け取ってくれ」あるいは「データを送ってくれ」と依頼し、データの流れ(ストリーム)をそのまま処理します。
この際、サーバーから送られてくるファイル名やパスをクライアント側で厳密に検証する仕組みが弱く、「サーバーが嘘をつかない」ことを前提とした設計になっています。
sftp の仕組み:「手順を検証する」モデル
一方、sftp は リモートファイルシステム操作プロトコル として設計されています。
転送は以下のような厳格な手順(RPCに近いやり取り)で行われます。
- Open: クライアントが「ファイルXを開きたい」と要求する。
- Handle: サーバーはファイルハンドル(操作ID)を返す。
- Read/Write: クライアントはそのハンドルに対して「データを書き込む/読み込む」命令を出す。
- Close: 操作が終われば閉じる。
このように、クライアントが操作の主導権を持ち、サーバーからの応答をステップごとに検証できるため、サーバー側が意図しないファイル名やパスを送りつける攻撃(パストラバーサル等)を構造的に防ぐことができます。
2. scp の脆弱性と背景(CVEの事例)
scp の設計思想に起因する脆弱性がいくつか報告されており、これが sftp への移行が推奨される主な理由となっています。
-
CVE-2019-6111(ファイル名検証の不備) 悪意あるサーバー(またはMITM攻撃者)に接続した際、サーバーが要求とは異なるファイル名を返すことで、クライアント側の意図しないローカルファイルを上書きできてしまう脆弱性です。
scpクライアントがサーバーからのファイル名を十分に検証しないことに起因します。 -
CVE-2018-20685(ディレクトリ処理の検証不備)
scpにおけるディレクトリ処理とエラー検証の不備により、サーバー側の応答次第で想定外のディレクトリ権限操作などが行われる可能性が指摘された脆弱性です。 -
CVE-2020-15778(コマンド生成時のサニタイズ問題)
scpが内部でリモート側のscpを呼び出すためのシェルコマンドを生成する際、サーバーから渡されるパス文字列のサニタイズ(無害化)が不十分な場合がある問題です。特定の条件下において、クライアント側で想定外のコマンド実行につながる可能性が指摘されています。
3. sftp の基本的な使い方(対話モード)
sftp はシェルにログインするように対話的にコマンドを入力して操作するのが基本です。
接続の開始
sftp user@remotehost
接続が確立するとプロンプトが sftp> に変わり、専用のコマンドを受け付ける状態になります。
主要な内部コマンド
| コマンド | 説明 | 使用例 |
|---|---|---|
| put | ローカルのファイルをリモートへアップロード | put local.txt |
| get | リモートのファイルをローカルへダウンロード | get remote.txt |
| ls | リモート側のファイル一覧を表示 | ls -l |
| cd | リモート側のディレクトリを移動 | cd /var/www |
| lls | ローカル側のファイル一覧を表示 | lls |
| lcd | ローカル側のディレクトリを移動 | lcd ~/Documents |
| pwd | リモート側の現在のパスを表示 | pwd |
| lpwd | ローカル側の現在のパスを表示 | lpwd |
| bye | sftpを終了する | bye |
ディレクトリごとの転送(再帰的処理)
ディレクトリごと転送する場合は -r オプションを使用します。
sftp> put -r local_dir
sftp> get -r remote_dir
4. 自動化の手法(バッチモード)
scp が好まれる理由の一つに「コマンド一発で転送できる(スクリプトに組み込みやすい)」点がありますが、sftp でも -b オプションや標準入力を使用することで同等の自動化が可能です。
方法1: バッチファイルを指定する (-b)
あらかじめ実行したいコマンドをファイルに記述しておきます。
commands.txt
cd /target/directory
put data.csv
bye
実行コマンド
sftp -b commands.txt user@remotehost
方法2: ワンライナーで実行する(標準入力)
ヒアドキュメントやパイプを利用して、ファイルを作らずに実行できます。CI/CDパイプラインなどで便利です。
echo "put source.txt /dest/path/" | sftp user@remotehost
5. scp vs sftp 機能比較まとめ
| 項目 | scp | sftp |
|---|---|---|
| セキュリティ設計 | サーバー信頼モデル(rcp系)。パス検証に弱点あり。 | プロトコル主導モデル。操作と応答を厳密に検証。 |
| OpenSSHの扱い | レガシー (Legacy) | 推奨 (Preferred) |
| 中断再開 (Resume) | 基本的に不可 | 可能 (reget / reput コマンド) |
| ファイル操作 | 転送のみ | 削除 (rm)、権限変更 (chmod)、ディレクトリ作成 (mkdir) 等が可能 |
| パフォーマンス | ストリーム転送のため比較的高速 | パケット制御のため若干のオーバーヘッドがあるが、現代の帯域ではほぼ差はない |
| ネットワーク | ポート22 (SSH) のみ | ポート22 (SSH) のみ |
6. 実践的な応用ケースとTips
実務で役立つ sftp ならではの活用法です。
-
転送の中断と再開(レジューム) 巨大なファイル(ログやDBダンプなど)の転送が切れた場合、
reput(アップロード再開)やreget(ダウンロード再開)を使うことで、途中から再開できます。# 自動化スクリプトでの再開例 echo "reput big_database.dump" | sftp user@remotehost -
帯域制限による業務影響の低減 昼間の転送などでネットワーク帯域を占有したくない場合、
-lオプションで帯域を制限(Kbit/s単位)できます。sftp -l 2000 user@remotehost # 上限を約2Mbpsに制限 -
SSH設定の堅牢化
sftpも SSH の設定 (~/.ssh/configや-oオプション) を利用できます。鍵認証を強制する場合の例です。sftp -o PreferredAuthentications=publickey -i ~/.ssh/id_ed25519 user@remotehost
結論
日常的な単一ファイルのコピーであれば、scp の手軽さは依然として魅力的です。しかし、セキュリティが重視される環境や、システム間連携のバッチ処理、不特定多数のサーバーと通信するようなケースでは、信頼性の高い sftp を選択することが現在のベストプラクティスです。
特に自動化スクリプトにおいては、エラーハンドリングや再開機能の面でも sftp の方が堅牢な実装が可能になります。
最小チートシート
# Interactive Mode
sftp user@host
sftp -P 2222 -i ~/.ssh/id_ed25519 user@host
# Basic Upload/Download
put local.txt # Upload
get remote.txt # Download
put -r local_dir # Recursive Upload
get -r remote_dir # Recursive Download
# Resume Transfer (Retry)
reput large_file.iso # Resume Upload
reget large_file.iso # Resume Download
# Batch Automation
sftp -b batch_commands.txt user@host
echo "put file.txt" | sftp user@host
コラム:sftpをscpと同じ感覚で使う方法
「sftpは対話モードに入らなければならず、コマンド一発で終わらないから面倒だ」と思っていませんか? 実は、環境や使い方次第で scpと全く同じ感覚(ワンショット) で利用することが可能です。
1. OpenSSH 9.0以降の場合(推奨)
2022年4月にリリースされた OpenSSH 9.0 以降の sftp コマンドには、新たに「コピーモード」が搭載されました。
これにより、従来の scp と全く同じ構文(書き方)で、コマンド一発での転送が可能です。
ダウンロード(リモート → ローカル)
# scpと同じ書き方でOK
sftp user@host:/var/www/remote_file.txt .
アップロード(ローカル → リモート)
# こちらもscpと同じ
sftp local_file.txt user@host:/var/www/
ディレクトリごとの転送
再帰的な転送が必要な場合も、scp と同様に -r オプションを付けるだけです。
sftp -r user@host:/var/www/html/ ./backup_html/
Tips: お使いの環境が対応しているかは、
ssh -Vを実行してOpenSSH_9.0以上のバージョンが表示されるかで確認できます。
2. 古いバージョンでの対応(ワンライナー)
OpenSSH 9.0 未満の環境や、シェルスクリプトへの組み込みで互換性を重視する場合は、標準入力(パイプ) を活用します。 「コマンドを流し込む」ことで、対話モードに入ることなく即座に処理を完了させることができます。
ダウンロード
# echoでコマンドを渡して即実行
echo "get /var/www/remote_file.txt" | sftp user@host
アップロード
echo "put local_file.txt /var/www/" | sftp user@host
ディレクトリごとアップロード
# -r オプションを忘れずに
echo "put -r local_dir" | sftp user@host
3. scp → sftp 置き換え対応表
慣れ親しんだ scp コマンドを、互換性の高い sftp ワンライナーに置き換える場合の対応表��す。
| 動作 | 従来の scp コマンド | sftp ワンライナー (汎用) |
|---|---|---|
| ファイル送信 | scp file user@host:~/ | echo "put file" | sftp user@host |
| ファイル受信 | scp user@host:~/file . | echo "get file" | sftp user@host |
| フォルダ送信 | scp -r dir user@host:~/ | echo "put -r dir" | sftp user@host |
| ポート指定 | scp -P 2222 ... | echo "..." | sftp -P 2222 user@host |
| 帯域制限 | scp -l 1000 ... | echo "..." | sftp -l 1000 user@host |
まとめ
最新環境であれば、単にコマンド名を scp から sftp に書き換えるだけで移行は完了します。
古い環境であっても、パイプを活用すれば使用感はほとんど変わりません。
一度この使い方に慣れてしまえば、**「中断再開(レジューム)が可能」かつ「セキュア」**な sftp を使わない理由はほとんどなくなります。