2018年6月17日 星期日

回讀者留言: Modbus Gateway 與 IoT

在一月多的時候,網友 gary yang 留言:

你好,
一般來說,geteway ModbusTCP端的ip是例如192.168.1.3等等的區域網域ip.
在處處講求IoT應用的現今環境,透過ModbusTCP geteway的機制,雖然已能將設備device的ModbusRTU格式"打包"上網(例如大大曾提過的mbusd),但卻也只能應用於區域網域內.
如果客戶的需求是希望geteway的ModbusTCP能由"Server"成為"client"身份,主動connect到遠方主機(例如AWS cloud主機).
這樣的需求情況下,是否已違反了ModbusTCP的架構機制?(例如mbusd就無法設為client,只能是server).
怎樣才能讓geteway端的ModbusTCP能連上遠端?進入IoT的應用.

限於當時的知識水平,現在回想起來當初給的答案有點誤人子弟。現在重新回答一下,先給出幾個關鍵字:
  • UDP 打洞(UDP hole punching)
  • P2P
  • STUN
  • TURN
  • libjingle

UDP 打洞

傳統 Modbus TCP 的痛點

在解釋 UDP 打洞之前,必須先了解傳統 Modbus TCP 的痛點在哪?如果在封閉的區域網路內,Modbus TCP 使用上並沒有什麼問題,而上了 internet 之後很多問題馬上就浮現了:


由上圖可知,如果左邊的 SCADA (Modbus TCP Master/client) 要連上右邊的 Modbus Gateway (Slave/Server)。首先右邊的 NAT 必須提供以下資訊:
  • 右邊 NAT Public IP 必須固定不變,否則就要用到 DDNS(Dynamic DNS)
  • 右邊 NAT 必須 
    • port 502 映射(port mapping/forwarding)到內部的 Modbus Gateway。
    • 採用 DMZ (Demilitarized Zone)。
    • UPnP (2018/06/24 補充)
上面這些古人的作法在現今已經不合時宜了,首先是 IPv4 public IP 幾乎已經用盡,再來是 port mapping or DMZ 造成客戶設定安裝上的困擾,客人可能不知道如何設定,或者是他沒有權限,必須跑公文提出申請,而 Modbus TCP device 廠商你要他的客服精通市面上所有的 NAT 設定也不靠譜。另外還有一個問題是使用 port mapping/forwarding 的話,那 Modbus TCP device 使用 DHCP 就有困難了,MIS 可能為了這些 Modbus TCP device 還要特別規劃一段專用 IP 位址。

UPnP 可以解決手動設定 port mapping/forwarding 的問題,但有安全疑慮(通常 NAT 預設不啟動),對於手機 4G 上網也沒輒。還有一種方式是中大型企業常使用的 VPN,這邊不討論。

一個顯而易見的解法是透過一台在 internet 上擁有固定 public IP 的 Relay Server 進行通訊:

這樣的作法會有以下幾個問題:
  • Relay Server 如果由 Modbus TCP device 廠商營運管理,隨著產品越賣越多,成本也隨之升高。而且為了達到最好的傳輸效果,甚至必須在每個國家設置 Relay Server (例如你覺得 Google Play 比 Apple App Store 順暢,那是因為 Google 直接在你所在的地區附近安裝 Server)。
  • 涉入他人因果:對於客戶來說,我傳什麼不就被你看光光?
  • 如果交由客戶自行安裝,教育訓練將會很恐怖,客人接不接受就是一大問題。
所以說這樣的作法對於 Modbus TCP device 廠商來說也不可行,那有沒有辦法跳過 Relay Server,Modbus TCP Master & Slave 直接點對點(P2P) 通訊呢?

UDP 打洞原理

