結論

FTP(File Transfer Protocol)は、ネットワーク越しにファイルを送受信するための通信の決まりです。命令用の接続(21番ポート)とデータ用の接続(20番か、パッシブ用の範囲)の2本を使い、ユーザー名もパスワードも暗号化せずに送ります。今から選ぶならSFTPかFTPSです。

この記事でわかること

  • FTPの仕組み・ポート番号・アクティブとパッシブの違い(tcpdumpの原文つき)
  • ftpコマンドでサーバーに送ったUSER・PASS・PASV・LIST・RETR・STORの実際の応答
  • FTP・FTPS・SFTP・SCP・rsyncの違いと、530・425・タイムアウトのエラー原文

2026年10月29日更新|vsftpd 3.0.5・pyftpdlib 2.2.0・tnftp 20230507・tcpdump 4.99.4・curl 8.5.0で実行確認

FTPでは、命令と返事をやり取りする「制御接続」と、ファイルの中身や一覧を流す「データ接続」が別々のTCP接続です。データ接続をどちらから張るかで、アクティブモードとパッシブモードに分かれます。

sequenceDiagram
    participant C as クライアント
    participant S as FTPサーバー
    C->>S: 制御接続(21番)
    C->>S: USER / PASS(平文)
    S-->>C: 230 Login successful
    C->>S: PASV
    S-->>C: 227 (127,0,0,1,203,241)
    C->>S: データ接続(52209番)
    C->>S: RETR notes.txt
    S-->>C: ファイルの中身

よく調べられることの答えを先にまとめます。

知りたいこと 答え 詳しい節
ftpとは ファイルを送受信する通信の決まり(RFC 959)。暗号化なし FTPとは
ftp ポート 命令は21番。データは20番(アクティブ)か、サーバーが指定する番号(パッシブ) FTPのポート番号
ftp sftp 違い SFTPはSSH(22番)の上で動く別のプロトコル。全部暗号化される FTPとSFTPの違い
ftps sftp 違い FTPSはFTPにTLSをかぶせたもの。SFTPとは互換性が無い FTPとSFTPの違い
アクティブ パッシブ 違い データ接続をサーバーから張るのがアクティブ、クライアントから張るのがパッシブ アクティブモードとパッシブモードの違い
ftp コマンド 使い方 ftp ホスト → ユーザー名・パスワード → ls・get・put・quit ftpコマンドの実際のやり取り
530 Login incorrect ユーザー名かパスワードの誤り。匿名専用サーバーに通常ユーザーで入ったときも530 よくあるエラー
425 Failed to establish connection データ接続が張れない。アクティブ/パッシブの切り替えとファイアウォールを見る よくあるエラー
FileZilla 設定 ホスト・ユーザー名・パスワード・ポート。FTPSは ftpes://、SFTPは sftp:// FileZillaの設定項目

確認環境:Ubuntu 24.04.5 LTS の上で、vsftpd 3.0.5(Ubuntu のパッケージ)を自分の設定ファイルで 127.0.0.1 の 2121 番に匿名専用で起動し、ユーザー名とパスワードで入るサーバーと FTPS(AUTH TLS)のサーバーは pyftpdlib 2.2.0(Python 3.13.18・pyOpenSSL 26.4.0)で 127.0.0.1 の 2122 番と 2990 番に起動しました。クライアントは tnftp 20230507(Ubuntu の ftp コマンド)、curl 8.5.0、Python の ftplib で、パケットは tcpdump 4.99.4 でループバック(lo)だけを取りました。接続のタイムアウトは、ip netns で作った名前空間の中で、応答しない宛先に向けて確かめています。FileZilla の設定項目は FileZilla の公式 Wiki、vsftpd の設定の既定値は vsftpd の公式サイトの vsftpd.conf のページ、scp の変更は OpenSSH 9.0 のリリースノート、Chrome の FTP 対応の終了は Chrome Developers のブログで確かめました。図は mermaid で描画を確かめています(確認日 2026年10月29日)。

本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。

(記載例)出典:株式会社RJC「FTPとは|仕組み・ポート・SFTPとの違いをtcpdumpの実物で」

FTPとは(意味と仕組み)

この節では、FTPが何で、どういう仕組みでファイルを運ぶのかが分かります。

FTP は File Transfer Protocol(ファイル転送プロトコル)の略で、サーバーとクライアントの間でファイルを送受信するための通信の決まりです。 仕様は RFC 959(1985年)で、原型は1971年までさかのぼります。Web ページを運ぶ HTTP と同じく TCP の上で動きますが、HTTP より前からある、ファイルのやり取りに特化したプロトコルです。

FTP の特徴は、1つのやり取りに2本の TCP 接続を使うことです。

制御接続(コントロールチャネル)

クライアントがサーバーの21番ポートへ張る

USER・PASS・LIST・RETR などの命令と、3桁の数字で始まる返事が流れる

ログインから切断まで1本を使い続ける

データ接続(データチャネル)

ファイルの中身とディレクトリの一覧が流れる

転送のたびに新しく張り、終わると閉じる

どちらから張るかがアクティブ/パッシブの違い

手元で ftp コマンドからファイルを1つ受け取ったとき、tcpdump には、21番相当のポートへの接続とは別に、データ用のもう1本の接続(SYN)が見えました。この2本構成が、ファイアウォールでつまずく原因にも、アクティブ/パッシブという用語の由来にもなっています。

1サーバーとクライアント

ファイルを置いておく側が FTP サーバー(vsftpd・ProFTPD・IIS など)、取りに行く側が FTP クライアント(ftp コマンド・FileZilla・WinSCP・curl など)。

2アップロードとダウンロード

クライアントからサーバーへ送るのがアップロード(STOR・put)、サーバーから受け取るのがダウンロード(RETR・get)。

3匿名FTP

ユーザー名 anonymous(または ftp)で誰でも入れる公開サーバー。以前はソフトの配布に広く使われ、今も一部のミラーサイトに残っている。

