ESP32 および M5Stack で DNS および mDNS の SSL server を作ってみた

SSL ( TLS )

使ったもの

M5Stack

Espressif Systems 社の ESP32 を搭載し、技適取得済み、液晶ディスプレイ、micro SD カードスロット、バッテリ、スピーカー、ボタンスイッチ、Groveコネクタ等を搭載した全部入り WiFi マイコンモジュールです。

(追記)
M5Stack Basicは、この記事を書いた当時より格段にバージョンアップしております。
以下のスイッチサイエンスさんの公式サイトをご参照ください。
https://www.switch-science.com/collections/%E5%85%A8%E5%95%86%E5%93%81/products/9010

※M5Stack Gray(9軸IMU搭載)現在は販売終了しております

 

ESP32-WROOM-32 ( ESP-WROOM-32 )開発ボード

技適取得済みのEspressif Systems 社のマイコンモジュール ESP32-WROOM-32 ( 旧 ESP-WROOM-32 ) を搭載した開発ボードです。
ESP32-WROOM-32 には 4MB の Flash が内蔵されています。

開発ボードは各社から出ています。
今回は以下のボードを使いました。

ESPr Developer 32 ( スイッチサイエンス製 )

ESPr Developer 32
スイッチサイエンス(Switch Science)

ESP32-DevKitC ( Espressif Systems 社製 )

WiFi ルーター環境

2.4GHz 帯のインターネットに接続した WiFi 環境を用意してください。
インターネットに接続していなくても DNS SSL サーバーの実験は可能ですが、mDNS を試す時には、インターネットに接続してあった方が良いと思います。

ファイアウォールの設定で、ESP32 や M5Stack を接続できるようにしておいてください。
そして、mDNS のポート UDP 5353 を使用できる状態にしておいてください。
ただし、このポートを解放したことによって、悪意ある者から攻撃されたとしても、当方では一切責任を負いません。

Arduino – ESP32 のインストール

Arduino IDE は 1.8.7 で動作確認しています。
Arduino core for the ESP32 は stable版 1.0.0 で動作確認しています。

インストール方法は以下の記事を参照してください。

Arduino core for the ESP32 のインストール方法

SPIFFS アップローダープラグインのインストール

マイコンボードで SSL 通信する場合、証明書や秘密鍵は厳重に保管していないといけません。
micro SD カードなどに保存してしまうと、簡単に盗まれてしまいますので、M5Stack や ESP32-WROOM-32 の FLASH に保存できる SPIFFS を使った方が無難だと思います。
Arduino IDE に ESP32 SPIFFS プラグインをインストールする方法は以下の記事を参照してください。

ESP-WROOM-32 ( ESP32 ) SPIFFS アップローダープラグインの使い方

自作ライブラリのインストール

Arduino core for the ESP32 の WiFiServer ライブラリと、ESP-IDF のサンプルコード openssl_server_example_main.c を私が改変し、ライブラリを作ってみました。
openssl_server_example_main.c のライセンスは Public Domain ですが、WiFiServer ライブラリは LGPL2.1 でしたので、それを継承しています。

以下のリンクにあります。

https://github.com/mgo-tec/ESP32_SSLserver

ZIPファイルをダウンロードして、Arduino IDE にインストールしてください。
インストール方法は以下の記事を参照してください。

GitHubにある ZIP形式ライブラリ のインストール方法 ( Arduino IDE )

OpenSSL で ルート CA 証明書および秘密鍵の作成

では、OpenSSL を使って、ルート CA 証明書、および秘密鍵を作成していきます。

今回の OpenSSL は ver 1.1.0i で動作確認しています。
以下の記事を合わせて参照してください。
以前は IPアドレスで証明書を作成しましたが、今回は DNS ネームおよび mDNS ネームで作成しますので、cfgファイルの修正が必要です。

SSL Server 自作するための OpenSSL 使用方法

以前、この記事と同じように証明書を発行したことがある人は、再度同じ CN 名で発行しようとすると OpenSSL でエラーが出ます。
そりゃ、当然ですよね。
一つのサーバーネームには唯一、たった一つしかサーバー証明書は発行できません。
その場合、失効処理( revoke )をするか、または、demoCA フォルダ内のファイルを新規にすべて作り直して、最初から同じように発行すれば良いと思います。

cfg ファイルの alt_names

ルート CA 用の cfg ファイルを新たに作成しておきます。

ファイル名は、とりあえず
openssl_ca.cfg
としておきます。
[ alt_names ] のところで、今後作成することが考えられる全てを有りったけ入力して置き、有効期限を1 年としておくと良いと思います。
悪用されることを防ぎたい場合は有効期限をもっと短くすると良いと思います。
私の場合の[ alt_names ] は、例として以下の様にしています。
ポイントは、mDNS でも使えるように、
esp32.local
m5stack.local
などのように、*.local という名前も入れておくことです。
そして、今後も IP アドレスで証明書を発行することも有り得るので、よく使うローカル IP アドレスや、ESP32 の soft AP モードの IP アドレスも、考えられるだけ全て入力しておきます。
そうすれば、しばらくは ルート CA 証明書を発行しなくて済みます。
これを使って、サーバー証明書を量産していくわけです。

