「マイクロソフト系技術情報 Wiki」は、「Open棟梁Project」,「OSSコンソーシアム .NET開発基盤部会」によって運営されています。
目次 †
概要 †
MQTTブローカーのOSS
詳細 †
ブローカーモデル †
Producer †
送信する人
Consumer †
受信する人
Message †
送受信対象のメッセージ
Queue †
キュー
Topic †
- トピック
- / から始まる Unicode UTF-8 文字列
- 全長 65535 バイト以下
- ヌル文字を含まない
- ワイルドカード
- #:マルチレベル・ワイルドカード(その階層以下の全トピック文字列と一致)
- +:シングルレベル・ワイルドカード(当該階層以下の全トピック文字列と一致)
インストール †
http://mosquitto.org/download/
ブローカー起動 †
>cd C:\Program Files\Mosquitto
>mosquitto -v
送受信 †
その他の環境 †
Linux †
Raspberry Pi †
Docker on Windows †
ミドルウェアなので、コチラの作法で動かせるっぽい。
(ただし、コンフィグ・ファイルの準備は必要)
https://github.com/OpenTouryoProject/DxCommon/tree/develop/Edge/Mosquitto/IaC
Docker on Raspberry Pi †
...
SaaS / PaaS †
- Azure:Azure IoT Hub
- Azure:AWS IoT Core(ブリッジ機能)
- GCP:Cloud Pub/Sub?
認証 †
パスワード †
証明書 †
送受信(C#) †
Paho M2Mqtt †
最近、更新頻度が落ちてきている。
- 受信
using System;
using System.Text;
using uPLibrary.Networking.M2Mqtt;
using uPLibrary.Networking.M2Mqtt.Messages;
namespace M2MqttSub
{
class Program
{
static void Main(string[] args)
{
var client = new MqttClient("127.0.0.1");
client.MqttMsgPublishReceived += (sender, eventArgs) =>
{
var msg = Encoding.UTF8.GetString(eventArgs.Message);
var topic = eventArgs.Topic;
Console.WriteLine(topic + ", " + msg);
};
var ret = client.Connect(Guid.NewGuid().ToString());
Console.WriteLine("Connected with result code {0}", ret);
client.Subscribe(new[] { "test" }, new[] { MqttMsgBase.QOS_LEVEL_EXACTLY_ONCE });
while (client.IsConnected)
{
}
}
}
}
- 送信
using System;
using System.Text;
using uPLibrary.Networking.M2Mqtt;
namespace M2MqttPub
{
class Program
{
static void Main(string[] args)
{
var client = new MqttClient("127.0.0.1");
var ret = client.Connect(Guid.NewGuid().ToString());
Console.WriteLine("Connected with result code {0}", ret);
while (client.IsConnected)
{
var msg = "Test message from Publisher " + DateTime.Now;
client.Publish("test", Encoding.UTF8.GetBytes(msg), 0, true);
Console.WriteLine("Message published.");
System.Threading.Thread.Sleep(1500);
}
}
}
}
MQTTnet †
更新が頻繁で、トータル・ダウンロードがPaho M2Mqttの4倍以上
- 以下は認証フル実装だが、証明書検証を無効化している。
CertificateValidationHandler?で原因を見ると、
SslPolicyErrors?.RemoteCertificateChainErrors?が出ている。
- 受信
using System;
using System.Text;
using System.Collections.Generic;
using System.Threading.Tasks;
using MQTTnet;
using MQTTnet.Client;
using MQTTnet.Client.Options;
using MQTTnet.Client.Connecting;
using MQTTnet.Client.Receiving;
using System.Security.Cryptography.X509Certificates;
namespace msqt_sub
{
class Program
{
private static IMqttClient mqttClient = null;
static async Task Main(string[] args)
{
X509Certificate2 ca = new X509Certificate2("ca.crt");
X509Certificate2 cli = new X509Certificate2("client.pfx", "xxxxx");
var factory = new MqttFactory();
Program.mqttClient = factory.CreateMqttClient();
var options = new MqttClientOptionsBuilder()
.WithClientId("ef3614fca42b32d3")
.WithTcpServer("localhost", 8883)
.WithCredentials("guest", "guest")
.WithTls(new MqttClientOptionsBuilderTlsParameters(){
UseTls = true,
SslProtocol = System.Security.Authentication.SslProtocols.Tls12,
AllowUntrustedCertificates = true,
//CertificateValidationCallback = (a, b, c, d) => true,
CertificateValidationHandler = (o) =>
{
Console.WriteLine(o.ToString());
return true;
},
Certificates = new List<X509Certificate>()
{
ca, cli
}
})
.Build();
// 接続後のイベントハンドラの設定
Program.mqttClient.ApplicationMessageReceivedHandler
= new MqttApplicationMessageReceivedHandlerDelegate(OnAppMessage);
Program.mqttClient.ConnectedHandler
= new MqttClientConnectedHandlerDelegate(OnConnected);
// 接続
await Program.mqttClient.ConnectAsync(options);
// 待機
Console.ReadLine();
}
static private async void OnConnected(MqttClientConnectedEventArgs e) {
await Program.mqttClient.SubscribeAsync(
new TopicFilterBuilder()
.WithTopic("test").Build());
}
static private void OnAppMessage(MqttApplicationMessageReceivedEventArgs e)
{
string payload = Encoding.UTF8.GetString(e.ApplicationMessage.Payload);
Console.WriteLine(payload);
}
}
}
- 送信
using System;
using System.Text;
using System.Collections.Generic;
using System.Threading.Tasks;
using MQTTnet;
using MQTTnet.Client;
using MQTTnet.Client.Options;
using System.Security.Cryptography.X509Certificates;
namespace msqt_pub
{
class Program
{
private static IMqttClient mqttClient = null;
static async Task Main(string[] args)
{
X509Certificate2 ca = new X509Certificate2("ca.crt");
X509Certificate2 cli = new X509Certificate2("client.pfx", "xxxxx");
var factory = new MqttFactory();
Program.mqttClient = factory.CreateMqttClient();
var options = new MqttClientOptionsBuilder()
.WithClientId("ef3614fca42b32d3")
.WithTcpServer("localhost", 8883)
.WithCredentials("guest", "guest")
.WithTls(new MqttClientOptionsBuilderTlsParameters(){
UseTls = true,
SslProtocol = System.Security.Authentication.SslProtocols.Tls12,
AllowUntrustedCertificates = true,
//CertificateValidationCallback = (a, b, c, d) => true,
CertificateValidationHandler = (o) =>
{
Console.WriteLine(o.ToString());
return true;
},
Certificates = new List<X509Certificate>()
{
ca, cli
}
})
.Build();
// 接続
await Program.mqttClient.ConnectAsync(options);
// メッセージの送信するための設定
var message = new MqttApplicationMessageBuilder()
.WithTopic("test")
.WithPayload("hoge")
.WithExactlyOnceQoS()
.Build();
// メッセージの送信 publish
await Program.mqttClient.PublishAsync(message);
}
}
}
チュートリアル †
証明書認証(サーバー認証とクライアント認証)+パスワード認証を構成し、Paho M2Mqtt、MQTTnetからアクセスする。
サーバー認証 †
コチラとコチラが参考になる。
- 認証局の証明書を作成する。
>openssl req -new -x509 -days 365 -extensions v3_ca -keyout ca.key -out ca.crt
Generating a RSA private key
................................................+++++
............+++++
writing new private key to 'ca.key'
Enter PEM pass phrase:
Verifying - Enter PEM pass phrase:
-----
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [AU]:JP
State or Province Name (full name) [Some-State]:
Locality Name (eg, city) []:
Organization Name (eg, company) [Internet Widgits Pty Ltd]:
Organizational Unit Name (eg, section) []:
Common Name (e.g. server FQDN or YOUR name) []:hogeca
Email Address []:
- 証明書要求の作成
>openssl req -out server.csr -key server.key -new
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [AU]:JP
State or Province Name (full name) [Some-State]:
Locality Name (eg, city) []:
Organization Name (eg, company) [Internet Widgits Pty Ltd]:
Organizational Unit Name (eg, section) []:
Common Name (e.g. server FQDN or YOUR name) []:localhost
Email Address []:
Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:
- サーバー証明書の発行
>openssl x509 -req -in server.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out server.crt -days 365
Signature ok
subject=C = JP, ST = Some-State, O = Internet Widgits Pty Ltd, CN = localhost
Getting CA Private Key
Enter pass phrase for ca.key:
- 証明書ファイルの配置
証明書ファイルをインストール・ディレクトリ直下のcertsディレクトリに配置
- 認証局のCNとサーバーのCNが同じ場合、以下のエラーが表示される。
- SSL routines:tls_process_server_certificate:certificate verify failed
- SSL routines:ssl3_read_bytes:tlsv1 alert unknown ca
- Connection error: Connection Refused: not authorised.が出る。
「allow_anonymous true」を設定ファイルに追加する。
クライアント認証 †
コチラとコチラが参考になる。
- 証明書要求の作成
>openssl req -out client.csr -key client.key -new
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [AU]:
State or Province Name (full name) [Some-State]:
Locality Name (eg, city) []:
Organization Name (eg, company) [Internet Widgits Pty Ltd]:
Organizational Unit Name (eg, section) []:
Common Name (e.g. server FQDN or YOUR name) []:hogecli
Email Address []:
Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:
- クライアント認証の発行
>openssl x509 -req -in client.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out client.crt -days 365
Signature ok
subject=C = AU, ST = Some-State, O = Internet Widgits Pty Ltd, CN = hogecli
Getting CA Private Key
Enter pass phrase for ca.key:
- 証明書ファイルの配置
証明書ファイルをインストール・ディレクトリ直下のcertsディレクトリに配置
- クライアント証明書の設定
mosquitto.confに以下を追加
require_certificate true
パスワード認証 †
- ハマりどころ
パスワードは「-p」ではなく「-P」で指定する。
Paho M2Mqtt からアクセス †
- 認証局の証明書(ca.crt)は、証明書ストアの
信頼されたルート証明機関に入れておく必要がある。
- 証明書やパスワードの追加実装を行う。
X509Certificate2 ca = new X509Certificate2("ca.crt");
X509Certificate2 cli = new X509Certificate2("client.pfx", "xxxxx");
var client = new MqttClient("localhost", 8883, true, ca, cli, MqttSslProtocols.TLSv1_2);
client.ProtocolVersion = MqttProtocolVersion.Version_3_1_1;
var ret = client.Connect(Guid.NewGuid().ToString(), "guest", "guest");
- デバッグ実行で動作確認
WindowsはPublisherだけ動作確認済み。
MQTTnetからアクセス †
コチラの実装で動作すると思う。
サーバー認証 †
※ ca_certificatesフォルダがあったので、
CAのファイルはそちらに配置した方が良いカモ。
クライアント認証 †
- ファイル設定
以下を追記
require_certificate true
パスワード認証 †
Paho M2Mqtt からアクセス †
- /dev/msqt_pubとか言うフォルダを作成
- プロジェクトを作成し
$ dotnet new console
- 認証局の証明書(ca.crt)は、証明書ストアの
信頼されたルート証明機関に入れておく必要がある。
MQTTnetからアクセス †
コチラの実装で動作した。
正規の証明書 †
正規のCN、場合によっては、
証明書ストアへの登録が必要なのかもしれない。
参考 †
Qiita †
.NETライブラリ †
Tags: :通信技術, :.NET開発, :IoT
|