Xử lý lỗi mất kết nối giữa ESP8266 với Firebase Realtime Database khi dùng thư viện Firebase-Arduino

Hiện nay, các project Internet of Things sử dụng NodeMCU (ESP8266) để kết nối, tương tác với nền tảng Firebase Realtime Database (FRD) trở nên rất phổ biến vì tính tiện lợi của cơ sở dữ liệu này là điều không cần bàn cãi.

Thư viện được sử dụng nhiều nhất cho đến thời điểm mình viết bài này (01/2021) là FirebaseExtended/firebase-arduino, tuy nhiên điều đáng ngại là hiện nay thư viện này vẫn dựa vào cộng đồng sử dụng đóng góp là chính và rất ít được cập nhật từ phía đội ngũ phát triển Google nên tính năng còn rất hạn chế, chẳng hạn như:
– Phụ thuộc vào thư viện Arduino-JSON phiên bản 5.x.x  dù thư viện Arduino-JSON đã có phiên bản 6.x.x từ khá lâu rồi.
– Tính năng Streaming để đọc dữ liệu từ FRD dùng khá ổn nhưng gửi dữ liệu lên FRD thì chỉ hỗ trợ phương thức PUT và POST, chưa có phương thức PATCH và chưa hỗ trợ tốt gửi dữ liệu chuỗi JSON.
–  Kho example khá sơ sài, vì vậy trong quá trình sử dụng mình thường xuyên phải customize lại cho đúng ý.

Các vấn đề về tính thiếu cập nhật của thư viện mình vừa kể trên tuy là chưa đầy đủ nhưng nhìn chung vẫn sử dụng ổn trong một số project ko yêu cầu quá nhiều tính năng phức tạp và khi cần thì chỉ cần bổ sung hoặc hiệu chỉnh code một chút là chạy được theo ý mình.

Tuy nhiên có một vấn đề nan giải mà rất nhiều bạn phản hồi với mình và chắc chắn mình là không hiểu vì sao sau một thời gian sử dụng thì vào một ngày đẹp trời bỗng nhiên NodeMCU (hoặc ESP8266) không thể kết nối với Firebase được nữa và hiện lỗi “Streaming Error” dù rõ ràng ngày hôm trước vẫn kết nối được và chạy bình thường?

Bài viết này mình sẽ giúp các bạn giải đáp chi tiết về lỗi này và gợi ý một số giải pháp đơn giản để giúp các bạn có thể nhanh chóng giải quyết vấn đề khi gặp phải.

TẠI SAO LẠI MẤT KẾT NỐI ĐỘT NGỘT KHI ĐANG SỬ DỤNG?

Hiện nay các kết nối từ thiết bị (client) đến máy chủ FRD được hỗ trợ tích hợp giao thức bảo mật TLS/SSL để giúp thiết bị có thể xác thực danh tính máy chủ, thiết bị có thể lựa chọn xác thực dùng chứng chỉ số của máy chủ theo tiêu chuẩn X.509 hoặc thông qua Certificate fingerprint (dấu vân tay của chứng chỉ). Các bạn có thể hiểu đơn giản rằng máy chủ FRD có một chứng chỉ số đại diện cho máy chủ gọi là Server Certificate là một tài liệu có định dạng theo một tiêu chuẩn chung gọi là X.509, chứng chỉ này được ký bởi một nhà cung cấp chứng chỉ đáng tin cậy khác gọi là CA (Certificate Authority) theo một quy trình tạo nên một chuỗi chứng chỉ Certificate Chain với cấp độ cao nhất gọi là Root CA, phía client khi giao tiếp với FRD có thể dựa vào chữ ký của các CA này để xác minh máy chủ Firebase có đáng tin cậy hay không. Đây là phương pháp quen thuộc nếu bạn nào từng thực hành qua các bài hướng dẫn làm việc với các nền tảng khác đám mây AWS, Google của TAPIT thì thiết bị cũng sẽ xác thực các máy chủ đám mây này thông qua chứng chỉ gốc Root CA. Còn Certificate fingerprint (dấu vân tay của chứng chỉ) là kết quả từ việc thực thi thuật toán băm SHA1 lên chứng chỉ của máy chủ để để tạo ra một dãy hexa có độ dài 20 byte đại diện duy nhất cho chứng chỉ của máy chủ. Thiết bị cũng có thể xác thực máy chủ thông qua fingerprint vì gọn nhẹ hơn rất nhiều so với chứng chỉ X509.