[ alt_names ]
IP.1 = 192.168.0.10
IP.2 = 192.168.0.11
IP.3 = 192.168.0.12
IP.4 = 192.168.4.1
IP.5 = 192.168.4.2
IP.6 = 192.168.4.3

DNS.1 = example.com
DNS.2 = *example.com
DNS.3 = localhost
DNS.4 = *localhost
DNS.5 = esp32.local
DNS.6 = esp32local
DNS.7 = esp32sslserver
DNS.8 = esp32-ssl-server
DNS.9 = esp32_ssl_server
DNS.10 = m5stack

DNS.11 = m5stack.local

ルート CA 証明書の crtファイルと秘密鍵生成コマンド

こちらの記事にあるように、OpenSSL でルートCA証明書と秘密鍵ファイルを作成するコマンドを入力して生成します。
例として

有効期限:1年
crtファイル名:esp32_ca.crt
秘密鍵ファイル名:esp32_ca.key

とします。
※ファイル名は、SPIFFS を使うため、拡張子以外は必ず半角8文字以内にしてください

そして、
※ルート CA の場合、CN ( Common Name ) 項目は DNS ネームや IPアドレスと一致する必要はありません
自分の好きな名前で良いと思います。
ここでは PrivateCA としています。

openssl req -new -x509 -sha256 -days 365 -newkey rsa:2048 -config openssl_ca.cfg -subj "/C=JP/ST=Tokyo/L=Shinjyuku/O=TestCA/OU=testca/CN=PrivateCA/” -out esp32_ca.crt -keyout esp32_ca.key

あとは、任意にパスフレーズ解除コマンドを設定するなりしてください。

DNS サーバー用、証明書および秘密鍵の作成

同じようにこちらの記事を参照しながら、OpenSSL で DNS サーバー用の署名要求 ( CSR )ファイル、およびルート CA の署名付きサーバー証明書、および秘密鍵を生成していきます。

例として、以下の設定で作っていきます。

有効期限:1年
サーバーDNSネーム:esp32
CN ( Common Name ) : esp32
csrファイル名:esp32srv.csr
秘密鍵ファイル名:esp32srv.key
署名付きサーバー証明書ファイル名:esp32_srv.pem

※SPIFFS を使うため、ファイル名は拡張子以外は必ず半角8文字以内にしてください

cfg ファイルの alt_names

DNS サーバー用の cfg ファイルを新たに作成しておきます。
ここでは、ファイル名を
openssl_dns_server.cfg
としておきます。
この場合は、8文字以上でもOKです。

[ alt_names ] は以下のようにします。
サーバー証明書の場合、アドレスは1つしか指定できませんので注意です。

[ alt_names ]
DNS.1 = esp32

DNSサーバー証明書署名要求ファイル ( csr )および秘密鍵の生成コマンドおよび証明書の生成

サーバー証明書署名要求( csr )ファイルおよびサーバー秘密鍵の生成コマンドを説明します。
有効期限は出来るだけ短い方がセキュリティ的に良いです。
※重要なのは、サーバー証明書の場合、DNS ネームとCNを同じにすることです。

openssl req -new -sha256 -days 365 -newkey rsa:2048 -config openssl_dns_server.cfg -subj "/C=JP/ST=Tokyo/L=Shinjyuku/O=ESP32server/OU=esp32server1/CN=esp32” -out esp32srv.csr -keyout esp32srv.key

あとは、こちらの記事にあるようにパスフレーズ解除したり、CSR ファイルから CA署名付きサーバー証明書 を生成すれば良いです。
ここでは、最終的に生成されるファイル名は以下とします。

サーバー証明書ファイル名:esp32srv.pem
秘密鍵ファイル名:esp32srv.key

では、次は mDNS ネームのサーバー証明書および秘密鍵の説明をします。

コメント

  1. 匿名 より:

    わたしもAndroidでmDNSしたかったのですが、Android9になってもmDNSに対応してくれなかったので、自分でアプリを作ってみました。
    https://qiita.com/maccadoo/items/48ace84f8aca030a12f1
    https://play.google.com/store/apps/details?id=com.dokoden.dotlocalfinder&hl=ja
    デザインはデフォルトのまま、なんもいじっていないのはご容赦を

    • mgo-tec mgo-tec より:

      匿名さん

      コメント投稿ありがとうございます。

      これは良いかも知れませんね。
      私はまだ Android8 なのですが、Android9になってもmDNS対応していないんですね。
      それは残念です。
      でも、このアプリがあればすべてmDNSで統一できそうで、すばらしいですね。
      今は忙しくて、なかなか試せませんが、時間が空いた時に試してみようと思います。
      ありがとうございました。
      m(_ _)m

タイトルとURLをコピーしました