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

SSL ( TLS )

こんばんは。

今回は、凄いですよ!

なんと、ESP32 および M5Stackで、IPアドレスではなく DNS ネームアドレスで SSL サーバーを作ってみました!
そしてなんと、インターネットに接続しない WiFi softAP モードで、DNSネームを使って SSL サーバーを構築できたんです。
私が Arduino – ESP32 のライブラリと、ESP-IDF のサンプルスケッチを改変して実現しました。
しかも、STA モード でも、WiFi ルーターローカル環境であれば、Arduino – ESP32 のライブラリを使って、mDNS ネームでも SSL サーバー構築ができました!
mDNS であれば、LANがインターネットに接続されていてもOKです。

スポンサーリンク

そして、さらに、Android や iOS , Windows のブラウザの URL欄に鍵マークが出て、ブラウザからは完全に信頼された SSL 通信が実現できました。
残念ながら、グローバル環境の WAN ではさすがに DNS は無理です。
これは、ローカルエリアネットワーク ( LAN )限定です。

とりあえず、まずは以下の動画をご覧ください。

 

 

ブラウザの URL 欄にバッチリ鍵マークが出ています。
鍵マークが出たからと言って安全ではないのですが、なかなか有り得ない名前を URL 欄に入力して鍵マークが出ると、
「やったぜ!!!」」
ってなりますね。

そして、動画の01:21 あたりでは、ESP32 同士、ESP32 と M5Stack 間で、インターネットに接続せずに SSL 通信が実現できています。
なかなか、スゴイと思いませんか?
自分が一からプログラムを組んだわけではありませんが、Espressif Systems 社の既存ライブラリをちょっと改変させていただきました。

今までは、ライブラリコードを眺めていても何をやっているかサッパリ分からなかったのですが、素人独学ながらプログラミングを続けていくと、だんだん内容が理解できるようになってきたところが大きいですね。

そもそも、今回は、SSLサーバーを作ることが目的ではなく、前回記事で取り上げたように、WiFiClientSecure ライブラリのセキュリティ上の問題点を検証しようとしていて、その次いでにできた副産物だったのです。

因みに、前回記事でも述べたように、クライアント側の ESP32 および M5Stack は、Arduino – ESP32 stable 1.0.0 でコンパイルした場合、証明書の有効期限チェックや失効リストの検証はできません
有効期限チェックだけでもできないかと、いろいろトライしたのですが、私の今の実力では無理でした。
ルートCA 証明書の日付チェックはなんとかできますが、ESP32 のクライアント側から、つまり WiFiClientSecure ライブラリを使ったサーバー証明書の有効期限チェックはなかなか難しいです。
今後の課題とします。
ですから、パスワード等をやり取りする場合は、以下のことを十分認識しておいてください。

SSLで暗号化されても、ブラウザのURL欄に鍵マークが出ていても、セキュリティ的に安全とは言えません!!!

IoT 機器を使う場合はこれ重要です。
意味が分からない方は、前回記事を参照してください。

では、これの作り方について説明してみます。
自分の備忘録的に説明しているところが多々あるのでご容赦ください。
初めて OpenSSL を使う方は、かなり面倒な作業が多いと思いますので、十分覚悟しておいてください。
ただ、一回作ってしまえば、後は単純作業の繰り返しなので、それほど難しくなく作業ができると思います。

因みに私は独学アマチュア素人です。
動作保証はしませんし、セキュリティの保証などは絶対しません。
でも、もし誤りや勘違い等がありましたら、コメント投稿等でご連絡いただけると助かります。

    【目次】

  1. SSL/TLS や PKI , OpenSSL のおさらい
  2. Arduino – ESP32 や ESP-IDF で使われている SSLライブラリ ( mbedTLS )は、DNS ネームのサーバー証明書しか Velify ( 検証 )してくれない
  3. DNS と mDNS の違い
  4. 使ったもの
  5. Arduino – ESP32 のインストール
  6. SPIFFS アップローダープラグインのインストール
  7. 自作ライブラリのインストール
  8. OpenSSL で ルート CA 証明書および秘密鍵の作成
  9. DNS サーバー用、証明書および秘密鍵の作成
  10. mDNS サーバー用、証明書および秘密鍵の作成
  11. ESP32 または M5Stack に証明書および秘密鍵を SPIFFS フラッシュにアップロードする
  12. スマホやパソコンに ルート CA 証明書をインストールして、ブラウザに信頼させる
  13. DNS ネームのサーバーおよびクライアントのスケッチ(プログラム)の入力
  14. mDNS ネームのサーバーおよびクライアントのスケッチ(プログラム)の入力
  15. コンパイル書き込み実行
  16. Google Chrome でアクセスする場合の注意点

