5900
VNC が話す RFB プロトコルのベースポート。ビューアがつながらないのに、サーバーは 5901 で平然と動いている——その理由もここにあります。
自分の環境の行をそのまま実行してください。ポートを掴んでいるプロセス名と、バインドしているアドレスが出ます。たいていはそれだけで答えが分かります。
sudo lsof -nP -iTCP:5900 -sTCP:LISTEN`-n` と `-P` でアドレスもポートも数値のまま保つので、NAME の列は `*:rfb` ではなく `*:5900` と読めます。`-iTCP:5900` でポートを選び、`-sTCP:LISTEN` で待ち受けソケットだけを残します。COMMAND が持ち主、PID が手を出す番号、NAME がバインドアドレスで、`*:5900` は全インターフェイス、つまり画面共有なら、この Mac に経路のある人は誰でも試せる状態です。ここでの `sudo` は省略できません。画面共有のリスナーはシステムアカウントのものなので、特権のない `lsof` は何も出さず、塞がっているポートが空きに見えます。`-sTCP:LISTEN` を外せば確立済みのビューアのセッションも見えるので、誰かが既につながっていることに気づけます。
sudo ss -tlnp 'sport >= :5900 and sport <= :5910'単一のポートではなく範囲を見てください。どれが使われるかはディスプレイ番号で決まります。`-t` で TCP ソケット、`-l` で待ち受けのみ、`-n` でサービス名の解決を飛ばし、`-p` で所有プロセスを出します。`sport` は送信元ポートを比較し `<`・`<=`・`=`・`!=`・`>=`・`>` を受け付けるので、範囲も一つの式で書けます。5901 の行はディスプレイ `:1`、5902 なら `:2` という具合です。Local Address:Port の列が、SSH トンネルを待っているループバック限定の `127.0.0.1:5901` と、ネットワーク全体から届く `0.0.0.0:5901` を分けます。持ち主は `users:(("Xvnc",pid=2210,fd=8))` と出ます。`ss` がなければ `sudo netstat -tlnp | grep -E ':59[0-9][0-9]'` が、スラッシュ区切りの pid/program の列で同じ絵を出します。どちらも自分の所有でないプロセスを名指しするには特権が必要です。
netstat -ano | findstr ":59"同じくディスプレイ番号の事情から、厳密なポートではなく接頭辞で一致させます。`-a` ですべての接続と待ち受けポートを表示し、`-n` でアドレスとポートを数値のまま保ち、`-o` で最後の列に所有プロセス ID を足します。Local Address の列を読んで `5900`・`5901` のどれが実際にバインドされているか、そしてそれが `0.0.0.0` なのか `127.0.0.1` なのかを確かめ、その行をサーバーと見なす前に State が LISTENING であることを条件にしてください。そのうえで `tasklist /FI "PID eq 3320"` でプロセス名を引きます。この PID フィルタは eq・ne・gt・lt・ge・le を取り、出てくるのは `tvnserver.exe` や `winvnc.exe` あたりです。`findstr` は部分一致なので、`:59` のような広いパターンは無関係な高いポートも拾います。動く前に番号を最後まで確認してください。
Get-NetTCPConnection -LocalPort 5900 | Select-Object LocalAddress,LocalPort,State,OwningProcess上の部分一致探しに対する厳密一致版で、疑わしいディスプレイ番号ごとに実行する価値があります。`State` が `Listen` で `LocalAddress` が `127.0.0.1` なら、意図的にこのマシンに限定されたサーバー——安全な構成であり、同時にリモートのビューアが拒否される理由でもあります。`OwningProcess` を `Get-Process -Id` に渡せば実行ファイルが分かります。範囲内のどのポートでも結果が空なら VNC サーバーは一つも動いていないので、ビューアの拒否は謎ではなく正確です。
打つ価値があるのは `nmap -Pn -p 5900-5910 host.example.com` のほうです。単一のポートを見ても問いの半分にしか答えられません——サーバーはディスプレイ `:1` のために 5901 にいるかもしれないからです。`-Pn` はホスト探索を飛ばすので、ping を無視するホストもスキャンされます。nmap の状態には正確な意味があります。`open` は対象上のアプリケーションが待ち受けている、`closed` はホストは答えたがそこには誰もいない、`filtered` はファイアウォールやフィルタ、その他のネットワーク上の障害物がプローブを塞いでいて nmap にはどちらか判断できない、です。VNC では `closed` の 5900 と `open` の 5901 が並んだ 1 行が、そのまま診断結果になります。`--reason` で各状態を決めたパケットが分かり、`-sV` を付ければ RFB のバナーを読んでプロトコルバージョンと実装まで報告します。スキャンは自分が責任を持つホストにだけ。
| 出ているもの | 意味 |
|---|---|
The viewer reports connection refused on 5900 while the VNC server is definitely running | ほぼ確実にディスプレイ番号の計算です。RFC 6143 はサーバー N を 5900+N に置くので、`vncserver :1` は 5901 にいて、5900 には何もいません。ホスト名だけを渡されたビューアは 5900 を叩き、正しく拒否されます。ビューアの書式に応じて `host:1` か `host::5901` と入力し、単一ポートではなく範囲でスキャンして確認してください。 |
The viewer hangs and eventually times out instead of failing immediately | 何も答えていないので、拒絶ではなく破棄です。ホストのファイアウォール、クラウドのセキュリティグループ、あるいは経路上の ACL。拒否は即座に返り、破棄は接続タイムアウトいっぱいかかります。`nmap --reason` が名前を付けてくれます——破棄なら `filtered`、拒否なら `closed`。そしてこれは、サーバーを正しくループバックにバインドしたうえで SSH トンネルを忘れたときにも出る、想定内の結果です。 |
The server will not start: the display or port is already in use, or bind fails with Address already in use | 5900+N での `EADDRINUSE` です。そのディスプレイの前の `Xvnc` がまだ生きているか、kill されたものが残したロックファイルのせいでポートは空いているのにディスプレイだけ埋まって見えるかのどちらかです。エラー文だけでは二つを見分けられないので、まず自分の環境のコマンドでポートを確認してください。別のディスプレイ番号で起動すれば回避でき、正しいプロセスを kill すれば解決します。 |
No matching security types | TCP の接続は成功し、RFB のハンドシェイクもセキュリティのネゴシエーションまで進んで、そこでサーバーの一覧とビューアの一覧に共通するものが一つもありませんでした。よくあるのは、サーバーが VNC Authentication しか提示していないのにビューアが暗号化されたベンダー拡張を必須に設定されているケースや、このビューアが実装していない独自タイプをサーバーが出しているケースです。二つのプログラム間の設定のずれであってネットワークの障害ではないので、ポートには触るところがありません。 |
A long password is accepted, and so are its first eight characters | サーバーのバグではありません。VNC Authentication は DES の鍵を、パスワードを 8 文字に切り詰めるか右側にヌルバイトで詰めて作るので、9 文字目以降は両側で捨てられます。セッションを攻撃する側が探索すべきなのは常に 8 文字ぶんだけで、だからこそ RFC 6143 自身がこの方式を暗号学的に弱く、信頼できないネットワークには不適切だと呼んでいます。 |
lsof or ss prints nothing, yet the port is clearly busy | 権限のケースです。どちらのツールも `sudo` なしでは自分が所有するプロセスしか出さないので、別のユーザーが起動した VNC サーバー、macOS の画面共有のようなシステムサービス、あるいはコンテナの中のものは見えません。ポートが空いていると結論づける前に `sudo` を付けて再実行してください。そして持ち主が Docker のプロセスだと分かったら、プロセスではなくコンテナを止めてください。スーパーバイザーが公開し直すだけです。 |
The session connects, but the screen is blank or shows only a grey background and an X cursor | ポートも認証も通っているので、これはネットワークの問題ではまったくありません。単体の `Xvnc` のディスプレイは、ウィンドウマネージャーが起動されるまでデスクトップセッションが何も付いていない状態で始まります。それを起動するのはサーバーの起動スクリプトの仕事です。ポートではなく、そのディスプレイに対する VNC サーバー自身のログを見てください。 |
5900 は Remote Framebuffer プロトコルのベースポートで、RFC 6143 として標準化され、IANA には `rfb` として登録されています。全員が引っかかる計算について、RFC は明確です。「RFB クライアントは TCP ポート 5900 でサーバーに接続する。複数の RFB サーバーがあるシステムでは、サーバー N は通常ポート 5900+N で待ち受ける。X Window サーバーがポート 6000+N で待ち受けるのと同様である」。つまり Unix の `vncserver` がディスプレイ `:1` で起動したなら、待ち受けているのは 5901 であって 5900 ではありません。そして 5901 は IANA のレジストリには存在しません。登録されているのはベースの番号だけです。ビューアにホスト名だけを打ち込むと 5900 を叩きに行き、そのマシンではそこに何もいないことが非常に多い——「接続が拒否されました」が VNC で最もありふれた症状であり、しかもほぼ確実に思っているのとは違う意味である理由がこれです。実際に何がポートを持っているかはプラットフォームによって違い、探しに行くときに効いてきます。macOS では内蔵の画面共有と Apple Remote Desktop が 5900 を直接使い、Apple 自身のポート一覧も RFC 6143 を参照して `rfb` と記しています。Linux なら TigerVNC や TightVNC の `Xvnc`、あるいは既存のディスプレイに取り付く `x11vnc`。Windows なら TightVNC の `tvnserver` のようなサービスです。どれも同じハンドシェイクを話すので、あるプロジェクトのビューアが別のプロジェクトのサーバーにつながるのが普通です——両者がセキュリティタイプで折り合えなくなる、その一点までは。
5900 をインターネットに出さないでください。そして VNC のパスワードを防御と勘違いしないでください。RFC 6143 がコアプロトコルで定義しているセキュリティタイプはたった三つ、0 の Invalid、1 の None、2 の VNC Authentication だけです。タイプ 1 は認証がまったくないという意味で、インターネットに露出したサーバーの相当数が今もこれを提示しています。タイプ 2 もほとんど変わりません。サーバーがランダムな 16 バイトのチャレンジを送り、クライアントがパスワードを鍵として DES で暗号化するのですが、そのとき「パスワードは 8 文字に切り詰められるか、右側にヌルバイトで詰められる」のです。どれだけ長いパスワードを打っても、鍵空間は 8 文字ぶんしかありません。RFC 自身のセキュリティ考察も率直で、この方式は「暗号学的に弱いことが知られており、信頼できないネットワークでの使用は意図されていない。多くの実装は、IPsec や SSH が提供する暗号化されたチャネル上でセッションを走らせるなど、より強いセキュリティを使いたいと考えるだろう」と書いています。コアプロトコルにはセッションを暗号化する仕組みもないので、フレームバッファも、そこに打ち込むものも全部、平文でネットワークを渡ります。サーバーはループバックにバインドして、`ssh -L 5901:127.0.0.1:5901 user@host` のようなトンネル越しに `127.0.0.1:5901` へビューアを向けてください。ベンダー拡張で TLS や強い認証を足せますが、あくまで拡張なので、両端が同じものを実装している必要があります。実装していないときに出るのが、まさにセキュリティタイプのネゴシエーション失敗です。
どれもブラウザ内で完結します。アップロードは発生しません。
5900 を調べているとき、ついでに確認することになりがちなポートです。
ほぼ権限の問題です。lsof や ss はソケット自体は出しますが、他ユーザーのプロセスは所有者の列を伏せるので、システムアカウントやコンテナランタイム、launchd が起動したサーバーは sudo を付け直すまで持ち主不明のリスナーに見えます。Windows は逆で、netstat には何も出ないのに bind だけ失敗します。これは Hyper-V や WSL2、Docker Desktop が起動時に予約したポート帯に当たっている状態です。
何なのかを先に見てください。取り残された開発サーバーなら問題ありませんが、書き込み中のデータベースは別ですし、他が依存しているシステムサービスも同様です。持ち主がコンテナならコンテナごと停止してください。ホストから見えるプロセスを kill してもランタイムが再起動するだけです。どうしても止められないものなら、自分のサービスを別のポートへ移すほうが早く片付きます。
0.0.0.0 ではなく 127.0.0.1 にバインドしているからです。各ページのコマンドがプロセス名と並べてバインド先アドレスを出しているのはこのためで、ループバックにバインドしたものはファイアウォールの設定に関係なく自分のマシンからしか届きません。最近は意図的にそれを既定にしているフレームワークも多いので、たいていはバグではなくフラグの問題です。すでに 0.0.0.0 なのに届かないなら、次に疑うのはホストのファイアウォールかクラウドのセキュリティグループです。
ほとんどなりません。インターネット全体を舐めるスキャナーはポート範囲を丸ごと走査し続けているので、稼げるのは数時間であって安全ではなく、代わりに関係者全員がその番号を覚える羽目になります。既定ポートを狙う無差別スキャンのログが減るという効果は確かにありますが、それだけです。結果を変えるのは認証と、送信元アドレスを絞ったファイアウォールと、そもそも外に出さないことです。
ポート 5900 でまだ詰まっていますか。ポート一覧をすべて見る。あるいは上に戻って、実際に出たエラー文から追ってください。