嵌入式開發可能既困難又昂貴,但本文將展示如何花費不到30分鐘的時間,在一種成本超低的裝置上安裝安全嵌入式Web伺服器,讓FreeRTOS和lwIP TCP/IP堆疊在Wi-Fi晶片上執行。

為什麼要使用安全性(TLS)伺服器?

各種瀏覽器軟體已經開始將標準(HTTP)伺服器在瀏覽器欄中標記為「不受信任」(參考圖2),而安全性伺服器對終端使用者來說會更值得信賴。筆者將在文後的安全注意事項部分詳細介紹這種伺服器。

Wi-Fi晶片ESP8266和Minnow伺服器

用1美元就可以買到ESP8266晶片,但我建議使用具備USB埠的電路板,以方便韌體更新;如果沒有板載USB就會需要額外的步驟,例如使用USB-TTL轉換器。而具備USB埠的ESP8266電路板僅需花3美元就可以買到。

低成本的ESP8266 Wi-Fi晶片非常適合學習用途,但速度慢,特別是在執行諸如加密等CPU密集型任務時。在使用慢速晶片處理CPU密集型任務時,確實需要慎重考慮你的設計。

ESP8266以80 MHz頻率運作,這對嵌入式晶片來說適合,但程式碼執行速度會很慢,因為得透過SPI記憶體。在遇到資源受限之微控制器的實際限制時,在此裝置上執行TLS安全伺服器可提供真正的喚醒呼叫(wakeup call),並提供對可在慢速微控制器上執行之內容的完美呈現。安全Web伺服器類型的選擇以及網路應用程式設計,對慢速裝置至關重要。

在本文中,筆者將解釋如何在ESP8266上編譯和運作Minnow伺服器。Minnow伺服器和參考範例在GitHub上可以找到。

筆者最近有在embedded.com上發表一篇關於Minnow伺服器的文章,介紹了如何使用Minnow伺服器打造一個現代的Web裝置管理應用程式。本文還探討了在使用TLS時將WebSocket伺服器與所謂的單頁應用程式(Single Page Application,SPA)結合使用的好處。不過我建議讀者先閱讀這篇文章,因為我們將為ESP8266準備和編譯相同的範例程式碼。

入門

我們將使用由esp-open-rtos專案提供的ESP8266 FreeRTOS/lwIP環境;但不用擔心,你不需要經歷一遍複雜的esp-open-rtos設置過程。我們將利用預先配置好且立即可用的環境,是一個容易使用、以Web為基礎的整合開發環境(IDE)。

下載FreeRTOS/lwIP ESP8266 IDE

連結至Real Time Logic網站下載我們已經準備好的ESP8266 IDE,此IDE是專為教育目的設計,包括一個預先配置好、綁定易於使用之C語言原始碼Web IDE的esp-open-rtos。該IDE需要VmWare或VirtualBox;我本人偏愛VmWare勝過VirtualBox,因為發現前者更容易使用。請注意VmWare在非商業用途是免費的。

ESP8266 IDE還包括一個嵌入式TLS堆疊(SharkSSL),Minnow伺服器在使用SharkSSL編譯時會自動使用TLS。

你可以在沒有ESP8266電路板的情況下開始使用ESP8266 IDE,但這樣無法上傳和執行經過編譯的程式碼;換句話說,你可以下載該IDE並依循本文的所有步驟,除了不能在ESP8266上執行編譯好的程式碼。

圖1中的螢幕截圖顯示了虛擬機及與其相連的Web IDE。請注意虛擬機是如何取得ESP8266 USB連結的所有權;該Web IDE檢測到此情況就會顯示ESP8266已經連結,並準備使用新韌體進行更新。

20190418_Minnow_TA31P1

圖1:Web IDE連結至虛擬機的IP位址。
(來源:Real Time Logic)

此外圖1的螢幕截圖也顯示ESP8266透過一片麵包板連結至LED。除非你想要控制此應用範例中使用的外部LED,否則不需要額外的LED或麵包板。

還要注意,你的虛擬機IP位址很可能與圖1中的不同,要確保有在虛擬機視窗鍵入該IP位址;如果視窗是空白的,就點擊視並按下Enter鍵,必須在瀏覽器中輸入此IP位址才能打開Web IDE。

安裝Minnow伺服器和範例程式碼

