ByteScope

27017

連接埠 27017 · MongoDB

TCPIANA 有指派資料庫

mongod 和 mongos 預設監聽的地方——也是驅動程式會安靜地花上三十秒選不到伺服器的那個連接埠。

查出是誰占用連接埠 27017

照你的系統挑一行貼上去執行。它會直接印出占著這個連接埠的行程,以及它綁在哪個位址上——通常看到這兩件事答案就出來了。

從機器外面確認一次

`nmap -Pn -p 27017 db.example.com` 回報這個連接埠從機器外面看是什麼樣子。`-Pn` 把主機當成上線的、跳過探索,這一點很重要,因為資料庫主機常常會丟掉 ping;`-p` 把掃描限制在這一個連接埠。`open` 代表 TCP 交握完成,有東西在聽。`closed` 代表主機回了 reset,所以它活著、路由得到,但沒有人占著這個連接埠——那是 `mongod` 停掉時的典型特徵。`filtered` 代表完全沒有回應,那是防火牆或安全群組把封包丟了;你的驅動程式那三十秒等的也是它。`--reason` 會印出實際發生的是三者中的哪一個,open 對應 `syn-ack`、closed 對應 `conn-refused`,而 `-sV` 會探測連接埠以判定服務和版本——那和全網掃描器在找沒有認證的資料庫時做的判讀是同一件事。只掃你自己負責的主機。

連不上 27017 的時候怎麼讀

你看到的訊息代表什麼
MongoNetworkError: connect ECONNREFUSED 127.0.0.1:27017socket 層直接拒絕:主機回了一個 reset,因為沒有東西占著這個連接埠。要嘛 `mongod` 沒在跑,要嘛你人在容器裡,而那裡的 `127.0.0.1` 指的是那個容器、不是資料庫。用服務名稱或主機的實際位址去指資料庫,並且在真正跑它的那台機器上用對應的探測指令確認一次。
MongoServerSelectionError: Server selection timed out after 30000 ms`serverSelectionTimeoutMS` 用完之後驅動程式自己的說法,而它的預設值剛好是 30000 毫秒,所以卡大約三十秒就是它的標記。這是一層包裝,不是原因:真正的 socket 錯誤在 `reason` 裡,或是在跟著印出來的拓撲描述裡。去讀那個,並且把逾時當成封包被丟掉、把拒絕當成伺服器停掉。
MongoServerError: Authentication failed.錯誤碼 18,`AuthenticationFailed`。網路、連接埠和綁定位址全都正確——連線已經走到交握,是帳密被拒絕。檢查使用者、密碼,還有最常見的 `authSource`:在 `admin` 建立的使用者,除非你明講,否則不會拿去對應用資料庫做認證。
MongoServerError: not authorized on appdb to execute command錯誤碼 13,`Unauthorized`,同樣跟 27017 無關。你認證成功了,只是掛在那個使用者身上的角色沒有帶你剛才那道指令需要的權限。去在對的資料庫上授予角色,不要伸手去拿 root 使用者。
listen EADDRINUSE: address already in use 0.0.0.0:27017已經有東西占著這個連接埠了——通常是開機就啟動的 MongoDB 服務,跟你剛拉起來的容器擺在一起,再不然就是上一個沒有真的結束的 `mongod`。先找出持有者;把容器發布到另一個連接埠,常常比去停掉那個服務還快。
mongod logs 'Waiting for connections' with a port you did not expect那行啟動訊息帶著它實際拿到的連接埠,而它是抓到設定檔覆蓋你的最快方法。帶 `--shardsvr` 的 `mongod` 預設是 27018,帶 `--configsvr` 的是 27019,所以分片叢集的成員經常根本不在 27017 上,不管連線字串怎麼寫。

連接埠 27017 上跑的是什麼