ブラウザからの利用は終わっています。Chrome Developers のブログ(Chrome 95 の非推奨と削除の一覧)は、ブラウザでの FTP の利用がとても少なくなったため FTP の URL への対応を取り除く、と書いています。今は専用のクライアントか、コマンドで使います。

FTPのポート番号(21番・20番・パッシブ用の範囲)

この節では、FTPが使うポート番号と、ファイアウォールで何番を開ける必要があるのかが分かります。

FTP は、制御接続に 21 番、アクティブモードのデータ接続に 20 番を使います。パッシブモードのデータ接続は、サーバーが決めた任意の番号(vsftpd なら pasv_min_port〜pasv_max_port の範囲)です。 ここが「FTP は 21 番を開ければよい」とは言い切れない理由です。

プロトコル ポート 何が流れるか 誰が接続を張るか
FTP 制御接続 TCP 21 命令と返事(平文) クライアント → サーバー
FTP データ接続(アクティブ) TCP 20(サーバー側の送信元) ファイル・一覧(平文) サーバー → クライアント
FTP データ接続(パッシブ) サーバーが 227 の返事で指定 ファイル・一覧(平文) クライアント → サーバー
FTPS(explicit) TCP 21 で接続し AUTH TLS で暗号化 命令・データ(TLS) FTP と同じ
FTPS(implicit) TCP 990 最初から TLS FTP と同じ
SFTP・SCP TCP 22(SSH) 命令・データ(SSH で暗号化、1本) クライアント → サーバー

手元の vsftpd は listen_port=2121・pasv_min_port=52100・pasv_max_port=52110 で起動したので、パッシブのデータ接続は 52100〜52110 のどれかに来ます。ファイアウォールを設定するときは、21 番に加えてこの範囲を開けます(アクティブモードも許すなら、サーバーからの 20 番発の接続も)。ポート番号の全体像は、関連記事「ポート番号一覧【2026年版】well-knownポートと確認コマンドの早見表」で扱っています。

ftpコマンドの実際のやり取り(USER・PASS・LIST・RETR・STOR)

この節では、ftpコマンドが裏で何を送り、サーバーが何を返しているのかが、実行した原文で分かります。

ftp コマンドの ls・get・put は、裏では LIST・RETR・STOR という FTP の命令に置き換わっています。 ftp -v -d(デバッグ表示)で vsftpd の匿名サーバーに入り、一覧・ダウンロード・アップロードを行ったときの原文です。---> がクライアントの送った命令、3桁の数字で始まる行がサーバーの返事です(passive を打って、わざとアクティブモードにしています)。

$ ftp -v -d 127.0.0.1 2121
Connected to 127.0.0.1.
220 Welcome to the RJC test FTP server (vsftpd).
Name (127.0.0.1:root): anonymous
---> USER anonymous
331 Please specify the password.
Password:
---> PASS XXXX
230 Login successful.
---> SYST
215 UNIX Type: L8
Remote system type is UNIX.
Using binary mode to transfer files.
---> FEAT
211-Features:
 EPRT
 EPSV
 MDTM
 PASV
 REST STREAM
 SIZE
 TVFS
211 End
ftp> pwd
---> PWD
257 "/" is the current directory
ftp> passive
Passive mode: off; fallback to active mode: off.
ftp> ls
---> EPRT |1|127.0.0.1|42711|
200 EPRT command successful. Consider using EPSV.
---> LIST
150 Here comes the directory listing.
drwxr-xr-x    2 65534    65534        4096 Oct 29 08:48 pub
226 Directory send OK.
ftp> cd pub
---> CWD pub
250 Directory successfully changed.
ftp> binary
---> TYPE I
200 Switching to Binary mode.
ftp> get readme.txt
---> SIZE readme.txt
213 28
---> EPRT |1|127.0.0.1|51017|
200 EPRT command successful. Consider using EPSV.
---> RETR readme.txt
150 Opening BINARY mode data connection for readme.txt (28 bytes).
226 Transfer complete.
28 bytes received in 00:00 (536.15 KiB/s)
ftp> put notes.txt upload.txt
---> EPRT |1|127.0.0.1|34385|
200 EPRT command successful. Consider using EPSV.
---> STOR upload.txt
550 Permission denied.
ftp> quit
---> QUIT
221 Goodbye.

最後の put が 550 Permission denied. になったのは、この vsftpd を write_enable=NO(書き込み禁止)で起動しているためです。ユーザー名とパスワードで入るサーバー(pyftpdlib)では、同じ put が 226 Transfer complete. になり、ls に uploaded.txt が増えました。

画面に出るクライアントの操作と、裏で流れる命令の対応です。

ftp コマンドでの操作 流れる FTP の命令 手元の返事
ユーザー名を入れる USER alice 331 Username ok, send password.
パスワードを入れる PASS s3cret-pass(平文) 230 Login successful.
pwd PWD 257 "/" is the current directory.
cd pub CWD pub 250 Directory successfully changed.
ls PASV(または PORT)→ LIST 150 → 一覧 → 226 Directory send OK.
binary/ascii TYPE I/TYPE A 200 Switching to Binary mode.
get readme.txt SIZE → PASV → RETR readme.txt 150 Opening BINARY mode data connection
put a.txt PASV → STOR a.txt 226 Transfer complete.(禁止なら 550)
quit QUIT 221 Goodbye.
  • tnftp(Ubuntu の ftp コマンド)は、既定でパッシブモードかつ EPSV/EPRT(IPv6 にも使える拡張形)です。 passive で切り替わり、epsv4 off と打つと、以前からの PASV・PORT を使うようになりました。
  • 画面の PASS XXXX は、クライアントが画面上だけ隠している表示です。ネットワーク上では隠れていません(後の節で tcpdump の原文を示します)。

FTPの応答コード(220・230・331・530・550)の読み方

この節では、FTPサーバーが返す3桁の数字の意味と、よく見る番号が分かります。