SSL/TLS や PKI , OpenSSL のおさらい

SSL 通信について、良く分からない方の為に念のため。
SSL / TLS や、PKI、公開鍵暗号化方式、OpenSSL による証明書の発行方法は以下の記事を予め参照しておいてください。

SSL サーバーを自作するための自分的予備知識

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

Arduino – ESP32 や ESP-IDF で使われている SSLライブラリ ( mbedTLS )は、DNS ネームのサーバー証明書しか Velify ( 検証 )してくれない

前回の記事と重複しますが、そもそも、以前、こちらの記事こちらの記事で IP アドレスの SSL サーバーは既に作っておきながら、なぜ DNS の SSL サーバーを作ったかと言うと、Arduino – ESP32 の WiFiClientSecure ライブラリの SSL 証明書有効期限チェックができるかどうかを調べるためでした。
そのためには、ESP32 同士、および M5Stack 同士で、サーバー、クライアント間の SSL 通信をする必要がありました。
でも、以前作った IP アドレスのサーバー証明書では WiFiClientSecure に使われている mbedTLS ライブラリが受け付けてくれませんでした。
そこで、DNS ネーム、および mDNS ネームの SSL サーバーを作ってみたら、できちゃったという経緯です。

DNS と mDNS の違い

あらかじめ言っておきます。
正直言って、私は mDNS や DNS についてはあまり詳しくありません。
というのも、つい最近知って使い始めたばかりです。
にわか知識で述べたいと思います。
個人的想像も入っているので、ちゃんとした知識はご自分で調べた方が良いと思います。
ただ、間違えていたら、コメント投稿欄等でご連絡ください。

DNS について

DNS とは Domain Name System の略で、サーバーにアクセスする際、サーバーの IP アドレスに紐づけて事前にある機関に登録した名前をブラウザの URL 欄に入力してアクセスすると、ある機関の DNS サーバーで名前を IP アドレスに自動変換して、 アクセスできるようにするものの様です。
当ブログの URL の場合、
www.mgo-tec.com
が DNS のホストネームです。
mgo-tec.com
という名前も DNS ネームとして登録してありますので、どちらでもアクセスできます。

レンタルサーバーを借りた場合、そのサーバー屋と連携している DNS ネームサーバーによって名前解決しています。

ブラウザの URL 入力欄に DNS ネームで入力してアクセスする場合、UDPポートを使うらしいです。
ポート番号は 53 です。

UDP は、ストリーミングなどに使うポートで、ハンドシェイクや認証などといった時間のかかる処理は一切せず、単純な処理でデータを転送するもので、スピードが速いです。
ということは、ブラウザの URL 入力欄に DNS ネームを入力したら、単純な処理で出来るだけ素早くネームサーバーに接続して IP アドレスに変換して、TCP/IP ポートにアドレスを渡してサーバーにアクセスしていると思われます。
(あくまで想像)

DNSネームサーバーを使うということは、基本的にインターネットに接続しているか、あるいは、自宅で DNSネームサーバーを構築しているかということになります。
これを ESP32 や M5Stack の WiFi マイコンモジュールで実現しようとすると、難しい気がします。

しかし、Arduino – ESP32 には DNSserver ライブラリというものがあるではないか!

