[後端] 如何讓 Heroku 上的專案使用固定 IP 連接 MongoDB Atlas 服務?

前言

在閱讀以下內容前,請先確認你有一張信用卡可以註冊到 Heroku 的帳戶內,如果沒有,請嘗試使用其他免費網路空間服務。


基礎概念

隨著硬體技術越來越強,儲存空間的單位成本越來越低,於是有各種雲端空間服務可以使用,但是網路 IP 是有限的共享資源,由各地區的 ISP 業者分配使用(以台灣來說,需要申請中華電信線路,再申請固定 IP),雲端空間業者不會持有大量的 IP 讓用戶使用,通常是以內部固定 IP 加上動態分配外部 IP 來連線。

資料庫用來儲存網站的各種資料,通常也會包含大量的客戶資訊(姓名、手機、信箱…等),這些個資或商業機密一旦外洩就會造成公司和客戶的嚴重損失,最基礎的第一道防線就是網路防火牆,只能允許網頁(App)伺服器對資料庫(DB)伺服器連線(設置白名單規則)。


設置 Heroku 連線 IP 的三種方法

MongoDB 的文件 Configuring Heroku IP Addresses in MongoDB Atlas 有介紹幾個方法讓 Heroku 使用固定 IP 連線:

  1. 使用插件(add-on)來提供固定的對外 IP,也就是這篇文章要介紹的方法。
  2. 使用 Heroku Private Spaces 來設置固定 IP,雖然不需要安裝插件(add-on),但是需要$$$,無課仔表示:下面一位!
  3. 直接把所有 Heroku 會使用的動態 IP 加到白名單中,文章中沒有提供到底是哪些 IP,表示要自己找,而且這個方法非常不保險,萬一動態 IP 清單變了,服務突然就掛了。

Heroku Addons 說明

我們可以到 Heroku 的 Network Services Addons 中看到有許多網路服務的插件可以選擇,這些插件並不是直接提供固定 IP,而是以代理的方式來達到固定 IP 的效果。

了解 Addons 的運作方式,事情並沒有因此豁然開朗,這麼多的 Addons 根本不知道要選哪個!先講結論:我使用的是QuotaGuard Static IP's

每個 Addons 提供的應用不太一樣,有些使用他的函式庫來取代 Axios(或 fetch),透過 Addons 函式庫的方法設置好代理參數後發出 GET 請求,但這種方式提供的是 HTTP 代理,僅適用 HTTP/HTTPS 的連線,MongoDB 的連線就無法使用了(網路層級不同)。

QuotaGuard Static IP’s 提供了 SOCKS 代理,他可以監聽 Heroku App 的連線請求,並且把對 MongoDB 的連線導向自己,再由 Addons 把請求送給 MongoDB,所以對 MongoDB 來說,收到的請求來源都會是 QuotaGuard Static IP’s 提供的固定 IP。

原始連線模式
Heroku(IP: ??.??.??.??) -> MongoDB Atlas(無法限制來源)

代理連線模式
Heroku(IP: ??.??.??.??) -> Proxy(某個固定 IP) -> MongoDB Atlas(只接受 Proxy 的固定 IP)


實作開始

整個實作過程,都是參考 QuotaGuard 的 How to Connect to MongoDB using QuotaGuard 文件進行,雖然他寫的蠻詳細的,但是要弄清楚還是得費一番功夫。

