mosquito服务器实现 ssl/tls 安全配置通信

1、ssl/tls通信证书配置

        要想实现moquitto 服务器证书加密通信,首先要自己生成client 和server的证书,证书生成又需要签名证书,一般签名证书是第三方机构来提供,但我们自己也可以实现签名证书生成,下面是具体签名证书的生成步骤:

1.1 生成自己CA签发证书(该证书用于给server和client 生成证书)

        1.1.1 生成 rootca 证书命令

                openssl genrsa -out rootCA.key 2048

        1.1.2 根据key 生成csr 文件(发给ca 机构,生成crt证书)

              openssl req -new -out rootCA.csr -key rootCA.key

                     注意:这里会提示 输入国家,省份,城市,公司,等等信息,可以自定义填写,但要记住你填了什么,因为后面签发client, server证书的时候也需要;

         1.1.3 CA机构根据CSR(证书签发请求)(自己给自己)签发证书

              openssl x509 -req -sha1 -in rootCA.csr -out rootCA.crt -signkey rootCA.key -days 3650

         到此签发证书已经生成,会在目录一下看到有rootCA.csr rootCA.crt rootCA.key 三个文件

        rootCA.crt 就是后面要用的签发证书;

1.2  使用上面制作的签发跟证书为server 和client 生成相应的私钥和证书

        1.2.1 先生成server key, 在用server key 生成server csr(签名请求),使用root ca (          证                  书签发机构CA)和server csr 生成server.crt 证书

                首先自己生成server的私钥,

               openssl genrsa -out server.key 2048

                生成签名请求 server.csr(用于生成证书)

             openssl req -new -out server.csr -key server.key

             使用私钥,根证书,生成证书

        openssl x509 -req -in server.csr -CA rootCA.crt -CAkey rootCA.key -CAcreateserial -out server.crt -days 3650

到此server.key 和server.crt 已生成; client 证书通过以上三条命令生成

注:Client 一样 (common name server 和client 应该都是server ip) CA 的common name 应该设置为0.0.0.0

1.2.2 证书校验命令

openssl verify -CAfile ca/rootCA.crt client/client.crt (校验证书是否可以使用)

2. 修改mosquitto 配置文件支持证书加密

cp /etc/mosquito/mosquito.conf.example  /etc/mosquito/mosquito.conf.example

修改配置文件权限,添加mosquitto 权限

groupadd mosquitto

useradd -g mosquitto mosquitto

chown -R mosquitto:mosquitto /etc/mosquitto/

配置允许匿名访问。

allow_anonymous true

require_certificate true 

use_identity_as_username  true           //单双向验证配置, false 单项(默认),true 双向

cafile  (需要填写绝对路径)

certfile (需要填写绝对路径)

修改完配置,重启mosquitto server 即可;

2.2 测试mosquitto 命令

       mosquitto_sub -h 10.30.11.47 -p 8884 -t "mqtt/server/topic" --cafile ./ca/ca.crt &

单项验证

mosquitto_sub -h 10.30.11.47 -p 8883 -t "mqtt/server/topic" --cafile ./ca/ca.crt --cert ./client/client.pem --key ./client/client.key &

双向验证

在启动订阅端的时候,加上“--insecure”参数, 启动的时候将不再校验common name;

3 mosquitto api demo

#include 
#include 
#include 
#include "mosquitto.h"

//server ip
#define HOST "xx.xx.xx.xx"   
#define PORT 8883
#define KEEP_ALIVE 60
#define MSG_MAX_SIZE 512
static int running = 1;

void my_connect_callback(struct mosquitto* mosq, void* obj, int rc)
{
    printf("Call the function:on_connect\n");
    if (rc)
    {
        printf("on_connect error!\n");
        exit(1);
    }
    else
    {
        for (int i = 0; i < 10; i++)
        {
            char topic[1024] = { 0 };
            snprintf(topic, sizeof(topic), "HELLOMQTT%d", i); //连接成功后初始化所有的topic
            if (mosquitto_subscribe(mosq, NULL, topic, 2))
            {
                printf("Set the topic error!\n");
                exit(1);
            }
        }
    }
}

