5900
連接埠 5900 · VNC
VNC 講的 RFB 協定的基準連接埠——也是為什麼檢視器死都連不上,而伺服器好端端地坐在 5901。
查出是誰占用連接埠 5900
照你的系統挑一行貼上去執行。它會直接印出占著這個連接埠的行程,以及它綁在哪個位址上——通常看到這兩件事答案就出來了。
- macOS
sudo lsof -nP -iTCP:5900 -sTCP:LISTEN`-n` 和 `-P` 讓位址和連接埠維持數字,NAME 那一欄才會讀成 `*:5900` 而不是 `*:rfb`;`-iTCP:5900` 選連接埠,`-sTCP:LISTEN` 只留監聽中的 socket。COMMAND 點出持有者,PID 是你要動手的號碼,NAME 是綁定位址——`*:5900` 代表每一張介面,對螢幕共享來說就是任何路由得到這台 Mac 的人都可以來試。這裡的 `sudo` 不是可有可無:螢幕共享的監聽者屬於系統帳號,所以不帶權限的 `lsof` 什麼都不會印,一個忙碌的連接埠看起來會像空的。把 `-sTCP:LISTEN` 拿掉還能看到已經建立的檢視器 session,那是你發現已經有人連進來的方法。
- Linux
sudo ss -tlnp 'sport >= :5900 and sport <= :5910'掃一段範圍而不是單一連接埠,因為決定用到哪一個的是 display 號碼。`-t` 顯示 TCP socket,`-l` 只留監聽中的,`-n` 跳過服務名稱解析,`-p` 顯示所屬行程;`sport` 比對來源埠,而且接受 `<`、`<=`、`=`、`!=`、`>=`、`>`,所以一段範圍寫成一個運算式就好。5901 那一行是 display `:1`,5902 是 `:2`,依此類推。Local Address:Port 那一欄分得出來:`127.0.0.1:5901` 只綁回送位址,在等一條 SSH 通道;`0.0.0.0:5901` 則是整個網路都碰得到。持有者會出現成 `users:(("Xvnc",pid=2210,fd=8))`。沒有 `ss` 的話,`sudo netstat -tlnp | grep -E ':59[0-9][0-9]'` 給你同一幅畫面,行程那欄是斜線分隔的 pid/program;兩者都需要超級使用者權限才點得出不屬於你的行程。
- Windows
netstat -ano | findstr ":59"同樣因為 display 號碼的關係,這裡比對的是前綴而不是完整連接埠。`-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` 這種寬鬆樣式也會撈到不相干的高位連接埠——動手之前先把完整號碼看清楚。
- Windows
Get-NetTCPConnection -LocalPort 5900 | Select-Object LocalAddress,LocalPort,State,OwningProcess上面那種子字串搜尋的精確比對版本,而且每一個你懷疑的 display 號碼都值得跑一次。`State` 是 `Listen` 加上 `LocalAddress` 是 `127.0.0.1`,代表這台伺服器被刻意限制在本機,那是安全的設定,同時也是遠端檢視器被拒絕的原因。把 `OwningProcess` 丟進 `Get-Process -Id` 就能拿到執行檔。整段範圍每一個連接埠都是空結果,代表根本沒有 VNC 伺服器在跑,所以檢視器的拒絕訊息是準確的,不是什麼謎團。
從機器外面確認一次
`nmap -Pn -p 5900-5910 host.example.com` 才是值得打的版本,因為只掃單一連接埠只回答了一半的問題——伺服器可能因為 display `:1` 而在 5901。`-Pn` 跳過主機探索,所以不理 ping 的主機照樣掃得到。nmap 的狀態有精確定義:`open` 代表目標上有應用程式在聽;`closed` 代表主機回應了但那裡沒有人在聽;`filtered` 代表防火牆、過濾器或其他網路障礙擋住探測,所以 nmap 分不出是哪一種。對 VNC 來說,一個 `closed` 的 5900 旁邊接著一個 `open` 的 5901,一行就是完整的診斷。加 `--reason` 看是哪個封包決定了每一個狀態,加 `-sV` 讓 nmap 讀 RFB banner 並報出協定版本和實作。只掃你自己負責的主機。
連不上 5900 的時候怎麼讀
| 你看到的訊息 | 代表什麼 |
|---|---|
VNC 伺服器明明在跑,檢視器卻回報連接埠 5900 被拒絕連線 | 幾乎一定是 display 的算式。RFC 6143 把第 N 台伺服器放在 5900+N,所以 `vncserver :1` 在 5901,而 5900 上根本什麼都沒有。檢視器拿到一個光禿禿的主機名稱就去撥 5900,被拒絕是正確的。依你的檢視器語法輸入 `host:1` 或 `host::5901`,並且用範圍掃描而不是單埠掃描來確認。 |
檢視器沒有馬上失敗,而是一直卡住,最後逾時 | 什麼都沒回應,所以封包是被丟掉而不是被拒絕:主機防火牆、雲端安全群組,或你和那台機器之間的某條 ACL。被拒絕是瞬間的,被丟掉要等滿整個連線逾時。`nmap --reason` 會替它命名——被丟掉是 `filtered`,被拒絕是 `closed`——而伺服器本來就正確地綁在回送位址、你卻忘了開 SSH 通道時,看到的也正是這個結果。 |
伺服器啟動不了:顯示器或連接埠已經被占用,或是 bind 因 Address already in use 失敗 | 5900+N 上的 `EADDRINUSE`。要嘛那個 display 之前的 `Xvnc` 還活著,要嘛是被砍掉的那一個留下了過時的鎖檔,讓 display 看起來被占用、其實連接埠是空的——光看錯誤訊息這兩種一模一樣,所以先用你系統對應的探測指令查連接埠。換一個 display 號碼啟動可以繞過去;砍掉對的那個行程才是修好它。 |
No matching security types(沒有相符的安全性類型) | TCP 連線成功了,RFB 交握也走到了安全協商那一步,然後伺服器的清單和檢視器的清單沒有任何交集。典型情況是伺服器只提供 VNC Authentication,而檢視器被設定成一定要加密的廠商擴充;也可能是伺服器提供了某個這個檢視器從來沒實作過的私有類型。這是兩個程式之間的設定不合,不是網路故障——連接埠一根寒毛都不用動。 |
很長的密碼可以通過,只輸入前八個字元也一樣通過 | 這不是伺服器的 bug。VNC Authentication 產生 DES 金鑰的方式,是把密碼截成八個字元、不足的話右邊補 null 位元組,所以第八個字元之後的東西在兩端都會被丟掉。攻擊這個 session 的人永遠只需要搜尋八個字元,這正是 RFC 6143 自己說這套機制在密碼學上脆弱、不適合用在不受信任網路上的原因。 |
lsof 或 ss 什麼都沒印出來,但這個連接埠明明被占用 | 這是權限的情況:兩個工具在沒有 `sudo` 的時候都只顯示你自己擁有的行程,而由別的使用者、由 macOS 螢幕共享這類系統服務,或在容器裡啟動的 VNC 伺服器,不加權限就是看不到。斷定連接埠是空的之前,先用 `sudo` 再跑一次——而如果查出來持有者是 Docker 的行程,要停的是容器不是行程,因為監督者會直接再發布一次。 |
工作階段連得上,但畫面一片空白,或只看到灰色背景和一個 X 游標 | 連接埠和認證都成功了,所以這完全不是網路問題。獨立的 `Xvnc` display 在有人替它啟動視窗管理員之前,是沒有任何桌面 session 掛上去的,而那件事本來該由伺服器的啟動腳本負責。去看 VNC 伺服器自己針對那個 display 的紀錄檔,不要看連接埠。 |
連接埠 5900 上跑的是什麼
5900 是 Remote Framebuffer 協定的基準連接埠,標準化為 RFC 6143,在 IANA 登記為 `rfb`。這份 RFC 對那個絆倒所有人的算式講得很明白:「RFB 用戶端連到伺服器的 TCP 連接埠 5900。在有多個 RFB 伺服器的系統上,第 N 台伺服器通常監聽 5900+N,就像 X Window 伺服器監聽 6000+N 一樣。」所以一個啟動了 display `:1` 的 Unix `vncserver` 聽的是 5901 而不是 5900——而且 5901 根本不在 IANA 登記表裡,只有基準號碼有指派。在檢視器裡打一個光禿禿的主機名稱,它就會去撥 5900,而那台機器的 5900 上通常什麼都沒有,這就是為什麼「連線被拒」是 VNC 最常見的症狀,卻幾乎從來不是大家以為的那個意思。至於真正占著這個連接埠的是什麼,每個平台不一樣,而你去找的時候這件事很重要:在 macOS 上,內建的螢幕共享和 Apple Remote Desktop 直接用 5900,蘋果自己的連接埠清單也把它列成 `rfb` 並引用 RFC 6143;在 Linux 上是 TigerVNC 或 TightVNC 的 `Xvnc`,再不然就是掛在既有 display 上的 `x11vnc`;在 Windows 上則是 TightVNC 的 `tvnserver` 這類服務。它們講的是同一套交握,這也是為什麼某個專案的檢視器通常連得上另一個專案的伺服器——直到兩邊在安全類型上談不攏為止。
連接埠 5900 該不該對外開
不要把 5900 對外開,也不要把 VNC 的密碼當成保護。RFC 6143 在核心協定裡只定義了三種安全類型——0 Invalid、1 None、2 VNC Authentication——而類型 1 的意思是完全不做認證,這正是現在還暴露在網際網路上的一大堆伺服器提供的東西。類型 2 也只是好一點點:伺服器送出一個隨機的 16 位元組挑戰,用戶端用密碼當金鑰以 DES 加密它,而「密碼會被截成八個字元,不足的話右邊補上 null 位元組」。不管你打了多長的密碼,整個金鑰空間就是八個字元。RFC 自己的安全性考量講得毫不客氣:這套機制「在密碼學上已知是脆弱的,不打算用在不受信任的網路上。許多實作會想使用更強的安全機制,例如把 session 跑在 IPsec 或 SSH 提供的加密通道上。」核心協定裡也沒有任何東西會加密 session,所以整個 framebuffer——以及你在上面打的每一個字——都是明文穿過網路的。把伺服器綁在回送位址上,透過通道連進去,例如 `ssh -L 5901:127.0.0.1:5901 user@host`,然後把檢視器指向 `127.0.0.1:5901`。廠商擴充確實加了 TLS 和更強的認證,但那是擴充:兩端必須實作同一個,而當它們沒有的時候,安全類型協商失敗要告訴你的就是這件事。
- 服務
- VNC
- 傳輸協定
- TCP
- 登記狀態
- IANA 有指派
- 分類
- 遠端連線
站上可以搭配的工具
這些全都在你的瀏覽器裡跑,不會上傳任何東西。
相關連接埠
查 5900 的時候,通常也會順手看一下這幾個。