Thư viện FirebaseExtended/firebase-arduino hiện đang sử dụng cách thức xác thực máy chủ thông qua fingerprint của chứng chỉ máy chủ Firebase được dẫn trực tiếp trong thư viện khi các bạn tải về, vấn đề đặt ra ở đây là chứng chỉ máy chủ thường hết hạn sau vài tháng đến 1 năm và phía máy chủ sẽ gia hạn hoặc tạo mới chứng chỉ, từ đó fingerprint tạo ra từ chứng chỉ này cũng sẽ thay đổi dẫn đến yêu cầu phía thiết bị cũng phải cập nhật dãy giá trị fingerprint trong thư viện nếu không sẽ bị mất kết nối đến máy chủ. Nếu phân tích kỹ thì có thể thấy rằng đây là một lỗi không quá phức tạp nhưng đối với người chưa có kinh nghiệm trong việc sử dụng các kết nối qua TLS trên thiết bị IoT và thường quen dùng thư viện có sẵn thì thực sự lỗi này rất khó để khắc phục. Vì vậy để giải quyết lỗi này, các bạn có thể sử dụng một trong các cách mà mình trình bày ngay sau đây.

MỘT SỐ GIẢI PHÁP

1. Kiểm tra định kỳ và cập nhật fingerprint trong thư viện

Để kiểm tra chuỗi fingerprint của máy chủ firebase các bạn có thể làm như sau: truy cập vào website https://www.grc.com/fingerprints.htm, sau đó nhập vào ô Custom Site Fingerprinting địa chỉ test.firebaseio.com sẽ lập tức nhận được giá trị fingerprint của FRD.

Sau đó các bạn copy chuỗi fingerprint và cập nhật vào thư viện Firebase-Arduino ở file FirebaseHttpClient.h theo đường dẫn mặc định: Arduino\libraries\firebase-arduino-master\src\FirebaseHttpClient.h

Thay thế vào giá trị của mảng kFirebaseFingerprint[] ở cuối file:

2. Sử dụng thư viện cho phép xác thực qua chứng chỉ Root CA

Như đã nói ở trên, chứng chỉ máy chủ FRD được ký bởi một CA trung gian khác, CA ở cấp cao nhất trong chuỗi chứng chỉ này gọi là Root CA, chứng chỉ Root CA thường sẽ có thời hạn sử dụng lâu hơn và có tính ổn định, ít bị thay đổi hơn so với Server Certificate. Vì vậy nên nếu thiết bị sử dụng phương pháp xác thực qua chứng chỉ Root CA thì hạn sử dụng có thể lên đến hàng chục năm là bình thường. 

Các bạn có thể tự mình xem thông tin chứng chỉ của server và các chứng chỉ CA khác bằng cách sử dụng trình duyệt truy cập vào website test.firebaseio.com. Kích chọn hình ổ khóa trên góc trái và chọn Certificate (Valid). Lúc này sẽ hiện ra cửa sổ thông tin về chứng chỉ của Firebaseio ở tab General, các bạn sẽ thấy được thông tin về trang chủ website và đặc biệt là ngày khởi tạo và hết hạn chứng chỉ (13/01/2021 đến 12/07/2021). Chứng chỉ này được tạo mới cách đây vài ngày so với thời điểm mình viết bài này, nếu bạn nào đang gặp lỗi này thì mau mau cập nhật fingerprint đi nhé ^_^.

              

Tiếp tục chọn qua tab Certification Path, sẽ thấy được danh sách các CA trong chuỗi chứng chỉ đã ký cho firebaseio là GTS CA 1O1Root CA-R2. Thử kick đúp vào các chứng chỉ này, các bạn sẽ thấy thời hạn cho chứng các chứng chỉ này lên đến hơn 10 năm, đặc biệt Root CA là 15 năm (từ 12/2006 đến 12/2021) đúng như mình đã nói ở trên.

   

Mình giới thiệu đến các bạn một thư viện hỗ trợ xác thực qua chứng chỉ Root CA mà không cần thông qua fingerprint là mobizt/Firebase-ESP8266, ở link github thư viện gồm hướng dẫn sử dụng và ví dụ khá chi tiết rồi nên mình sẽ không giải thích kỹ ở đây, các bạn tự tìm hiểu và sử dụng thử nhé.
Qua bài viết này ngoài giúp các bạn giải quyết lỗi kết nối giữa NodeMCU (ESP8266) với Firebase Realtime Database, hy vọng các bạn cũng học được một số kiến thức bổ ích về xác thực qua giao thức TLS/SSL giữa thiết bị IoT với máy chủ bất kỳ. 
Chúc các bạn thành công!

Vinh Khai (TAPIT IoTs Team)

Tìm hiểu thêm: