MongoDB預設並不允許遠端裝置的連線,而為了要能夠讓它允許遠端連線,就必須要進行一些額外的設定。



執行以下指令,可以查看目前MongoDB所監聽的連接埠。

sudo ss -tlnp | grep mongod

ss指令可以顯示出Socket相關的資訊。-l參數可以只顯示正在監聽中的連線。若使用ss指令時都沒給任何參數的話,會忽略掉監聽中的連線。-t參數可以只顯示TCP連線。-n參數可以讓連接埠數字直接被輸出,而不是用一個名稱代替。-p參數可以顯示佔用連線的行程。

mongodb-remote

如上圖,可以看到MongoDB目前只有監聽127.0.0.1也就是「loopback」這個網路介面。所以目前的MongoDB是無法直接透過遠端的方式連入的。

讓MongoDB監聽其它網路介面

在MongoDB的設定檔/etc/mongod.conf內,位於net欄位下的bindIp欄位所設定的IP,即為MongoDB所監聽的網路介面。

mongodb-remote

我們可以使用逗號,來連接更多網路介面的IP。例如:

net:                                                                                                
  port: 27017
  bindIp: 127.0.0.1, 192.168.56.103

如果要綁定所有網路介面,那就把bindIp欄位值設成0.0.0.0吧!

設定完成之後,使用以下指令重新執行MongoDB的服務,新設定就會套用了。

sudo systemctl restart mongod

mongodb-remote

當然,防火牆也記得要設定才行。MongoDB預設的連接埠是27017,iptables規則可以這樣設定:

sudo iptables -A INPUT -p tcp -m state --state NEW -m tcp --dport 27017 -j ACCEPT

以上指令會對所有網路介面允許連接埠27017的TCP連入,如果要限定網路介面的話,可以再加上-i參數,後面接上要限定的網路介面名稱。

另外還可以參考這篇文章來永久保存iptables的設定。

讓MongoDB能使用帳號密碼來登入

如果讓MongoDB監聽能連到外網的網路介面,一定要替MongoDB增設授權機制。預設的MongoDB是不啟用任何的授權機制的,任何人都可以隨意連入存取資料庫。

在啟用授權機制之前,我們先替MongoDB添加管理者帳號吧!

利用以下指令連入本地端的MongoDB。

mongosh

接著會進入MongoDB的shell。輸入以下指令切換目前的資料庫為admin資料庫,因為我們要在這個資料庫下新增使用者。admin這個名稱是MongoDB預設的授權資料庫(Authentication Database)。

use admin

輸入以下指令來建立擁有管理所有使用者權限的使用者。指令執行之後才會設定該使用者的密碼(因為使用了passwordPrompt函數)。

db.createUser(
  {
    user: "admin",
    pwd: passwordPrompt(),
    roles: [ { role: "userAdminAnyDatabase", db: "admin" }, "readWriteAnyDatabase" ]
  }
)

此處的使用者名稱為admin,可以改成別的,避免被暴力破解。userAdminAnyDatabase表示這個位於admin資料庫的使用者是可用來管理所有資料庫的使用者的角色,readWriteAnyDatabase表示這個使用者可以對任意資料庫進行讀取與寫入(不需再另外指定資料庫)。

mongodb-remote

接著在MongoDB的設定檔/etc/mongod.conf內,添加security欄位(預設應該會有,但被加上#註解掉了),並在其下再添加authorization欄位,將authorization欄位值改成enabled表示要啟用授權機制(disabled表示要關閉授權機制)。如下:

security:
    authorization: "enabled"

mongodb-remote

設定完成之後,使用以下指令重新執行MongoDB的服務,新設定就會套用了。

sudo systemctl restart mongod

之後要替不同資料庫新增使用者的話,可利用以下指令連入本地端的MongoDB。

mongosh -u "admin" -p

以上指令執行後才會需要輸入admin使用者的密碼。

mongodb-remote

輸入以下指令切換目前的資料庫為要新增使用者的資料庫,在此的資料庫名稱以blog為例。不過事實上,用來存取資料庫的使用者不一定要被建在該資料庫之內,我們可以透過roles欄位來設定一個使用者在多個資料庫下的不同角色。

use blog

輸入以下指令來建立擁有讀寫目前這個資料庫權限的使用者,使用者名稱為blogger。指令執行之後才會設定該使用者的密碼(因為使用了passwordPrompt函數)。

db.createUser(
  {
    user: "blogger",
    pwd: passwordPrompt(),
    roles: [ { role: "readWrite", db: "blog" } ]
  }
)

mongodb-remote

如此一來在遠端,要使用URI存取這個在192.168.56.103主機上的blog資料庫時,若blogger使用者的密碼為{2/cH^BBS4n2,則URI可以寫作:

mongodb://blogger:%7B2%2FcH%5EBBS4n2@192.168.56.103/blog

注意這邊的密碼因為寫在URI裡面,所以需要跳脫處理。

mongodb-remote