ByteScope

21

ポート 21 · FTP

TCPIANA 割り当てありファイル転送

FTP の制御用コネクション。コマンドと 3 桁の応答コードが流れるのはこのポートで、ファイルの中身そのものは、ファイアウォールに誰も教えていない別のポートの上を流れます。

ポート 21 を使っているプロセスを特定する

自分の環境の行をそのまま実行してください。ポートを掴んでいるプロセス名と、バインドしているアドレスが出ます。たいていはそれだけで答えが分かります。

外側から確かめる

`nmap -Pn -p 21 files.example.com` は、ホストの外から見て本当に知りたい一点だけを答えます。`-Pn` を付けるのは、ping を無視するマシンをスキャン対象から外させないためです。答えの意味は nmap 自身の定義で決まります。`open` はそのポートで実際にアプリケーションが接続を受け付けているということ。`closed` は到達できて応答も返ったが、待ち受けているアプリケーションがいないということ。`filtered` はパケットフィルタがプローブをポートまで届かせなかったということで、この場合 nmap には前の 2 つのどちらだったかが分かりません。`--reason` を付ければ何が決め手だったか——closed なら返ってきたリセット、filtered なら無反応——が見えますし、`-sV` を付ければ `220` の挨拶バナーを読んで、たいていはデーモン名とバージョンまで教えてくれます。このポート特有の注意が一つ。このスキャンはデータ用コネクションについては何も語りません。パッシブ転送が使うのはスキャンが触れもしない高位ポートだからです。21 番が `open` なのにダウンロードが 0 バイトで死ぬ、という組み合わせは矛盾なく成立します。スキャンは自分が責任を持つホストにだけ。

21 につながらないときの読み方

出ているもの意味
ftp: connect: Connection refusedパケットはホストまで届き、21 番を持つプロセスがないのでカーネルがリセットを返しました。デーモンが止まっているか、起動に失敗しているか、あなたが叩いたアドレスを含まない場所にバインドしています。上のコマンドは手元のノート PC ではなくサーバー側で実行し、行があることを確認するだけでなくバインドアドレスまで読んでください。
The client sits silent for tens of seconds, then reports Connection timed out何も返ってきていません。パケットフィルタが SYN を黙って捨てています。クラウドのセキュリティグループ、ホスト上のファイアウォール、あるいは経路上のネットワーク ACL のどれかです。拒否なら即座に返り、破棄なら待たされます。この待ち時間そのものが診断結果です。外から `nmap --reason` で確かめてください。`filtered` が破棄、`closed` が拒否です。
425 Can't open data connection21 番は問題ありません。ログインできていてサーバーもコマンドを受け付けたからこそ、番号付きの応答が返っているのです。失敗しているのは 2 本目のコネクションのほうです。パッシブモードなら、サーバーが指定した高位ポートへあなたのファイアウォールが出してくれなかったか、サーバー側のパッシブ用の範囲が外から開いていないかのどちらか。アクティブモードなら、サーバーがクライアントへ接続を返そうとして途中で塞がれています。モードを切り替えてどちらが通るか見てください。多くのクライアントは `passive` で切り替わりますし、`curl` は `-P -` を渡さない限りパッシブです。
500 Illegal PORT commandサーバーがアクティブモードそのものを拒否しています。折り返しの接続がよく知られた悪用経路なので、今はそうする実装が多いのです。パッシブモードを使ってください。NAT が `PORT` コマンドの中のアドレスを書き換えた結果、サーバーから見て制御用コネクションの相手と一致しないアドレスが指定された場合も同じ見た目になります。これはサーバーが意図的に弾いています。
227 Entering Passive Mode reports an address you cannot route toNAT の内側にいるサーバーに外向きのアドレスを教えていないと、自分のプライベートアドレスをそのまま広告してしまいます。クライアントは律儀に 10.0.0.5 のような相手へデータ用コネクションを開こうとして、そのまま固まります。直すのはサーバー側です。広告するべき外部アドレスを設定するか、ポート番号だけを返して制御用コネクションのアドレスを流用する拡張版の `EPSV` を使ってください。
530 Login incorrectここにポートの問題は 1 つもありません。制御用コネクションは張れていて、サーバーは資格情報を読んだうえで拒否しています。アカウントかパスワードが違うか、アカウントはあるのに FTP だけ拒まれているかのどちらかです。後者はシェルが `/usr/sbin/nologin` になっている、サーバーの拒否リストに名前が載っている、chroot された仮想ユーザーしか許可しない設定になっている、あたりが定番です。
500 OOPS: could not bind listening IPv4 socket / bind: Address already in use`EADDRINUSE` です。既に誰かがソケットを持っていて、デーモンは動き出してから落ちるのではなく起動の途中で終わります。たいていは別パッケージで入った 2 つ目の FTP サーバーか、21 番をホストに公開しているコンテナです。何かを kill する前に上のコマンドで持ち主を特定してください。1、2 分待ってポートが自然に空くなら、前のプロセスが残した `TIME_WAIT` のソケットだったということで、kill する必要は最初からありませんでした。
bind: Permission denied while starting the server on 21こちらは本当に特権ポートの話です。Unix 系ではポート 1024 未満に root が要り、21 番はその中に入ります。init システム経由で root として起動するか、Linux ならバイナリに `CAP_NET_BIND_SERVICE` を与えるか、高い番号で待ち受けて転送してください。ただし SELinux や AppArmor のホストでは、ポリシーがそのバイナリの bind を拒否したときも同じ文言が出ます。1024 の規則だと決めつける前に監査ログを見てください。