返事の1桁目が結果の種類で、2 が成功、3 が「続きの情報を送って」、4 が一時的な失敗(やり直せる)、5 が恒久的な失敗(同じ送り方では直らない)です。 HTTP のステータスコードと似た考え方ですが、番号の割り当ては別物です。

コード 意味 手元で見た文言
220 サーバーの準備ができた(接続直後のあいさつ) 220 Welcome to the RJC test FTP server (vsftpd).
331 ユーザー名は受け取った。パスワードを送って 331 Please specify the password.
230 ログイン成功 230 Login successful.
227/229 パッシブモードに入った(データ接続先の案内) 227 Entering passive mode (127,0,0,1,203,241).
150/125 データ接続を開く・開いている。転送を始める 150 Here comes the directory listing.
226 転送が完了し、データ接続を閉じた 226 Transfer complete.
425 データ接続を開けない 425 Failed to establish connection.
421 サービスを提供できない。接続を閉じる(アイドルのタイムアウトなど) 421 Timeout.(120 秒放置して届いた)
530 ログインしていない・認証に失敗 530 Authentication failed./530 This FTP server is anonymous only.
550 ファイルに対する操作ができない(無い・権限が無い) 550 Failed to open file./550 Permission denied.
500 命令の構文が不正 500 Illegal PORT command.

サーバーの実装によって文言は変わります。vsftpd の本体(/usr/sbin/vsftpd)に含まれる文言を調べると、通常ユーザーの認証失敗は Login incorrect.、データ接続の手順違いは Use PORT or PASV first. でした。番号で判断し、文言は手がかりとして読みます。

アクティブモードとパッシブモードの違い(tcpdumpで見る)

この節では、アクティブモードとパッシブモードで何が違い、なぜパッシブが推奨されるのかが、パケットの向きで分かります。

違いは「データ接続をどちらから張るか」だけです。 アクティブモードでは、クライアントが PORT(または EPRT)で自分の待ち受けポートを伝え、サーバーが 20 番から接続しに来ます。パッシブモードでは、クライアントが PASV(または EPSV)を送り、サーバーが返した番号へクライアントが接続しに行きます。

データ接続の向き

アクティブクライアントが PORT で「ここに来て」と伝え、サーバーの 20 番がクライアントへ接続する。クライアント側のファイアウォール・NAT が外からの接続を止めると失敗する
↔
パッシブクライアントが PASV で「どこに行けばいい?」と聞き、サーバーが返した番号へクライアントから接続する。開けるのはサーバー側だけで済む

家庭・会社のネットワークから使うなら、ほぼパッシブ一択

アクティブモード:サーバーの 20 番からクライアントへ SYN が飛ぶ

vsftpd(2121 番)に対して epsv4 off・passive(オフ)で ls を打ったときの tcpdump です。IP ヘッダーの行と、各行の先頭にある TCP ヘッダー部分(記号に見える8文字)、長くなる options の欄は省いています(以下の tcpdump も同じ)。

$ tcpdump -i lo -nn -A 'tcp port 2121 or tcp port 20 or portrange 52100-52110'
17:49:26.561699 IP 127.0.0.1.48994 > 127.0.0.1.2121: Flags [P.], seq 62:85, ack 244, win 32742, (略)
PORT 127,0,0,1,190,93
17:49:26.561780 IP 127.0.0.1.2121 > 127.0.0.1.48994: Flags [P.], seq 244:295, ack 85, win 64, (略)
200 PORT command successful. Consider using PASV.
17:49:26.561821 IP 127.0.0.1.48994 > 127.0.0.1.2121: Flags [P.], seq 85:91, ack 295, win 32742, (略)
LIST
17:49:26.562068 IP 127.0.0.1.20 > 127.0.0.1.48733: Flags [S], seq 2917025089, win 65495, (略)

PORT 127,0,0,1,190,93 の後ろ2つの数字が待ち受けポートで、190 × 256 + 93 = 48733 です。直後に、サーバーの 20 番(127.0.0.1.20)からクライアントの 48733 番へ SYN(Flags [S])が飛んでいます。クライアントの手前にファイアウォールや NAT があると、この「外から入ってくる接続」が止められます。

パッシブモード:クライアントからサーバーの指定ポートへ SYN が飛ぶ

pyftpdlib(2122 番)に alice で入り、epsv4 off のまま(パッシブはオン)ls を打ったときです。

$ tcpdump -i lo -nn -A 'tcp port 2122 or portrange 52200-52210'
17:49:01.840660 IP 127.0.0.1.34286 > 127.0.0.1.2122: Flags [P.], seq 48:54, ack 328, win 32742, (略)
PASV
17:49:01.840908 IP 127.0.0.1.2122 > 127.0.0.1.34286: Flags [P.], seq 328:376, ack 54, win 64, (略)
227 Entering passive mode (127,0,0,1,203,241).
17:49:01.841086 IP 127.0.0.1.37906 > 127.0.0.1.52209: Flags [S], seq 3019674695, win 65535, (略)
17:49:01.841139 IP 127.0.0.1.34286 > 127.0.0.1.2122: Flags [P.], seq 54:60, ack 376, win 32742, (略)
LIST

227 Entering passive mode (127,0,0,1,203,241) の 203 × 256 + 241 = 52209 が、サーバーが用意したデータ用のポートです。今度は、クライアント(送信元 37906)からサーバーの 52209 番へ SYN が飛んでいます。サーバーは、起動時に決めた範囲(52200〜52210)の中から番号を選んでいました。

アクティブモード パッシブモード
クライアントが送る命令 PORT h1,h2,h3,h4,p1,p2(EPRT) PASV(EPSV)
データ接続を張る側 サーバー(送信元 20 番)→ クライアント クライアント → サーバーの指定ポート
開ける必要があるもの クライアント側の受け入れ(ファイアウォール・NAT の転送) サーバー側のパッシブ用ポートの範囲
手元の tcpdump 127.0.0.1.20 > 127.0.0.1.48733: Flags [S] 127.0.0.1.37906 > 127.0.0.1.52209: Flags [S]
向いている場面 サーバー側で外向きの接続を厳しく制限している ほとんどの場面(FileZilla の公式 Wiki も推奨)

