「ESP8266 Arduino スケッチ Tips」 接続先は本物?

2016/06/17

verify_1200

前回は、ESP8266とMQTT接続のTLSによる暗号化を取り上げました。今回は、接続先が本物か偽物かを確かめるための、電子証明の確認を取り上げます。

この記事はESP8266 Arduino Coreのバージョンは2.5.1以上を使用することを前提にしています。

電子証明の確認?

ESP8266とMQTTブローカーの接続を暗号化することで、通信の中身を見ることは難しくなります。ただし、「接続したブローカーを、真の接続先と確認していれば」です。

接続先を確認しないと、偽の接続先と暗号接続してしまう危険があり、通信の中身を盗まれる可能性がでてきます。接続先を装う攻撃は、「なりすまし」や「中間者攻撃」と呼ばれています。

MQTTの暗号接続で使うTLSでは、接続先から送られてくる「電子証明」を確認することで、接続先の確認をします。

電子証明書の確認

ESP8266 の Arduino スケッチでは、次の方法のいずれかで電子証明書の信頼性の確認ができます。

  • 接続先サーバの電子証明書を発行した認証機関のCA証明書を使う
  • 接続先サーバの電子証明書の拇印を確認する

今回はスケッチへの命令の追加が少なくて済む拇印の確認の方法を紹介します。

フィンガープリントは、信頼できる方法であらかじめ入手した電子証明ファイル(通常.crtといった拡張子です)を、OSに付属の証明書を表示するツールなどで表示させることであらかじめ調べておきます。

cert_image

opensslをインストール済の場合はコマンド入力やターミナル画面で次のopensslコマンドを使い拇印を確認することもできます。iot.eclipse.orgやポート番号8883は実際に調べたい接続先のものに変えます。

Linux

openssl s_client -connect iot.eclipse.org:8883 < /dev/null 2>/dev/null | openssl x509 -fingerprint -noout -in /dev/stdin


Windows


"C:\Program Files\OpenSSL-Win64\bin\openssl" s_client -connect iot.eclipse.org:8883 < NUL 2> NUL |"C:\Program Files\OpenSSL-Win64\bin\openssl" x509 -noout -fingerprint

スケッチの例

拇印を定義

const char* mqtt_server = "mqtt.example.com";
const char* mqttFingerprint = "4D:E9:06:27:9E:7E:07:1F:A7:FE:A5:D7:A0:E1:6C:5B:86:2D:DC:12"; 
WiFiClientSecure espClient;

Arduinoスケッチのsetup部分に拇印で証明書を検証するための二つの命令 allowSelfSignedCertsとsetFingerprintを追加します。setInsecure()はコメントアウトして無効にします。

setup_wiFi();
//espClient.setInsecure();
espClient.allowSelfSignedCerts();
espClient.setFingerprint(mqttFingerprint);

ネットワークや拇印の不一致などの理由でMQTTブローカーと接続できないときに動かす命令に、証明書エラー内容をシリアルモニタに送信する命令を追加します。

     if (client.connect(clientId.c_str())) {
    Serial.println("connected");
      // Once connected, publish an announcement...
      client.publish("outTopic", "hello world");
      // ... and resubscribe
      client.subscribe("inTopic");
    } else {
      Serial.print("failed, rc=");
      Serial.print(client.state());
      Serial.println(" try again in 5 seconds");
      char buf[256];
      espClient.getLastSSLError(buf,256);
      Serial.print("SSL error: ");
      Serial.println(buf);
      // Wait 5 seconds before retrying
      delay(5000);
    }

小さなマイコンESP8266に搭載できるセキュリティ機能は限定的なものとなります。言い換えれば、ESP8266のArduinoスケッチで可能なセキュリティ機能は最低限必要なセキュリティということもできますので、利用するようにしているとよいかもしれません。