ポート 21 で動いているもの

IANA は RFC 959 を根拠に 21 番を `ftp`、つまり File Transfer Protocol の制御用コネクションに割り当てていて、隣の 20 番は `ftp-data` として登録されています。TCP と UDP の両方が登録されていますが、実際に使われるのは TCP だけです。このポートで一番役に立つ知識は、コネクションが 2 本に分かれているという一点に尽きます。セッションは 21 番の上に開き、`USER`、`PASS`、`LIST`、`RETR` と打ち込んだ内容も、サーバーが返す数字の応答も、すべて読める ASCII のままそこを流れます。ただしファイルの中身は 1 バイトも流れません。転送のたびに 2 本目の TCP コネクションが張られ、そのときどちら側から接続しに行くかで、ファイアウォールを通るかどうかが決まります。アクティブモードではクライアントが `PORT`(RFC 2428 なら `EPRT`)を送り、サーバーの側からクライアントへ接続を返します。今どきの NAT とクライアント側のファイアウォールは、まずこれを通しません。パッシブモードではクライアントが `PASV` を送り、サーバーが `227 Entering Passive Mode (h1,h2,h3,h4,p1,p2)` と答えます。末尾の 2 つの数字がポート番号で、実際の値は `p1 * 256 + p2` です。あるいは `229 Entering Extended Passive Mode (|||port|)` が返り、クライアントはそこへ接続しに行きます。今はどれもパッシブが既定なので、FTP サーバーには 21 番だけでなくデータ用ポートの範囲もあわせて開けてやる必要があります。そしてもう一つ、多くの人をこのページに連れてくる名前の罠があります。FTPS と SFTP は同じものの別表記ではありません。FTPS は RFC 4217 が FTP に TLS を足したもので、クライアントが同じ 21 番の上で `AUTH TLS` を送り、そのまま暗号化された状態で続きます。最初から暗号化して始まる古い方式のほうには、IANA が 990 番を `ftps` として別に割り当てています。対して SFTP は、どう解釈しても FTP ではありません。22 番の SSH のサブシステムであって、コマンドも応答コードも 2 本目のコネクションも FTP とは何一つ共有していませんし、開けるべきポートは 22 番ひとつだけです。

ポート 21 を外部に開けてよいか