パッシブモードでつまずく「227 に内側の IP が返る」

NAT の内側にあるサーバーが 227 Entering passive mode (10,0,0,5,...) のように内側の IP を返すと、インターネット側のクライアントはその IP に接続できず、一覧の取得で止まります。vsftpd は pasv_address(既定は接続を受けたソケットのアドレス)で外側の IP を指定でき、pyftpdlib にも同じ役割の masquerade_address があります。手元ではどちらも 127.0.0.1 を設定して確かめました。サーバーが明示的に EPSV(229 Entering Extended Passive Mode (|||52110|))に対応していれば、IP を含まないので、この問題は起きません。

FTPは平文:tcpdumpで見えたパスワード(自分の環境の中だけ)

この節では、「FTPは安全でない」と言われる理由が、自分のサーバーに自分で送ったパケットでどう見えるかが分かります。

FTP の制御接続は暗号化されないため、ユーザー名とパスワードはそのままの文字でネットワークを流れます。 自分で立てた pyftpdlib(127.0.0.1:2122)に自分の端末からログインし、ループバックの通信を tcpdump で取ったものです。

$ tcpdump -i lo -nn -A 'tcp port 2122'
17:49:01.839422 IP 127.0.0.1.34286 > 127.0.0.1.2122: Flags [P.], seq 1:13, ack 45, win 32742, (略)
USER alice
17:49:01.839552 IP 127.0.0.1.2122 > 127.0.0.1.34286: Flags [P.], seq 45:78, ack 13, win 64, (略)
331 Username ok, send password.
17:49:01.839667 IP 127.0.0.1.34286 > 127.0.0.1.2122: Flags [P.], seq 13:31, ack 78, win 32742, (略)
PASS s3cret-pass
17:49:01.839810 IP 127.0.0.1.2122 > 127.0.0.1.34286: Flags [P.], seq 78:101, ack 31, win 64, (略)
230 Login successful.

PASS s3cret-pass がそのまま読めます。ファイルの中身(データ接続)も同じく平文です。この記事では自分の環境の中の自分の通信だけを見ており、他人の通信を見ることは法律と規約に反します。見せたかったのは「隠れていない」という事実だけです。

同じ pyftpdlib を TLS 必須(2990 番)で起動し、curl で FTPS 接続した tcpdump では、AUTH SSL に対する 234 AUTH SSL successful. までが読める最後の行で、その後の USER・PASS・一覧はすべて暗号化された文字の並びでした。PASS という文字列を取得結果から探しても 0 件です。

$ grep -c PASS tcpdump_ftps.txt
0
$ grep -n 'AUTH SSL' tcpdump_ftps.txt      # 読める最後の返事
30:234 AUTH SSL successful.
$ sed -n '31,34p' tcpdump_ftps.txt          # 直後のクライアントの送信(TLS の Client Hello)
17:51:27.097478 IP 127.0.0.1.34882 > 127.0.0.1.2990: Flags [P.], seq 11:528, ack 71, win 64, (略)
N8.O...X............^....3.2.%l..b7".,5..A...<.!q.. .2)..........h.sr..Ll..v.:.r..4..>.......,.0....
  • 1インターネット越しに素の FTP でログインしないWi-Fi や経路の途中で読める形で流れる。SFTP か FTPS にする
  • 2FTP のパスワードを他のサービスと共用しないレンタルサーバーの FTP アカウントは、管理画面と別の文字列にする
  • 3書き込みが要らないサーバーは write_enable=NO手元の vsftpd は put が 550 Permission denied. になった
  • 4FTPS なら PROT P(データも暗号化)を必須にするFileZilla の公式 Wiki は、PROT P を強制しないとクライアントが PROT C でデータを平文にできる、と説明している

パケットの中身を画面で追う方法は、関連記事「Wiresharkの使い方|画面の見方・フィルター早見表を実例で解説」で扱っています。

FTPとSFTPの違い(FTPS・SCP・rsyncとの比較表)

この節では、名前が似ているFTP・FTPS・SFTPと、同じ用途に使うSCP・rsyncの違いが一覧で分かります。

SFTP は FTP の暗号化版ではなく、SSH の上で動く別のプロトコルです。FTP の暗号化版は FTPS(FTP over TLS)です。 名前の「S」の位置で区別します。

FTP FTPS SFTP SCP・rsync
正式名 File Transfer Protocol FTP over TLS(RFC 4217) SSH File Transfer Protocol Secure Copy/rsync over SSH
土台 TCP(RFC 959) FTP + TLS SSH SSH
ポート 21(+20 かパッシブ用) 21(explicit)/990(implicit)+データ用 22 の1本 22 の1本
暗号化 なし TLS(PROT P でデータも) すべて すべて
認証 ユーザー名・パスワード ユーザー名・パスワード(+証明書) パスワードか SSH 鍵 パスワードか SSH 鍵
ファイアウォール 2本の接続で複雑 2本の接続で複雑(中継装置が中身を読めず、さらに難しい) 22 番だけ 22 番だけ
向いている用途 閉じた網の中・匿名の公開配布 FTP の資産を残しつつ暗号化 サーバーの保守・レンタルサーバー コピー・同期(差分・再開)
1

FTPS

FTP の手順はそのままに、TLS で包む。explicit は 21 番に接続して AUTH TLS、implicit は 990 番で最初から TLS。

FTP のクライアント・サーバーが対応

2

SFTP

SSH の機能の1つ。サーバーに sshd があれば使え、sftp コマンドや FileZilla・WinSCP で操作する。

FTP とは互換性が無い

3

SCP