IANA 把 27017 登記給 TCP 上的 `mongodb`(Mongo database system);UDP 那一列是 Reserved,沒有服務名稱。MongoDB 自己的參考文件列出了兄弟號碼,知道它們可以省下很多瞎猜:27017 是 `mongod` 和 `mongos` 共同的預設值,27018 是帶 `--shardsvr` 或設定 `clusterRole: shardsvr` 啟動的 `mongod` 的預設值,27019 是 `--configsvr` 的預設值,而 27020 是 `mongocryptd` 監聽的地方。這些兄弟號碼都沒有出現在 IANA 登記表裡,只有 27017 有。現在的 MongoDB 執行檔預設綁在 localhost,手冊直接這樣寫,也點名了放寬的方法:`0.0.0.0` 是每一個 IPv4 位址,`::,0.0.0.0` 是兩個位址家族,再不然就是 `net.bindIpAll` 這個設定。那個預設值就是「在伺服器上用 shell 問什麼都對、從應用主機卻連不到」最常見的單一原因。另一件值得知道的事是,這裡的失敗通常是透過伺服器選取而不是 socket 回報的:驅動程式會一直重試它拓撲裡的每一個節點,直到 `serverSelectionTimeoutMS` 用完,而那個預設值是 30000 毫秒,所以連接埠寫錯或被擋住,呈現出來的是卡三十秒,不是立刻報錯。

連接埠 27017 該不該對外開

27017 絕不能從網際網路碰得到。授權是一個你要自己打開的東西,而一台沒開授權就啟動的資料庫,會接受任何打得開那個 socket 的人送來的每一道指令——這正是掃描器開始掃這個連接埠之後,大量暴露的部署被清空並勒索的原因。localhost 這個預設值是實實在在的改善,但它只保護沒人重新設定過的伺服器;`bindIp` 一旦為了讓應用主機連進來而放寬,資料庫的可及範圍就等同網路允許的範圍。MongoDB 的建議是讓執行個體「只在受信任的網路上碰得到」,而在有多張網路介面的機器上,要綁在私有或內部那一張,不要綁全部。先做這件事。接著建立一個管理者使用者並啟用授權,而且給每個應用程式自己的角色範圍使用者,不要給 root,這樣一組外洩的帳密就是一次有邊界的損失。要從網路外面連進資料庫,走 VPN、對等連接的私有子網路或 SSH 通道,而不是在防火牆上把連接埠打開;真的非得可路由不可,就依來源位址限制並要求 TLS,因為沒有 TLS 的話,帳密、查詢和回傳的文件全都是明文穿過網路。

服務
MongoDB
傳輸協定
TCP
登記狀態
IANA 有指派
分類
資料庫

站上可以搭配的工具

這些全都在你的瀏覽器裡跑,不會上傳任何東西。

相關連接埠

查 27017 的時候,通常也會順手看一下這幾個。

常見問題

明明就有東西在用,指令卻什麼都沒印出來?

幾乎都是權限問題。lsofss 會列出 socket,但別人的行程它不會顯示所有者,所以由系統帳號、容器執行環境或 launchd 啟動的服務,在你補上 sudo 之前就只是一個沒有主人的監聽項。Windows 則是反過來:netstat 什麼都沒有,綁定卻還是失敗,那代表這個號碼落在 Hyper-V、WSL2 或 Docker Desktop 開機時預留的範圍裡。

占著連接埠的那個行程可以直接砍掉嗎?

先看清楚它是什麼。沒收乾淨的開發伺服器砍掉沒事;正在寫入的資料庫不行,其他東西依賴的系統服務也不行。如果持有者是容器,請停容器,不要砍主機看到的那個行程——砍了執行環境只會把它拉起來。遇到真的不能動的,把自己的服務換一個連接埠反而更快。

為什麼本機連得到,別台機器就連不到?

因為它綁在 127.0.0.1 而不是 0.0.0.0。每一頁的指令之所以會把綁定位址跟行程名一起印出來,就是為了這件事:綁在回送位址上的服務,不管防火牆怎麼設,都只有這台機器自己連得到。現在不少框架是刻意這樣預設的,所以通常是一個參數的問題,不是 bug。如果已經是 0.0.0.0 還是不通,下一個要懷疑的就是主機防火牆或雲端的安全群組。

把服務換到冷門的連接埠會比較安全嗎?

幾乎沒有幫助。掃全網的機器持續在掃整段範圍,換號碼買到的是幾個小時,不是安全,代價卻是每個同事都得記住它。它確實能讓針對預設埠的無差別掃描少污染一點日誌,這算是實際但有限的好處。真正會改變結果的是認證、限制來源位址的防火牆,以及一開始就不要讓它對外。

連接埠 27017 還是卡住嗎?看完整的連接埠對照表,或是回到上面,從你實際看到的那行錯誤往回追。