既然我們談的是 Modbus TCP,那為何不是 TCP 打洞而是 UDP  打洞?
  • TCP 打洞有實作上的困難
  • UDP 打洞實作遠比 TCP 簡單成熟(像是 bitcoin 因為使用 TCP P2P,還是得用 UPnP,而 UPnP 也只解決了 < 50% 的問題)
  • Modbus TCP ADU(Application Data Unit) 只有 260 bytes,大部分情況下不用擔心 IP fragmentation,header 內有 Transaction ID 可用來辨認 response。
也就是說 Modbus TCP 使用 UDP P2P 的障礙可能是所有 UDP P2P 應用中最低的(想想傳視訊的話要考慮多少因素)

現在來看看基本的 UDP 打洞如何實現。首先,如下圖所示主機 (1) 發送一個 UDP 封包到位於 internet 上有 public IP 的主機 (3),封包經過 (2) NAT 時 Source IP:Port Number 被替換成了 (2) NAT public IP 與另一個 Port Number(140.113.56.78:5566),而 140.113.56.78:5566 與 192.168.1.100:3000 的映射在 NAT 就稱作 session,這個 session 保留的時間從數分鐘到小時不等,而 140.113.56.78:5566 就稱作"洞"

第二步:同樣 (5) 發送 UDP 封包到 (3),這時候因為 (3) 已經有了 (2) 的記錄(140.113.56.78:5566),(3) 就把 (2) 的洞傳回給主機 (5)。


第三步:因為 (3) 也有了 (4) 的洞,就把這個洞傳回給主機 (1),現在兩邊就可以進行 P2P 通訊。

以上是 UDP 打洞最簡單的狀況(稱作 Full Cone NAT),實際上的情形當然會複雜許多,像是 NAT 打出來的洞會檢查進入的封包 IP:Port 是不是與目的地的 IP:Port 一樣?這有許多種情況與排列組合,有興趣的可以參考這篇文章

UDP 打洞現實狀況

打洞通訊協定已經標準化,稱作 STUN(Session Traversal Utilities for NAT),網路上還有公用 STUN server(不用費心自己架設了)。而 Google 也釋出 library - libjingle (使用 C++ 實作)。libjingle 是 Google 釋出的 WebRTC 原始碼一部分。

那會不會有打洞失敗的情形呢?如果打洞失敗,還是得走回 relay,這也有了標準稱作 TURN(Traversal Using Relay NAT),當然 libjingle 也有支援。

可惜的是 Google 釋出的部份並不包含 server side,如果要替網路嚴格管制的國家服務,或是該公司不信任公用 server,堅持要自己來,libjingle 就無能為力。

libjingle 也是筆者最近剛剛接觸,未來如果有什麼心得會陸續發表,盡請期待。

我的意見

為何不提什麼 MQTT 之類的東西呢?筆者認為每次一個新的 IT 名詞提出來,整個大環境就塑造一種一定要「新程式語言」+「新通訊協定」+「新硬體」才能完成這個「新名詞」要達到的目的。好像舊的投資通通不算數一樣。

但以筆者最近的實戰經驗,UDP P2P 才是 IoT 的「現在進行式」,因為這樣的技術才不會讓客戶的舊投資全部付諸流水,或是需要花大把銀子升級。

比方說,我可以設計一個 Gateway 把原有的 Industrial Protocol 改用 P2P 傳輸(很多小型 PLC 的通訊協議只是一問一答而已),客人不必升級原有硬體,只需要花少少的代價就可以實現遠端監控,而幾乎不用變動原有的設計設定。最重要的是 - 教育訓練簡單太多了!

另外,個人認為 Modbus Gateway 與 Device Server 相當適合加上 UDP P2P 的功能,在沒有 VPN 的情形下,這應該是個相當有賣點的功能。

妙的是,發表這篇文章的前一天,筆者在書店翻一堆跟 IoT 有關的書,卻幾乎沒有一本提到 UDP P2P!?

筆者已經不玩工控了(應該說沒人找筆者玩XD),因為最近接觸 UDP P2P,想到可以與 Modbus 做個結合,就寫篇心得跟大家分享,歡迎留言討論 :)

沒有留言:

張貼留言