Minnow伺服器參考範例不包括在ESP8266 IDE中,必須另外安裝。圖1顯示了已安裝在「ESP/ms」目錄下的Minnow伺服器範例。必須從Linux指令列安裝Minnow伺服器;如果你不是使用Linux也沒關係,只要複製並貼上我們準備好的指令即可。圖2是已貼上Linux Web shell的Minnow伺服器安裝指令螢幕截圖,該指令可從此連結取得。

20190418_Minnow_TA31P2

圖2:貼到Linux Web shell中的Minnow伺服器安裝指令。
(來源:Real Time Logic)

當你在瀏覽器中輸入Web shell的URL時,系統會跳出登錄訊息;輸入使用者名稱sharkssl,密碼則是SharkSSL。

GitHub上的ESP8266教學解釋了如何配置虛擬機、安裝一切、編譯Web伺服器範例,以及更新韌體等的方法。在YouTube上也有展示詳細操作步驟的視訊如下:

安全vs.不安全

Minnow伺服器可以在安全或不安全模式下使用,在與ESP8266 IDE和SharkSSL一起使用時會自動進入安全模式(TLS)。在裝置中使用支援TLS的Web伺服器會增加額外的複雜性,終端使用者也要承擔處理SSL憑證的管理責任。在上述的YouTube視訊中展示了如何藉由在瀏覽器中安裝憑證管理中心(CA)的憑證,來去除瀏覽器中顯示憑證錯誤。CA憑證用於在Web伺服器範例中對憑證進行簽章。

嵌入式裝置通常安裝在受保護的私人網路中,但許多客戶仍要求Web伺服器連結須採用TLS;在私人網路使用支援TLS的伺服器會有問題,因為沒有眾所周知的憑證授權機構簽署IP位址或非標準(私人網路)名稱。還有另一個選項是自己扮演憑證授權單位,有興趣的讀者可以參考我們的教學範例

如前面所述,ESP8266速度慢,TLS則非常佔用CPU,你會注意到需要一些時間才能建立連接。使用WebSockets進行通訊的SPA範例,針對CPU資源有限的裝置進行了最佳化,但初始非對稱加密(initial asymmetric encryption,即TLS交握)仍需要時間,特別是對於一些不遵循友好設計實踐規則,且開啟許多TCP連結、需要完整TLS交握的瀏覽器。

在一篇「以Minnow伺服器建立單頁應用程式」的教學文章中,會有更多關於當前網路瀏覽器以及慢速微控制器相關問題的探討。

開發者模式與發佈模式

在前面提到的視訊中,我們透過在韌體中嵌入SPA (HTML資源)來編譯發佈模式(Release Mode),如此我們可以導航至裝置啟動應用程式,將應用程式按需求載入瀏覽器。

開發Web應用程式通常需要經歷多次反覆(iteration),並且必須為每次反覆更新韌體,這就使得開發過程非常耗時。幸運的是,SPA可以在開發期間駐留在你的PC上,只需重新載入瀏覽器就可以即可載入新的應用程式。從PC載入應用程式後,其中的JavaScript程式碼將與ESP8266建立唯一的WebSocket連結,應用於所有瀏覽器與裝置的互動。

請注意,SPA的伺服器端(裝置端)為ESP8266提供了一個導入(porting) API,此API與拖放韌體上傳範例一起使用,但不保存上傳的資料,更改憑據也沒生效。 esp-open-rtos API包含一個檔案系統,你可以使用esp-open-rtos提供的API添加缺失的功能。

以IoT啟用的ESP8266參考範例

配備嵌入式Web伺服器的裝置通常會在公司防火牆和/或路由器背後的私人網路上安裝和運作,並且在外部使用和濫用時自動受到防火牆保護。不過此類佈署也會阻止合法的遠端使用。

有時,嵌入式裝置需要透過網際網路從遠端位置操作,最安全的方法是利用物聯網啟用裝置並讓裝置連接到網際網路上的伺服器。圖3描繪了這樣的設置。

20190418_Minnow_TA31P3

圖3:本地或通過網際網路遠端存取嵌入式裝置。
(來源:Real Time Logic)

Minnow伺服器參考範例包含一個可在編譯時啟用的可選IoT元件;請注意,此元件在預設時是關閉的,需要對程式碼(或Makefile)進行微調才能啟用。