scp 元 先 の1行でコピー。OpenSSH 9.0 からは、scp コマンドの中身も SFTP プロトコルで転送する(-O で以前の方式)。

対話は無い

4

rsync

差分だけを送る同期。SSH の上で動かすのが一般的で、中断からの再開や削除の同期ができる。

バックアップ・デプロイ向き

SFTP・SCP のコマンドの使い方は関連記事「scp・sftpコマンドの使い方|オプション一覧と転送パターン集」、同期は関連記事「rsyncの使い方|オプション一覧と目的別コピペ例(実行結果つき)」で扱っています。

FTPS(AUTH TLS)の接続の実物と、暗号化の速度差

この節では、FTPSの接続が裏で何をしているかと、暗号化で転送がどれだけ遅くなるかの実測が分かります。

explicit FTPS は、素の FTP と同じポートに接続してから AUTH TLS(curl は AUTH SSL を先に試します)で TLS に切り替え、PBSZ 0・PROT P でデータ接続も暗号化します。 TLS 必須にした pyftpdlib(2990 番)へ、curl で接続した原文です(証明書は自分で作った自己署名のものを --cacert で渡しています)。

$ curl -v --ssl-reqd --cacert cert.pem -u alice:s3cret-pass ftp://127.0.0.1:2990/
< 220 RJC test FTP server ready (pyftpdlib).
> AUTH SSL
< 234 AUTH SSL successful.
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
* SSL connection using TLSv1.3 / TLS_AES_256_GCM_SHA384 / X25519 / RSASSA-PSS
* Server certificate:
*  subject: CN=127.0.0.1
*  SSL certificate verify ok.
> USER alice
< 331 Username ok, send password.
> PASS s3cret-pass
< 230 Login successful.
> PBSZ 0
< 200 PBSZ=0 successful.
> PROT P
< 200 Protection set to Private
> EPSV
< 229 Entering extended passive mode (|||52205|).
* Connecting to 127.0.0.1 (127.0.0.1) port 52205
* SSL connection using TLSv1.3 / TLS_AES_256_GCM_SHA384 / X25519 / UNDEF
> LIST
< 125 Data connection already open. Transfer starting.
< 226 Transfer complete.

TLS を必須にしたサーバーへ、暗号化せずに USER を送ると、次のように断られました。

$ curl -v -u alice:s3cret-pass ftp://127.0.0.1:2990/
< 220 RJC test FTP server ready (pyftpdlib).
> USER alice
< 550 SSL/TLS required on the control channel.
curl: (67) Access denied: 550

実測:20MB のダウンロードにかかった時間

同じ 20MB のファイルを、素の FTP(2122 番)と FTPS(2990 番)から curl で3回ずつ受け取った時間です(ループバックなので回線の速度ではなく、暗号化の処理の差が出ます)。

方式 1回目 2回目 3回目 速度(1回目)
FTP(平文) 0.0113 秒 0.0119 秒 0.0112 秒 約 1.86GB/s
FTPS(TLS 1.3・AES-256-GCM) 0.0388 秒 0.0392 秒 0.0470 秒 約 540MB/s
3.4倍FTPS の所要時間(対 FTP)20MB・ループバック・3回の中央値
540MB/sFTPS でも出た速度実際の回線(1Gbps ≒ 125MB/s)より速い
0件FTPS の取得結果にあった PASS の文字平文の FTP では 1 件

暗号化で3倍ほど時間が伸びましたが、それでも 1Gbps の回線で出せる速度を大きく上回っています。実際の利用では回線のほうが先に上限になるため、速度を理由に平文の FTP を選ぶ場面はほぼありません。

FileZillaの設定項目の読み方(公式ドキュメントで確かめた範囲)

この節では、FileZillaでFTP・FTPS・SFTPに接続するときに入力する項目と、接続できないときに見る設定が分かります。

入力するのは、ホスト・ユーザー名・パスワード・ポートの4つで、ポートは既定(FTP の 21、SFTP の 22)と違うときだけ入れます。 FileZilla の公式 Wiki(Using)に書かれている手順です。

1

クイック接続バーにホストを入れる

SFTP なら sftp:// を頭に付ける。FTPS(explicit)は ftpes://、implicit は ftps:// を付ける(FTP over TLS のページ)。

何も付けなければ素の FTP

2

ポートは既定と違うときだけ入れる

FTP は 21、SFTP は 22。implicit FTPS は通常 990。

空欄なら既定

3

ユーザー名・パスワードを入れて Quickconnect

空のままなら匿名(anonymous)でログインする。

Enter でも接続

4

残したい接続は Site Manager に保存する

クイック接続は直近10件しか残らない。接続後に File → Copy current connection to Site Manager... で保存。Site Manager は File → Site Manager... か、ツールバーの先頭のボタン。

Advanced タブで既定のフォルダー、Transfer Settings タブで同時接続数

接続できないときに見る設定(Network Configuration のページ)

  • パッシブモードが、ほとんどの場合で推奨されています。 クライアント側のファイアウォールでは、外向きの接続を任意のポートへ許す(サーバーが指定するポートは選べないため)。
  • アクティブモードを使うなら、ポートの範囲を指定し、50000 以上の範囲を選ぶ(50 個ほどあれば大抵は足りる)。NAT ルーターの内側なら、その範囲を自分の端末へ転送する。固定の外側 IP があれば設定画面に入れ、動的なら FileZilla に取得させる。
  • FileZilla 3 では、ネットワーク設定ウィザードの実行が勧められている。
  • FTPS で一度信頼した証明書は trustedcerts.xml(Windows は %APPDATA%\FileZilla\、Linux・macOS は ~/.config/filezilla/)に残る。証明書が変わって警告が出るときは、このファイルを編集するか名前を変える。

Windows 向けのクライアント WinSCP の使い方は、関連記事「WinSCPとは・使い方|ダウンロードから鍵認証・エラー対処まで」で扱っています。Microsoft の ftp コマンドのページ(Windows Server のコマンドリファレンス)には、パッシブモードを切り替える引数は載っていません。Windows で NAT の内側から FTP を使うなら、FileZilla か WinSCP のほうが迷いません。

