MQTTnet入门(三) - 使用证书创建SSL加密端口

5 篇文章 6 订阅
5 篇文章 1 订阅

MQTTnet入门(三) - 使用证书创建SSL加密端口

前言

在上一篇《MQTTnet入门(二) - 验证来自MQTT客户端的连接请求》中,实现了MQTT服务器对客户端连接请求的验证,然而在1883端口上采用的是最原始的TCP方式连接,这是极不安全的,本章会给出使用证书创建SSL加密端口并通信的完整示例,并且尽可能详尽的描述作者在实现该例程时所做的所有工作。

使用证书创建SSL加密端口Demo

创建证书

我们需要创建用于MQTT通信加密的证书,OpenSSL最常用的证书生成工具之一,我所使用的OpenSSL是运行在Linux下的命令行工具,但我相信大多数.Net Core的开发者还是在Windows平台下进行开发,好在Win10集成的Ubuntu子系统,因此我们可以不必运行虚拟机或是云服务去执行我们的OpenSSL。Win10下运行Ubuntu与本无关联不大,我将详细步骤放在了附录中,有需要可以自行翻阅。

启动Win10下的Ubuntu后,进入/mnt/ 会看见Windows的磁盘驱动器都挂载在了这里,因此我们可以从这里访问到我们要创建证书的路径。
在这里插入图片描述

若尚未安装OpenSSL,可使用命令“sudo apt-get install openssl”快速安装。

创建证书命令示例(提示:创建过程中会要求输入密码和证书创建者信息,请妥善保管密码。):

openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -days 365
openssl pkcs12 -export -out certificate.pfx -inkey key.pem -in cert.pem

如此,证书及密钥对就创建完成了:
在这里插入图片描述

编写MQTT服务端代码

代码是基于上一篇Demo进行的改进,运行前需修改证书文件“certificate.pfx”的路径,设置证书密码。

using MQTTnet;
using MQTTnet.Protocol;
using MQTTnet.Server;
using System;
using System.IO;
using System.Reflection;
using System.Security.Authentication;
using System.Security.Cryptography.X509Certificates;

namespace MQTT
{
    class Program
    {
        private const string CERTIFICATE_FILE_PATH  = "./certificate.pfx";  // 证书文件路径
        private const string CERTIFICATE_PASSWORD   = "创建证书时的密码";  	// 证书文件密匙
        private const UInt16 EncryptedEndpointPort  = 1884;                 // 加密端口号

        static async System.Threading.Tasks.Task Main(string[] args)
        {
            // 创建MQTT服务配置的构建器
            MqttServerOptionsBuilder optionsBuilder = new MqttServerOptionsBuilder();

            // 读取证书文件
            X509Certificate2 certificate = new X509Certificate2(CERTIFICATE_FILE_PATH, CERTIFICATE_PASSWORD, X509KeyStorageFlags.Exportable);
            // 关闭默认端口(1883端口)
            optionsBuilder.WithoutDefaultEndpoint();
            // 启用加密端口
            optionsBuilder.WithEncryptedEndpoint();
            // 设置加密端口号
            optionsBuilder.WithEncryptedEndpointPort(EncryptedEndpointPort);
            // 设置加密端口所使用的证书
            optionsBuilder.WithEncryptionCertificate(certificate.Export(X509ContentType.Pfx));
            // 设置加密端口所使用的SSL协议
            optionsBuilder.WithEncryptionSslProtocol(SslProtocols.Tls12);

            // 为构建器添加连接验证的处理过程
            optionsBuilder.WithConnectionValidator(context => {

                // 验证ClientID的长度
                if (context.ClientId.Length < 10)
                {
                    context.ReasonCode = MqttConnectReasonCode.ClientIdentifierNotValid;
                    return;
                }

                // 验证用户名和密码
                if (context.Username != "user01" || context.Password != "123456")
                {
                    context.ReasonCode = MqttConnectReasonCode.BadUserNameOrPassword;
                    return;
                }

                // 标记当前连接请求的ReasonCode为Success
                context.ReasonCode = MqttConnectReasonCode.Success;
            });

            // 利用MqttFactory创建MQTT服务器
            IMqttServer mqttServer = new MqttFactory().CreateMqttServer();

            // 采用异步方式启动服务(使用服务配置构建器创建的对象)
            await mqttServer.StartAsync(optionsBuilder.Build());

            Console.WriteLine("按任意键退出程序...");
            Console.ReadLine();

            // 异步关闭MQTT服务
            await mqttServer.StopAsync();
        }
    }
}

连接测试

测试用的MQTT客户端是MQTT.FX,填写连接信息:

MQTT.FX是一款用Java开发的跨平台的MQTT可视化客户端,功能全面,便于调试。
下载地址:http://mqttfx.bceapp.com/

在这里插入图片描述
在这里插入图片描述
与MQTT服务端连接成功:
在这里插入图片描述


附录一:Win10下的Ubuntu子系统

打开Microsoft Store。
在这里插入图片描述
搜索关键字“Ubuntu”,选择想要安装的版本,单击获取。
在这里插入图片描述
在这里插入图片描述
从控制面板中打开“程序”,打开“启用或关闭Windows功能”
在这里插入图片描述
勾选“适用于Linux的Windows子系统”,完成后重启。
在这里插入图片描述
重启完成后,打开安装完成的Ubuntu就OK啦~
在这里插入图片描述


附录二:MQTTnet API - Server Options

MqttServerOptionsBuilder类

构建选项类

Description: Builds the options class.

方法原型:Build()

允许处理来自客户端的所有已发布消息

Description: Allows to work with all published messaged from the clients.

方法原型:WithApplicationMessageInterceptor(IMqttServerApplicationMessageInterceptor value)

允许处理来自客户端的所有已发布消息

Description: Allows to work with all published messaged from the clients.

方法原型:WithApplicationMessageInterceptor(Action value)

设置用于服务器的客户端ID

Description: Sets the client id used for the server.

方法原型:WithClientId(string value)

设置要保留的连接数

Description: Sets the number of connections to keep.

方法原型:WithConnectionBacklog(int value)

启用自定义的处理程序验证连接

Description: Allows to validate connections with a custom handler.

方法原型:WithConnectionValidator(IMqttServerConnectionValidator value)

启用自定义的处理程序验证连接

Description: Allows to validate connections with a custom handler.

方法原型:WithConnectionValidator(Action value)

设置服务器的默认的通信超时时长

Description: Tells the server to use the default communication timeout.

方法原型:WithDefaultCommunicationTimeout(TimeSpan value)

服务器启用默认端口

Description: Tells the server to use the default endpoint.

方法原型:WithDefaultEndpoint()

设置服务器使用默认端口的IPv4地址

Description: Tells the server to use the default endpoint IPv4 address.

方法原型:WithDefaultEndpointBoundIPAddress(IPAddress value)

设置服务器使用默认端口的IPv6地址

Description: Tells the server to use the default endpoint IPv6 address.

方法原型:WithDefaultEndpointBoundIPV6Address(IPAddress value)Tells the server to use the default endpoint IPv6 address.

服务器启用默认加密端口

Description: Tells the server to use the default endpoint port.

方法原型:WithDefaultEndpointPort(int value)

服务器启用加密端口

Description: Tells the server to use the encrypted endpoint.

方法原型:WithEncryptedEndpoint()

设置服务器使用加密端口的IPv4地址

Description:

方法原型:WithEncryptedEndpointBoundIPAddress(IPAddress value)

设置服务器使用加密端口的IPv6地址

Description: Tells the server to use the encrypted endpoint IPv6 address.

方法原型:WithEncryptedEndpointBoundIPV6Address(IPAddress value)

设置服务器用于SSL加密连接的端口号

Description: Tells the server to use the encrypted endpoint port.

方法原型:WithEncryptedEndpointPort(int value)

设置服务器用于SSL加密连接的证书

Description: Tells the server to use the certificate for SSL connections.

方法原型:WithEncryptionCertificate(byte[] value)

设置服务器用于加密的SSL协议类型

Description: Tells the server to use the SSL protocol level.

方法原型:WithEncryptionSslProtocol(SslProtocols value)

告诉服务器允许每个客户端最大的挂起消息

Description: Tells the server to allow a maximum of pending messages per client.

方法原型:WithMaxPendingMessagesPerClient(int value)

允许服务器保留会话

Description: Tells the server to persist sessions.

方法原型:WithPersistentSessions()

允许服务器使用存储

Description: Tells the server to use a storage.

方法原型:WithStorage(IMqttServerStorage value)

允许处理来自客户端的所有订阅

Description: Allows to work with all subscriptions from the clients.

方法原型:WithSubscriptionInterceptor(IMqttServerSubscriptionInterceptor value)

允许处理来自客户端的所有订阅

Description: Allows to work with all subscriptions from the clients.

方法原型:WithSubscriptionInterceptor(Action value)

禁用默认(非SSL)端口

Description: Disables the default (non SSL) endpoint.

方法原型:WithoutDefaultEndpoint()

禁用默认(SSL)端口

Description: Disables the default (SSL) endpoint.

方法原型:WithoutEncryptedEndpoint()

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

猿长大人

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值