void my_disconnect_callback(struct mosquitto* mosq, void* obj, int rc)
{
    printf("Call the function: my_disconnect_callback\n");
    running = 0;
}

//初始化topic的时候,会调用这个回调
void my_subscribe_callback(struct mosquitto* mosq, void* obj, int mid, int qos_count, const int* granted_qos)
{
    printf("Call the function: on_subscribe\n");
}
//topic 订阅到之后,回调处理
void my_message_callback(struct mosquitto* mosq, void* obj, const struct mosquitto_message* msg)
{
    printf("Call the function: on_message\n");
    printf("Recieve a message of %s: %s\n.", (char*)msg->topic, (char*)msg->payload);
    if (0 == strcmp((const char*)msg->payload, "quit")) {
        mosquitto_disconnect(mosq);
    }
}
//初始化设置cert 和 设置不校验common name (--insecure)
int init_config(struct mosquitto* mosq)
{
    int rc;
    const char* firstMessage = "himqtt";

    if (mosquitto_will_set(mosq, "HELLOMQTT",
        strlen(firstMessage), firstMessage, 0,
        true )) {
        printf("Error: Problem setting will.\n");
        mosquitto_lib_cleanup();
        return 1;
    }

    {
        rc = mosquitto_tls_set(mosq,"Y:/\mosquitto/\ca/\\rootCA.crt",         
                "Y:/\mosquitto/\ca", "Y:/\mosquitto/\client/\client.crt", 
                 "Y:/\mosquitto/\client/\client.key", NULL);
        if (rc) {
            if (rc == MOSQ_ERR_INVAL) {
                printf("Error: Problem setting TLS options: File not found.\n");
            }
            else 
            {
                printf("Error: Problem setting TLS options: %s.\n", 
                   mosquitto_strerror(rc));
            }
            mosquitto_lib_cleanup();
            return 1;
        }
    }
//该函数是设置不校验证书的common name 也就是CN 
    if (mosquitto_tls_insecure_set(mosq, true)) {
        printf("Error: Problem setting TLS insecure option.\n");
        mosquitto_lib_cleanup();
        return 1;
    }
}

int main(int argc, char** argv)
{
    int ret;
    struct mosquitto* mosq;
    ret = mosquitto_lib_init();
    mosq = mosquitto_new("sub_test", true, NULL);
    if (mosq == NULL)
    {
        printf("New sub_test error!\n");
        mosquitto_lib_cleanup();
        return -1;
    }
    init_config(mosq);
    mosquitto_connect_callback_set(mosq, my_connect_callback);
    mosquitto_disconnect_callback_set(mosq, my_disconnect_callback);
    mosquitto_subscribe_callback_set(mosq, my_subscribe_callback);
    mosquitto_message_callback_set(mosq, my_message_callback);

    ret = mosquitto_connect(mosq, HOST, PORT, KEEP_ALIVE);
    if (ret)
    {
        printf("Connect server error!\n");
        mosquitto_destroy(mosq);
        mosquitto_lib_cleanup();
        return -1;
    }
    printf("Start!\n");
    while (running)
    {
        mosquitto_loop(mosq, -1, 1);
        //mosquitto_loop_start(mosq);
    }
    mosquitto_destroy(mosq);
    mosquitto_lib_cleanup();
    printf("End!\n");

    return 0;
}

注意:mosquitto_tls_set    证书配置要写对

           mosquitto_tls_insecure_set(mosq, true)

           要设置不校验CN 不然可能会出现连接mosquitto server的失败

至此mosqutto server的证书双向校验配置结束;虽然写的很简陋,主要是本人配置过程中遇到的一些难点,记录下来;

你可能感兴趣的:(服务器小知识,ssl,服务器,安全)