vsftpdでFTPサーバーを立てる(確認した設定ファイル)

この節では、自分でFTPサーバーを立てて動きを確かめるときの、最小の設定ファイルと各項目の意味が分かります。

vsftpd は、設定ファイルを引数に渡すだけで、自分の好きなポートで起動できます。 この記事で使った設定です(ログの場所などは省いています)。

listen=YES
listen_ipv6=NO
listen_address=127.0.0.1
listen_port=2121              # 既定は 21
anonymous_enable=YES          # 匿名ログインを許す
local_enable=NO               # OS のユーザーでのログインは許さない(既定 NO)
write_enable=NO               # STOR・DELE などを許さない(既定 NO)
anon_root=/srv/s4/r17/t11/anon
pasv_enable=YES               # 既定 YES
pasv_min_port=52100           # パッシブ用の範囲(既定 0 = 任意)
pasv_max_port=52110
pasv_address=127.0.0.1        # 227 で返す IP(NAT の内側なら外側の IP)
port_enable=YES               # アクティブモードも許す(既定 YES)
connect_from_port_20=YES      # 送信元を 20 番にする(既定 NO。配布の見本では YES)
ftpd_banner=Welcome to the RJC test FTP server (vsftpd).
log_ftp_protocol=YES          # 命令と返事をログに残す
idle_session_timeout=120      # 既定 300 秒
data_connection_timeout=20    # 既定 300 秒
nopriv_user=nobody
secure_chroot_dir=/var/run/vsftpd/empty
$ vsftpd /srv/s4/r17/t11/vsftpd.conf &
$ ss -ltnp | grep 2121
LISTEN 0  32  127.0.0.1:2121  0.0.0.0:*  users:(("vsftpd",pid=18356,fd=3))

log_ftp_protocol=YES にすると、ログに命令と返事がそのまま残ります。通常ユーザーで匿名専用サーバーに入ろうとしたときの行です。

Thu Oct 29 17:50:08 2026 [pid 18602] FTP command: Client "127.0.0.1", "USER alice"
Thu Oct 29 17:50:08 2026 [pid 18602] [alice] FTP response: Client "127.0.0.1", "530 This FTP server is anonymous only."
  • OS のユーザーでログインさせるには local_enable=YES にします(PAM を通します)。この記事では OS の設定を変えないため、ユーザー名とパスワードで入る確認は pyftpdlib で行いました。
  • vsftpd の TLS は ssl_enable=YES と証明書の指定で有効になり、force_local_logins_ssl・force_local_data_ssl はどちらも既定が YES なので、有効にすると通常ユーザーは暗号化なしでは入れなくなります(公式の vsftpd.conf のページ)。
  • ASCII モードの改行変換(ascii_download_enable・ascii_upload_enable)は既定が NO で、手元でも TYPE A を受け付けたうえで中身はそのまま(LF のまま 28 バイト)返しました。