サンプルスケッチを使えば、SSL でない平文の通信ならば問題無く DNS ネームでアクセスできます。
ただし、Arduino – ESP32 の DNSserver ライブラリでは、インターネットに接続されたルーター間で通信する STA モードではうまくいきません。soft AP モード限定です
(soft AP モードというのは、ESP32 や M5Stack 自身が WiFi ルーターになるモードです。
STA モードは、外部のルーターに接続するモードです。)
そりゃそうですよね。
同じ 53 ポートを使ってしまうと、インターネット上の外部 DNS サーバーに先に接続しに行ってしまうものと思われます。
ライブラリ内でローカルとインターネットとで DNS サーバーを分けられるかも知れませんが、私にはそこまで解明しておらず、やり方も知りません。

ESP32 や M5Stack で DNS SSL サーバーを作った場合、スマホ等と通信する概要は以下の感じです。

ESP32 または M5Stack が soft AP モードならば、デバイスを選ばずに何でも接続できるようです。

ただ、インターネットに接続された環境の LAN内で使いたい場合は、次に紹介する mDNS を使った方が確実です

mDNS について

これも正直詳しくありませんのでご容赦を。

mDNS とは multicast DNS の略で、DNS サーバーは使いません。
ローカルネットワーク内をマルチキャストでクエリ?を使ってデバイスに問合せて名前解決するらしいのです。
ちょっと意味が分かりにくいかもしれません。

ネットワーク内で、マルチキャスト用の IP アドレス
( 224.0.0.0 ~ 239.255.255.255 )
というものが事前に設定されているとのことです。
マルチキャストアドレスでアクセスすると、ネットワークのすべてのデバイスにアクセスする様です。

mDNS を使用する場合、ブラウザの URL 欄に入力する名前は、

https://esp32.local

というように、
***.local
任意の名前+ .local を入力します。
そして名前の通り、ローカルエリアネットワーク ( LAN )限定です。

すると、この名前を入力することにより、マルチキャスト用の IP アドレスに変換されて、ネットワーク内のすべてのデバイスに問合せ、IPアドレスに付加されたコマンドみたいなもの(クエリ?)で、対象デバイスがそのクエリを受け入れて、名前を IP アドレスに変換して名前を解決しているのではないかと、個人的に想像しています。

この mDNS のポート番号は、UDP の 5353 を使うらしいです。
インターネットに接続してある LAN ネットワークでも、インターネット上の外部の DNS サーバーに問い合わせることは無いので、ローカルエリア内のデバイスにアクセスすることができます。

先に述べたように、ESP32 や M5Stack でインターネットに接続された WiFiルーター 環境では、DNSserver ライブラリを使ったアクセスできませんので、その場合、この mDNS を使ってローカルエリアネットワークのデバイスにアクセスした方が良いと思います。

一つ、mDNS には欠点があります。
それは、そのデバイスに mDNS をサポートするソフトがインストールされている必要があります

mDNS をサポートする代表的なソフトは、Apple の Bonjour です。
iTunes をインストールすると自動でインストールされるものです。
ですから、iPhone や iPad などの iOS Safari はアクセスできます。

最新版の Windows 10 も標準でサポートされているようです。
ただ、Windows 10 の場合、UDPポート 5353 がファイアウォールで無効になっている場合があるらしく、設定し直さなければいけない場合もあるようです。
また、ちょっと古いバージョンの Windows は、iTunes などに同梱されている Bonjour を別途インストールする必要があるようです。
私の手持ちPC の Windows 10 の場合は Google Chrome ではアクセスできますが、Edge や InternetExplorer ではアクセスできませんでした。
これは謎です。

そして、注意しなければいけないのは、
Android は mDNS をサポートしていないようです
( Android 8.0.0 で試した結果。2018/11時点 )
(たぶん・・・)
これは残念!!!
Android スマホで DNS ネームを使って ESP32 や M5Stack にアクセスしたい場合は、soft AP モードでアクセスすることですね。

ということで、mDNS で ESP32 や M5Stack が STA モードで接続する場合の概要は以下のような感じです。

ただ、クライアントが iOS の iPhoe や iPad の場合は、soft AP モードでもOKでした。

ということで、今回の場合、iOS は全てに対応していることが分かったので、iOS に軍配を上げたいと思います。

では前置きが長くなりましたが、次では ESP32 および M5Stack で DNS ネームの SSL サーバーの作り方を紹介してみたいと思います。

コメント

  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をコピーしました