當以IoT模式運作時,該裝置除了充當本地使用的伺服器之外,還作為網路客戶端運作。網路客戶端通常不需要任何網路配置來連結外部網際網路服務,但必須連至某個已知服務。因此我們設置了一個可用於測試目的的線上IoT伺服器

該線上伺服器充當遠端使用者和裝置之間的代理伺服器(proxy),並允許遠端使用者安全地接取在防火牆後運作的私人Web伺服器。請注意,我們設置的測試伺服器不是立即可用的服務,我們會保持其運作一段時間,但如果你打算使用IoT模式,最終仍需要設置自有私人IoT伺服器。

GitHub上的Minnow頁面包含如何設置自有私人IoT伺服器的相關說明;私人IoT伺服器的好處是不必依賴於任何特定的IoT服務供應商,你會驚訝地發現運作私人IoT伺服器是多麼容易和合理。

如何啟用IoT模式

上面的YouTube視訊有展示如何以IoT啟用Minnow伺服器的參考範例,圖4的螢幕截圖顯示了需要在Makefile中啟用的巨集。

20190418_Minnow_TA31P4

圖4:「USE_SMQ」巨集啟用IoT模式,「SMQ_DOMAIN」巨集設置伺服器名稱。
(來源:Real Time Logic)

從圖4中可以看出,SMQ_DOMAIN巨集必須設置為我們的線上IoT展示伺服器「minnow.ml」,或你自己的IoT伺服器。此時,應該可以按一下「Run」按鈕,以編譯並上傳新的韌體;新韌體執行時,你應該會在Web主控台(console)中看到以下文字(節錄)。

20190418_Minnow_TA31txt

出現憑證警告(certificate warning)的原因,與充當不信任線上伺服器之TLS客戶端的裝置有關。憑證管理很複雜,我們會在本文最後討論這個問題。

所有連線的裝置都顯示在線上伺服器(minnow.ml)的使用者介面中,點擊其中一個裝置會進入該裝置的登錄螢幕,登錄頁面的憑證由該裝置提供,並非線上伺服器。預設憑證是root/password。圖5顯示了點擊裝置連結前與後的線上伺服器。

20190418_Minnow_TA31P5

圖5:點擊裝置連結前和後的線上伺服器。
(來源:Real Time Logic)

圖5左邊的窗格顯示了一個已連線的裝置,但是線上伺服器可以管理任意數量的裝置,並且隨著連線裝置的增加,清單也會變長;點擊連結時,線上伺服器的代理功能會將你連結至裝置。從這一點開始,該連接在概念上的運作方式與圖3所示的直接WebSocket連接類似。

安全性考量

如上所述,Minnow伺服器可以在安全(HTTPS)或非安全(HTTP)模式下運作。因為不必處理憑證,使用非安全連結比較容易,該伺服器在慢速CPU上運作的速度也會快得多。但是如圖2中的瀏覽器欄位所示,在非安全連線時,Google的Chrome瀏覽器和其他瀏覽器現在會顯示警告消息。誰知道接下來那些軟體供應商會做什麼?Google似乎下決心終止非安全通訊。

使用TLS時,你必須確保使用有效的信任鏈,如果使用者瀏覽到具有不受信任憑證的伺服器,所有瀏覽器都會發出嚴重警告資訊。就像前面解釋過的,為私人伺服器建立信任鏈需要你在私人網路上提供信任管理解決方案,其中一種解決方案是自己扮演憑證管理中心(CA)。

當裝置在客戶端模式下運作,並連結至線上測試伺服器minnow.ml時,主控台上將出現憑證警告;你可以在範例原始程式碼檔「main.c」(參考圖3)中找到警告文字。不應該是跳出警示文字而是應該終止連線,但在修改C程式碼以終止不受信任連結之前,必須確保裝置信任線上伺服器minnow.ml。透過將線上伺服器的CA憑證(根憑證)導入裝置的C程式碼,就可以恢復信任。該線上伺服器的憑證是由Let's Encrypt簽署。

如果你不熟悉「信任鏈」(china of trust)概念,請參考《嵌入式系統的憑證管理》一文。以上,如果讀者們有任何問題歡迎交流!

本文同步刊登於電子工程專輯雜誌2019年4月號;責編:Judith Cheng

(原文出自EE Times姊妹刊,Embedded.com網站;參考連結:How to install a secure embedded Web server on a $3 WiFi device,by Wilfred Nilsen)