Pythonとcurlからの操作(ftplib・curl ftp://)

この節では、スクリプトからFTPを扱うときの最小の書き方と、実行した結果が分かります。

Python は標準ライブラリの ftplib、コマンドなら curl の ftp:// が、追加のインストールなしで使えます。

from ftplib import FTP
ftp = FTP()
print(ftp.connect("127.0.0.1", 2122))          # 220 ...
print(ftp.login("alice", "s3cret-pass"))       # 230 Login successful.
print(ftp.nlst())                              # ファイル名の一覧
with open("dl_notes.txt", "wb") as f:
    print(ftp.retrbinary("RETR notes.txt", f.write))   # ダウンロード
with open("readme.txt", "rb") as f:
    print(ftp.storbinary("STOR from_python.txt", f))   # アップロード
print(ftp.quit())
220 RJC test FTP server ready (pyftpdlib).
230 Login successful.
['big.bin', 'lf.txt', 'notes.txt', 'uploaded.txt']
226 Transfer complete.
226 Transfer complete.
221 Goodbye.

curl は、URL にパスを書くだけで一覧とダウンロードができ、-u でユーザー名とパスワード、-T でアップロードです。匿名サーバーの一覧と、パスワード違いの結果です。

$ curl ftp://127.0.0.1:2121/pub/
-rw-r--r--    1 65534    65534          28 Oct 29 08:48 readme.txt
-rw-r--r--    1 65534    65534     5242880 Oct 29 08:48 sample.bin

$ curl -u alice:bad ftp://127.0.0.1:2122/
curl: (67) Access denied: 530

FTPS にするには --ssl-reqd、SFTP にするには URL を sftp:// にします(手元の curl 8.5.0 は libssh 付きでした)。ログインに使うパスワードをコマンドの引数に書くと、シェルの履歴とプロセス一覧に残るため、スクリプトでは .netrc や環境変数に逃がします。

よくあるエラー/つまずき(原文つき)

この節では、FTPで接続やログインに失敗したときに出る文言と、見るべき場所が分かります。

接続の段階(つながらない)、ログインの段階(530)、データ接続の段階(425・一覧で止まる)、ファイルの段階(550)のどこで止まったかを、最初に切り分けます。 手元で再現した原文です(530 Login incorrect. だけは、vsftpd の本体に含まれる文言から取っています)。

原文 止まった段階・原因 見る場所・直し方
ftp: Can't connect to `127.0.0.1:2199': Connection refused 接続。そのポートで誰も待ち受けていない ポート番号・サーバーが起動しているか(ss -ltnp)
ftp: Can't connect to `10.9.9.2:21': Connection timed out
curl: (28) Failed to connect to 10.9.9.2 port 21 after 5002 ms: Timeout was reached
接続。返事が無い(経路の途中で捨てられている)。手元では2分ほど待って出た IP・ファイアウォール・VPN。ping や nc -zv ホスト 21 で 21 番に届くか
530 Authentication failed./530 Login incorrect. ログイン。ユーザー名かパスワードの誤り 大文字小文字・前後の空白・コピー時の改行。レンタルサーバーの FTP アカウントは管理画面で確かめる
530 This FTP server is anonymous only. ログイン。匿名専用のサーバーに通常ユーザーで入った ユーザー名を anonymous にするか、サーバーの local_enable
550 SSL/TLS required on the control channel. ログイン。TLS 必須のサーバーに平文で入った FTPS(ftpes://・--ssl-reqd)で接続する
425 Failed to establish connection./425 Can't connect to specified address. データ接続。アクティブモードでサーバーがクライアントへ接続できない パッシブモードに切り替える。クライアント側のファイアウォール・NAT
ログインは成功するが ls で止まる・タイムアウト データ接続。パッシブ用のポートがサーバー側で閉じている、227 に内側の IP が返っている サーバーのパッシブ用の範囲を開ける・pasv_address
425 Use PORT or PASV first. データ接続。PORT も PASV も送らずに LIST した 手で命令を送ったときに出る。クライアントを使えば起きない
500 Illegal PORT command. データ接続。PORT で制御接続と違う IP を指定した vsftpd が安全のため拒んだ。NAT 越しのアクティブモードはパッシブにする
550 Failed to open file. ファイル。名前の誤り・無いファイル ls で名前を確かめる(大文字小文字を区別する)
550 Permission denied. ファイル。書き込みが許されていない・ディレクトリの権限 サーバーの write_enable・ディレクトリの所有者と権限
421 Timeout. セッション。無操作が長く、サーバーが切った(手元の vsftpd は idle_session_timeout=120 で、ログイン後に何も送らず 120 秒で届いた) つなぎ直す。サーバー側は idle_session_timeout(既定 300 秒)

切り分けの順番です。

1

220 のあいさつが出るか

出なければ接続の問題(ホスト名・ポート・ファイアウォール)。Connection refused はポート違いか未起動、timed out は経路で捨てられている。

curl -v でも同じ行が見える

2

230 Login successful が出るか

530 ならユーザー名・パスワード・サーバーの種類(匿名専用・TLS 必須)。

サーバーのログに USER の行が残る

3

ls の一覧が出るか

ここで止まるならデータ接続。アクティブ↔パッシブを切り替え、サーバーのパッシブ用の範囲と 227 の IP を見る。

425 が出ればほぼ確定

4

get・put が通るか

550 はファイル名か権限。バイナリのファイルが壊れるなら TYPE I(binary)。

サーバー側の権限は ls -l で

FTPを使うべきか:判断表

この節では、これからファイルの転送手段を選ぶときに、FTP・FTPS・SFTP・rsync のどれにするかが決められます。

  1. 1サーバーに SSH で入れる → SFTP(対話)か rsync(同期)22 番だけ。鍵認証が使える。追加のサーバーソフトが要らない
  2. 2相手が FTP しか受け付けない(取引先・機器) → FTPS を頼むexplicit(21 番+AUTH TLS)が主流。PROT P を必須に
  3. 3レンタルサーバーの案内が FTP → 管理画面で SFTP か FTPS の有無を見る多くの事業者が FTPS か SFTP を用意している。FileZilla なら URL の頭を変えるだけ
  4. 4閉じた網の中の機器(複合機・組み込み)が FTP でしか送れない → 素の FTP を網の中だけで書き込み専用のアカウント・インターネットからは届かない場所に
  5. 5誰でも取れる配布物 → HTTPS で公開するブラウザは FTP を開けない。匿名 FTP は CDN や HTTPS に置き換わっている
場面 選ぶもの 理由
Web サイトのファイルをレンタルサーバーへ上げる SFTP(無ければ FTPS) パスワードを平文で流さない。FileZilla・WinSCP で操作は同じ
サーバー間のバックアップ・同期 rsync over SSH 差分だけ送る。中断から再開できる
1ファイルをすぐ送る scp か sftp 1行で終わる
取引先との定期的なファイル交換(FTP 指定) FTPS(explicit) FTP の手順のまま暗号化。先方のクライアントも対応しやすい
インターネットから素の FTP でログインする 避ける tcpdump の節のとおり、パスワードがそのまま流れる

よくある質問

Q. FTPとは何ですか? A. ネットワーク越しにファイルを送受信するための通信の決まり(プロトコル)です。RFC 959 で定められ、命令用の接続(21 番)とデータ用の接続の2本を使います。暗号化の仕組みは無く、ユーザー名とパスワードはそのままの文字で流れます。

Q. FTPのポート番号は何番ですか? A. 命令用が TCP 21 番です。データ用は、アクティブモードではサーバーの 20 番から、パッシブモードではサーバーが 227 の返事で指定した番号です。FTPS の implicit は 990 番、SFTP は SSH の 22 番です。

Q. FTPとSFTPの違いは何ですか? A. SFTP は SSH の上で動く別のプロトコルで、FTP とは互換性がありません。22 番の1本で命令もデータも暗号化され、SSH 鍵で認証できます。FTP の暗号化版は FTPS(FTP over TLS)です。

Q. FTPSとSFTPはどちらを使うべきですか? A. サーバーに SSH で入れるなら SFTP が簡単です(22 番だけ、追加のサーバーソフト不要)。相手が FTP の仕組みしか持たない、FTP 用の運用が残っている、というときは FTPS です。FTPS はデータ接続が別なので、ファイアウォールの設定は FTP と同じ手間がかかります。

Q. アクティブモードとパッシブモードはどちらにすればよいですか? A. ほとんどの場合パッシブモードです。アクティブモードはサーバーからクライアントへ接続しに来るため、クライアント側のファイアウォールや NAT で止まります。手元の tcpdump でも、アクティブではサーバーの 20 番からの SYN、パッシブではクライアントからの SYN が見えました。

Q. ログインはできるのに一覧(ls)で止まります。 A. データ接続が張れていません。アクティブモードならパッシブに切り替え、パッシブならサーバー側のパッシブ用のポートの範囲が開いているか、227 の返事に NAT の内側の IP が入っていないかを見ます。

Q. 530 Login incorrect が出ます。 A. ユーザー名かパスワードの誤りです。大文字小文字、前後の空白、コピーしたときの改行を見直します。サーバーが匿名専用なら 530 This FTP server is anonymous only.、TLS 必須なら 550 SSL/TLS required のように、別の文言になります。

Q. ブラウザで ftp:// を開けないのはなぜですか? A. Chrome は 95 で FTP の URL への対応を取り除きました(Chrome Developers のブログ)。FTP のサーバーには FileZilla・WinSCP などのクライアントか、ftp・curl のコマンドで接続します。

Q. FTPでファイルが壊れます。 A. 画像や ZIP などを ASCII モードで転送すると壊れることがあります。binary(TYPE I)にします。手元の vsftpd と pyftpdlib は既定で ASCII モードでも中身を変えませんでしたが、サーバーの設定(vsftpd なら ascii_download_enable)によって改行が変換されます。

Q. 匿名FTP(anonymous)とは何ですか? A. ユーザー名 anonymous(または ftp)、パスワードにメールアドレスなどを入れて、誰でも入れる公開サーバーです。手元の vsftpd では anonymous_enable=YES・write_enable=NO で、読み取りだけの匿名サーバーになりました。

Q. FTPは今でも使われていますか? A. レンタルサーバーの案内、取引先とのファイル交換、複合機や組み込み機器の送信先として残っています。新しく選ぶなら SFTP か FTPS で、素の FTP はインターネットに出ない閉じた網の中に限ります。

Q. curlやPythonからFTPを使えますか? A. curl は curl -u ユーザー:パスワード ftp://ホスト/パス、Python は標準の ftplib で FTP().login()・retrbinary()・storbinary() が使えます。どちらも手元で一覧・ダウンロード・アップロードが通りました。

まとめ

  • FTP は、命令用の制御接続(21 番)とデータ用の接続(20 番かパッシブ用の範囲)の2本でファイルを運ぶ、暗号化の無いプロトコル。
  • ftp コマンドの ls・get・put は、裏では LIST・RETR・STOR に置き換わり、サーバーは 220・331・230・150・226 のような3桁の番号で答える。
  • アクティブモードはサーバーの 20 番からクライアントへ、パッシブモードはクライアントからサーバーの指定ポートへ接続する。手元の tcpdump で SYN の向きが逆だった。ほとんどの場面でパッシブ。
  • 自分の環境の tcpdump で、PASS s3cret-pass がそのまま読めた。FTPS にすると 234 AUTH SSL successful. より後は読めず、20MB の転送は約 3.4 倍の時間でも 540MB/s は出た。
  • 今から選ぶなら SFTP(SSH の 22 番だけ)か FTPS。素の FTP は閉じた網の中に限る。

参考・出典

確認日はいずれも 2026年10月29日です。

  • IETF「RFC 959 File Transfer Protocol (FTP)」:https://www.rfc-editor.org/rfc/rfc959
  • IETF「RFC 4217 Securing FTP with TLS」:https://www.rfc-editor.org/rfc/rfc4217
  • vsftpd「vsftpd.conf - config file for vsftpd」:https://security.appspot.com/vsftpd/vsftpd_conf.html
  • pyftpdlib「Tutorial」:https://pyftpdlib.readthedocs.io/en/latest/tutorial.html
  • FileZilla Wiki「Using」:https://wiki.filezilla-project.org/Using
  • FileZilla Wiki「Network Configuration」:https://wiki.filezilla-project.org/Network_Configuration
  • FileZilla Wiki「FTP over TLS」:https://wiki.filezilla-project.org/FTP_over_TLS
  • OpenSSH「OpenSSH 9.0 release notes」:https://www.openssh.org/txt/release-9.0
  • Chrome Developers「Deprecations and removals in Chrome 95」:https://developer.chrome.com/blog/deps-rems-95
  • Microsoft Learn「ftp」(Windows コマンド):https://learn.microsoft.com/ja-jp/windows-server/administration/windows-commands/ftp
  • curl「curl.1 the man page」:https://curl.se/docs/manpage.html
  • Python「ftplib — FTP protocol client」:https://docs.python.org/3/library/ftplib.html

本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。

(記載例)出典:株式会社RJC「FTPとは|仕組み・ポート・SFTPとの違いをtcpdumpの実物で」

株式会社RJC ― SI事業・SES事業・AI駆動開発。RJCは一緒に成長を楽しめる会社です。

WE ARE HIRING

RJCで一緒に開発しながら、
成長を楽しみませんか?

RJCは、Web・モバイル・AIを活用した開発プロジェクトで、テックリードやPM・PMOも活躍するシステム開発会社です。会社を知る、待遇を確かめる、話を聞いてみる。気になるところ見てみてください!

  • 127日年間休日
  • 12時間平均残業時間
  • 毎日ガチャ遊びココロも大切にする福利厚生。アマギフなどの賞品ラインナップ!

ほかにも、チケットレストラン、書籍読み放題、2年ごとの慰労報奨(休暇 or 金一封)、11期連続の黒字決算。

ABOUT RJC RJCがどんな会社か知る 考え方、研修、働き方、福利厚生、社員の前職まで。RJCのことが丸わかり! RJC丸わかりページへ JOB DESCRIPTION 仕事内容・待遇を見てみる 仕事内容、給与・待遇、選考の流れ。経験者も未経験も!応募前に知りたいこと、まとめました! 募集要項を見る ENTRY エントリーする エントリーは1〜2分・履歴書不要です。まずは話を聞いてみたい、という方でも歓迎です! エントリーフォームへ

RJCで一緒に開発しながら、 成長を楽しみませんか?