[教學] 透過 DuckDNS 與 NGINX Reverse Proxy 做 TLS/SSL 加密連線

如果對於 DuckDNS 與 Port Forwarding 沒有概念,請先看這篇

前言


很多剛接觸 Home Assistant 又希望能從外部網路連回家控制的朋友,常常會面臨不知道如何設置 DDNS 動態域名服務以及 TLS/SSL 安全連線(透過 https://)的問題,希望這篇教學可以稍微減少一點上手的難度。裡面用的都是 Home Assistant 中已經包含的預設 add-on 套件,如果是使用完整版的 Home Assistant 依照下列步驟應該都能順利設定完成,也減少使用外部套件遇到升級出問題的機會。


必要條件


  • 家中網路環境有外部可存取的 IP(無論是固定或是動態)
  • 知道如何設置路由器(網路分享器)上的 port forwarding
  • 先將外部 IP port 80 與 443 forward 到內部 Home Assistant IP 的 port 8123 與 443

*將外部 port 80 forward 到 HA IP 的 port 8123 非必要,但可協助確認一些基本的 port forwarding 是否正常,有疑慮可以等到都設定完後再將此 forwarding 的條件移除。


DuckDNS 是什麼


DuckDNS 是一個免費的 DDNS(動態域名系統)服務,跟 DNS 一樣可以將一個 domain name(域名)對應到 IP 上,但是一般 DNS 服務只能對應到固定 IP,而 DDNS 會定時檢查主機的 IP 是否有變化,並動態的修改註冊表,讓沒有固定 IP 的主機也能有 domain name 可以使用,即使 IP 變動了,透過 DDNS 對應的 domain name 依然可以連線回家。

由於網路上的服務是透過 IP 連結,因此要使用 DDNS 的服務,首先必須確定自己的網路環境可以取得外部 IP(public IP),很多社區網路的環境指定的是內部 IP,是無法使用 DDNS 服務的,因此可以先測試一下自己是否能透過外部 IP 連到家中的 Home Assistant,例如 http://123.123.123.123:8123。(要將外部 IP port 8123 forward 到內部 Home Assistant IP 的 port 8123,以此類推)


建立 DuckDNS 帳號




首先到 https://www.duckdns.org/ 註冊一個帳號,例如我透過 Gmail 帳號登入後,會看到上圖的畫面。DuckDNS 會給予一個 token,這個 token 在待會的設定步驟上會用到,可以先複製起來。

接下來,在下面輸入 sub domain 的地方,輸入自己想要的名字,這個就是之後可以連回家中的免費域名,例如我這邊申請了一個 etphonehome,之後連線的網址就是 etphonehome.duckdns.org。(知道這個名稱梗的,應該都有點年紀了吧)


安裝 Home Assistant DuckDNS Add-on


現在我們可以到 Home Assistant 中的 Add-on Store 安裝 DuckDNS,安裝完後到設定中,於 Domains 欄位輸入剛才於 DuckDNS 網站上申請的 domain name(域名),然後下方 token: 的部分輸入申請時取得的 token:


接下來捲到頁面下方的 Let’s Encrypt 設定,將 accept_terms: 設為 true,代表接受 Let’s Encrypt 的服務條款(提供免費安全憑證的服務供應商),這樣 DuckDNS add-on 就會順便完成安全憑證的申請:


儲存後啟動套件,DuckDNS 會將目前偵測到的外部 IP 與剛才註冊的 domain name 對應,並且到 Let’s Encrypt 申請安全憑證。可以在 log 中查看整個申請流程是否成功,如果成功的話憑證檔案會自動放入對應的資料夾中,待會會用到。


可以看到紅筆圈起的位置,安全憑證申請成功:


現在雖然還沒有將安全連線必要的步驟完成,但如果輸入 domain name,應該已經可以看到 Home Assistant 的登入畫面(如果有將外部的 port 80 轉到內部的 port 8123 的話),但這樣是未經加密的連線,如果在外面輸入帳號跟密碼,帳密在整個由外到內的路線上都有可能被中間人看到,所以我們接下來要設定安全連線,讓帳密傳輸的過程是加密的。


安裝 NGINX Home Assistant SSL Proxy


接下來一樣到 Add-on Store 裏面,找到並安裝 NGINX Home Assistant SSL Proxy,並到設定頁面中,在 Domain: 欄位輸入剛才註冊的 DuckDNS domain name,這個套件會預設使用前面步驟中申請並產生的安全憑證檔案,因此其他設定都可以不用變動。


設定完成後,儲存並啟用套件。以前的話這樣就可以了,但是 Home Assistant 近期的更新要求使用 reverse proxy 服務(例如 NGINX)必須要加入額外參數,否則會看到下面的 400: Bad Request 錯誤訊息:


這時候如果到 Home Assistant 裡查看 log,會看到系統有警示有來自 reverse proxy 的連線請求,將此 IP 位址紀錄,待會會用到:

現在到 configuration.yaml 裏面,加入以下的設定:


http:
  use_x_forwarded_for: true
  trusted_proxies:
    - 172.30.33.0/24 #輸入 proxy server 的 IP,也可以輸入 subnet mask

記得剛才系統警示的那組 IP 嗎?在上方填入該 IP 或是輸入對應的 subnet mask 都行。重新開機後,試試看用 https:// 是否可以連線:


可以看到網址前面有個鎖頭符號,代表已經使用加密連線。如果無法存取 Home Assistant 介面,檢查一下 configuration.yaml 裏面 http 的部分是否有設定錯誤,或是 443 port forwarding 是否設定正確。

如果有其他問題,請在下面回覆討論。

7個讚

E大真的很熱心! 推推~

1個讚

幫推+1 , 感謝E大!!

2個讚

E大:
若兩個homeassistant設置在不同兩地,
duckdns也要用另外一組不同的mail去申請新的網址嗎??

不用,一組郵件記得可以申請五個域名…

感謝E大,我再試試

請問e大,我沿用之前大duckdns,nginx照你的教學操作,顯示如圖片
之前duckdns配caddy是沒問題的,這次我改用ros軟路由,固定ip可以直接連上內網,但duckdns就無法,請求支援

Caddy有關掉了嗎?Nginx不需要轉port

你外部的 port 433 有轉到 HA 那台 IP 的 port 433 嗎?

有啊,e大是說 443嗎?

有,關掉也刪掉啦,但還是一樣:joy:

E大想請問一下,最近有網友在討論一些比較特殊的狀況,例如用的是社區專線,社區有開Port出來(非80/ 443),這種情況下該如何設定? 我用Cable modem的條件來模擬這個狀況,只要不是設定80/ 443基本上就不會通,轉port的部分是否該注意什麼?
第一種條件全部選用預設服務的port沒問題

第二種條件就無法透過NGINX manager的ssl了

不知道是不是有那裡設定錯誤

我記得之前測試,外部 port 80 會用來做 Let’s Encrypt HTTP-01 challenge(NGINX Proxy Manager 使用的免費憑證驗證機制),DuckDNS add-on 裡也是用 Let’s Encrypt 的憑證服務,但因為 DuckDNS 就是域名提供者所以可以用 DNS-01 challenge,不必用到 port 80。

不過我有試過把手動取得的憑證透過匯入的方式加入到 NGINX Proxy Manager 是可以的(Synology NAS 提供的 DDNS 域名跟憑證,我從 DSM 中匯出),目前只能想到透過這種方式。但一般申請 TLS/SSL 憑證要過認證要嘛就是走 HTTP 確認有 server 控制權,不然就是要有同網域 admin email 或 DNS server 修改權限,一般使用者沒有相關架站知識跟環境會有蠻高的難度。

NGINX Proxy Manager 很多功能我都找不到資料去研究,所以後來就沒花太多時間深掘了。對這一塊我也只有很粗淺的知識,有人知道的話也請分享一下。

Let’s Encrypt 網站上的說明

我用 Synology Router、EdgeRouter 以及 Dream Machine Pro 上做 port 80 / 443 forwarding 都正常(外部 port 80 → HA port 80,外部 443 → HA port 443),我沒有 RouterOS 環境,不然就要等我收到我的 MikroTik router 後再來玩看看了。(藍圈預購不知要等多久)

你手動匯入後有試過不開80/ 443,改開別的port給HA的80/ 443嗎? 因為我手動匯入HA底下的SSL憑證還是不行,不過我忘了試匯入後用預設服務的port看能不能通就是了

沒有試過非正規 port,因為原本的目的就是不希望輸入 port,但我記得手動輸入憑證是 OK 的。

終於可以https上ha,也不確定是怎麼成功的,請問e大,在同個ip下的其他port也可以做到https嗎?如果可以請教如何? 我有在路由器上設定,但除了ha外,其他的都是能http

你需要使用 NGINX Proxy Manager,然後每個服務都要申請自己的域名才能對應。

例如:
https://service1.duckdns.org → HA port 443
https://service2.duckdns.org → router port 8080
https://service3.duckdns.org → nas port 5001

謝謝ed大,已經解決問題

2個讚
http:
  use_x_forwarded_for: true
  trusted_proxies:
    **- 172.30.33.0/24 #輸入 proxy server 的 IP,也可以輸入 subnet mask** <<這IP要輸入甚麼?