平文の FTP をインターネットに出さないでください。パスワードは telnet とまったく同じように 21 番の上を平文で流れますし、公開されたリスナーは数時間で全世界スキャナーに見つかり、そのまま匿名アクセスとベンダーの初期設定を順に試されます。FTP サーバーが他より漏れやすいのは、だいたい次の 2 つの習慣のせいです。1 つのファイルを渡すために有効にした匿名読み取りが、そのまま切られずに残っていること。もう 1 つは、ユーザーごとの chroot をしていないせいで、認証を通ったアカウントが自分のディレクトリの外まで歩けてしまうことです。ただ誰かにファイルを渡したいだけなら、443 番の HTTPS のほうが露出はずっと少なくて済みます。対話的にファイルを触りたいなら、22 番の SSH 越しの SFTP なら開けるポートは 1 つ、しかもホスト鍵の検証つきで、コマンドも中身もまとめて暗号化されます。それでも FTP を残さざるを得ないとき——機器の仕様、測定器、変えてくれない取引先——は、`AUTH TLS` を使う明示的な FTPS を必須にしてください。そのうえで、制御用コネクションを守っても転送そのものは守られないことを頭に入れておく必要があります。データ用コネクションが暗号化されるのはクライアントが `PROT P` まで要求したときだけなので、ログインは TLS で守られているのにファイルは平文で流れている、という状態が普通に成立します。パッシブ用のポート範囲はサーバー側の設定で固定して、ファイアウォールの穴を高位ポート全域ではなく狭い窓にしてください。送信元アドレスでも絞り、NAT が隠してくれていると信じる前に、ルーターが実際に何を転送しているかを確認してください。

サービス
FTP
トランスポート
TCP
登録状況
IANA 割り当てあり
カテゴリ
ファイル転送

このサイトのツール

どれもブラウザ内で完結します。アップロードは発生しません。

関連するポート

21 を調べているとき、ついでに確認することになりがちなポートです。

よくある質問

明らかに使用中なのに、コマンドが何も表示しないのはなぜ?

ほぼ権限の問題です。lsofss はソケット自体は出しますが、他ユーザーのプロセスは所有者の列を伏せるので、システムアカウントやコンテナランタイム、launchd が起動したサーバーは sudo を付け直すまで持ち主不明のリスナーに見えます。Windows は逆で、netstat には何も出ないのに bind だけ失敗します。これは Hyper-V や WSL2、Docker Desktop が起動時に予約したポート帯に当たっている状態です。

ポートを掴んでいるプロセスは kill してよい?

何なのかを先に見てください。取り残された開発サーバーなら問題ありませんが、書き込み中のデータベースは別ですし、他が依存しているシステムサービスも同様です。持ち主がコンテナならコンテナごと停止してください。ホストから見えるプロセスを kill してもランタイムが再起動するだけです。どうしても止められないものなら、自分のサービスを別のポートへ移すほうが早く片付きます。

ローカルからは届くのに、別のマシンからは届かないのはなぜ?

0.0.0.0 ではなく 127.0.0.1 にバインドしているからです。各ページのコマンドがプロセス名と並べてバインド先アドレスを出しているのはこのためで、ループバックにバインドしたものはファイアウォールの設定に関係なく自分のマシンからしか届きません。最近は意図的にそれを既定にしているフレームワークも多いので、たいていはバグではなくフラグの問題です。すでに 0.0.0.0 なのに届かないなら、次に疑うのはホストのファイアウォールかクラウドのセキュリティグループです。

珍しいポート番号に移すと安全になる?

ほとんどなりません。インターネット全体を舐めるスキャナーはポート範囲を丸ごと走査し続けているので、稼げるのは数時間であって安全ではなく、代わりに関係者全員がその番号を覚える羽目になります。既定ポートを狙う無差別スキャンのログが減るという効果は確かにありますが、それだけです。結果を変えるのは認証と、送信元アドレスを絞ったファイアウォールと、そもそも外に出さないことです。

ポート 21 でまだ詰まっていますか。ポート一覧をすべて見る。あるいは上に戻って、実際に出たエラー文から追ってください。