馬上進入實作步驟:

  1. 請到 Heroku 的 Network Services Addons 選擇 QuotaGuard Static IP’s。

  2. 選擇 Addons 之後建議還是先往下拉看一下價錢,確認有免費的,才能為荷包把關。

  3. 價錢確認後,可以回到最上方的右邊點選 install 按鈕安裝。

  4. 進入提交頁面後,請先確認收費方式,接著在下方輸入要設置代理的專案名稱(專案名稱可以到自己的 Heroku 頁面查看),選取好專案後就可以點擊按鈕進入下一步。

  5. 如果帳號沒有綁定信用卡,就會跳出警告,不讓你安裝,請完成綁定才能進行下一步。

  6. 裝完後會進入 資源列表(Resources)畫面,點擊「QuotaGuard Static IP’s」進入,首次進入會出現一些條款需要拉到最底下點擊同意(後續再點擊就會導向操作面板了)。

  7. 接下來請回到 VScode,開啟佈署到這個 Heroku 專案的資料夾,接著在終端機輸入以下指令來安裝 QuotaGuard 的相關檔案,執行完成後會多出一個 vender 資料夾和一些檔案。

1
curl https://s3.amazonaws.com/quotaguard/qgtunnel-latest.tar.gz | tar xz
  1. 接著再開啟瀏覽器進入操作面板網址 https://www.quotaguard.com/dashboard,或是在終端機輸入以下指令,會開啟瀏覽器進入相同頁面。
1
heroku addons:open quotaguardstatic
  1. 點選操作面板右上方的「齒輪」圖案,再點選「QGTunnel Configuration」

  2. 點擊右上方的綠色「+」按鈕來新增 Tunnel。

  3. 請開啟一個網頁分頁,並登入 MongoDB Atlas,點選你的 cluster 名稱進入詳細資訊頁面。

  4. REGION 區塊有好幾個 cluster,請每個都點進去,然後把完整的名稱複製下來。

  5. 回到步驟 10 的 新增 Tunnel 頁面,把剛才 mongoDB 複製下來的字串建立起來,有幾個就建幾筆(通常會有三筆,有關 cluster 的連線字串在 QuotaGuard 的文件也有說明),設定資訊如下:

  • Remote Destination:MongoDB Atlas 內 cluster region 的完整名稱,建立完成後系統會在前面自動加上 “tcp://“,這是正常的。
    (名稱範例:xxxxxx-xxxx-00-00.xxxxx.mongodb.net:27017)
  • Local Port:27017(MongoDB 的 Port)
  • Transparent:透通模式請開啟
  • Encrypted:加密模式可以不用開
  • Optional Name:可以為這個 Tunnel 設定名稱,也可以空著。
  1. 回到 VScode,在專案的根目錄新增一個檔案,檔案名稱是 Procfile (請不要加入任何副檔名,txt 也不行),這個檔名是 Heroku 的設定檔,在裡面撰寫導入 addons 的啟動指令,撰寫格式如下:
1
web: bin/qgtunnel 啟動程式名稱 啟動指令和參數

以 node.js 為例,啟動指令是 npm start,Procfile 內撰寫的就是

1
web: bin/qgtunnel npm start

範例圖片

  1. 接下來就可以執行 git add & commit 把修改好的專案 push 到 Heroku 上,在 commit 前請用 git status 確認 vender 資料夾內的檔案和 Procfile 都有加入,一個都不能少!

  2. 推送完後先確認一下 app 會不會 crash,如果正常運行就可以回到 QuotaGuard 的操作面板 https://www.quotaguard.com/dashboard,把左上方的兩個 IP 設定到 MongoDB Atlas 裡面的 Network Access,IP 後面請加上 /32,這個遮罩表示單一 IP,如果後面是 /0,不管前面打什麼 IP,任何人都可以連的到!

  3. 設定完之後就可以測試,在本地用 Compass 連和從 Heroku 主機連線是否一個不能連、一個能連,測試沒問題就大功告成啦!

補充

  • 官方文件有建議把 Tunnel 的設定備份下來,可以自行考量需不需要。
  • Heroku 安裝 QuotaGuard Static IP’s 時會自動為該專案建立一條名稱為 QUOTAGUARDSTATIC_URL 的環境變數,如果連線失敗可以查看一下這個環境變數有沒有建立起來。
  • 正常狀況下加入 QuotaGuard Static IP’s 不會影響原始 App 的運作,因為他只是個封包傳輸的代理程式。