美文网首页
MQTT(二)在 mosquitto 中调试 mosquitto

MQTT(二)在 mosquitto 中调试 mosquitto

作者: 蓝笔头 | 来源:发表于2021-07-02 12:39 被阅读0次

    前言

    在前文 编译 mosquitto 和 mosquitto-auth-plug 中,详细描述了 mosquittomosquitto-auth-plug 的编译构建过程。

    接下来,我们将开始在 编译 mosquitto 和 mosquitto-auth-plug 基础上,对 mosquitto-auth-plug 进行调试。

    调试 mosquitto-auth-plug 用户鉴权

    mosquitto 项目的 mosquitto_plugin.h 文件中的用户鉴权接口定义。

    /*
     * Function: mosquitto_auth_unpwd_check
     *
     * This function is OPTIONAL. Only include this function in your plugin if you
     * are making basic username/password checks.
     *
     * Called by the broker when a username/password must be checked.
     *
     * Return:
     *  MOSQ_ERR_SUCCESS if the user is authenticated.
     *  MOSQ_ERR_AUTH if authentication failed.
     *  MOSQ_ERR_UNKNOWN for an application specific error.
     *  MOSQ_ERR_PLUGIN_DEFER if your plugin does not wish to handle this check.
     */
    mosq_plugin_EXPORT int mosquitto_auth_unpwd_check(void *user_data, struct mosquitto *client, const char *username, const char *password);
    

    1)查询 auth-plug.somosquitto-auth-plug 编译结果)的位置。

    $ pwd
    /tmp/tmp.dHVBlwblW0
    $ ls -al | grep .so
    -rwxr-xr-x  1 meikai meikai 61584 Jul  2 11:05 auth-plug.so
    

    2)在 mosquitto 项目中的 mosquitto.conf 文件中新增如下配置:

    # -----------------------------------------------------------------
    # External authentication and topic access plugin options
    # -----------------------------------------------------------------
    
    # External authentication and access control can be supported with the
    # auth_plugin option. This is a path to a loadable plugin. See also the
    # auth_opt_* options described below.
    #
    # The auth_plugin option can be specified multiple times to load multiple
    # plugins. The plugins will be processed in the order that they are specified
    # here. If the auth_plugin option is specified alongside either of
    # password_file or acl_file then the plugin checks will be made first.
    #
    #auth_plugin
    auth_plugin /tmp/tmp.dHVBlwblW0/auth-plug.so
    

    3)启动 mosquitto 进程

    命令启动

    $ /tmp/tmp.rcJYQzXv2I/cmake-build-debug/src/mosquitto -c /tmp/tmp.rcJYQzXv2I/mosquitto.conf
    

    或者,在 CLion 中添加 【Program arguments】的形式启动


    image.png

    控制台输出:

    1625195356: mosquitto version 2.0.11 starting
    1625195356: Config loaded from /tmp/tmp.rcJYQzXv2I/mosquitto.conf.
    1625195356: Loading plugin: /tmp/tmp.dHVBlwblW0/auth-plug.so
    1625195356: |-- *** auth-plug: startup
    |-- No backends configured.
    |-- *** ABORT.
    

    mosquitto-auth-plug 项目的 auth-plug.c 文件中可以找到 No backends configured 日志对应的代码行。

    4)完善第(2)步 mosquitto.conf 文件中的 auth_plugin 配置。

    #auth_plugin
    auth_plugin /tmp/tmp.dHVBlwblW0/auth-plug.so
    auth_opt_backends redis
    

    控制台输出:

    /tmp/tmp.rcJYQzXv2I/cmake-build-debug/src/mosquitto -c /tmp/tmp.rcJYQzXv2I/mosquitto.conf
    1625195930: mosquitto version 2.0.11 starting
    1625195930: Config loaded from /tmp/tmp.rcJYQzXv2I/mosquitto.conf.
    1625195930: Loading plugin: /tmp/tmp.dHVBlwblW0/auth-plug.so
    1625195930: |-- *** auth-plug: startup
    1625195930: |-- ** Configured order: redis
    
    1625195930: |-- }}}} Redis
    1625195930: Starting in local only mode. Connections will only be possible from clients running on this machine.
    1625195930: Create a configuration file which defines a listener to allow remote access.
    1625195930: For more details see https://mosquitto.org/documentation/authentication-methods/
    1625195930: Opening ipv4 listen socket on port 1883.
    1625195930: Opening ipv6 listen socket on port 1883.
    1625195930: Error: Cannot assign requested address
    1625195930: mosquitto version 2.0.11 running
    

    【安装 redis】

    问题:

    1625195544: |-- }}}} Redis
    1625195544: |-- Redis connection error: Connection refused for localhost:6379
    
    |-- redis init returns NULL
    |-- *** ABORT.
    

    解决方法,安装 redis-server:

    $ sudo apt install redis-server
    

    安装后使用 redis-cli 命令进行测试

    $ redis-cli
    127.0.0.1:6379> keys *
    (empty list or set)
    

    5)通过 mosquitto_sub 命令连接到 mosquitto 进程。

    $ /tmp/tmp.rcJYQzXv2I/cmake-build-debug/client/mosquitto_sub -t test -u admin -P 123456
    Connection error: Connection Refused: not authorised.
    
    • -t:指定 topic
    • -u:指定 broker 访问用户
    • -P:指定 broker 访问密码

    broker 指的就是 mosquitto 进程。

    $ /tmp/tmp.rcJYQzXv2I/cmake-build-debug/src/mosquitto -h
    mosquitto version 2.0.11
    
    mosquitto is an MQTT v5.0/v3.1.1/v3.1 broker.
    ...
    

    6)修改 mosquitto-auth-plug 项目的 auth-plug.c 文件中的 mosquitto_auth_unpwd_check 方法:

    match = (strcmp((char *)password, phash) == 0);
    

    修改前后对比如下所示:


    7)重新编译 mosquitto-auth-plug 项目生成 auth-plug.so 并运行 mosquitto 项目。并在在 redis 中设置配置鉴权使用的用户名和密码。

    meikai@test:~$ redis-cli
    127.0.0.1:6379> set admin 123456
    OK
    127.0.0.1:6379> get admin
    "123456"
    

    8)再次通过 mosquitto_sub 连接到 mosquitto 进程。

    # 连接成功
    $ /tmp/tmp.rcJYQzXv2I/cmake-build-debug/client/mosquitto_sub -t test -u admin -P 123456
    
    # 连接失败
    $ /tmp/tmp.rcJYQzXv2I/cmake-build-debug/client/mosquitto_sub -t test -u adminP 1234567
    Connection error: Connection Refused: not authorised.
    

    调试 mosquitto-auth-plug topic 鉴权

    mosquitto 项目的 mosquitto_plugin.h 文件中的 topic 鉴权接口定义。

    /*
     * Function: mosquitto_auth_acl_check
     *
     * Called by the broker when topic access must be checked. access will be one
     * of:
     *  MOSQ_ACL_SUBSCRIBE when a client is asking to subscribe to a topic string.
     *                     This differs from MOSQ_ACL_READ in that it allows you to
     *                     deny access to topic strings rather than by pattern. For
     *                     example, you may use MOSQ_ACL_SUBSCRIBE to deny
     *                     subscriptions to '#', but allow all topics in
     *                     MOSQ_ACL_READ. This allows clients to subscribe to any
     *                     topic they want, but not discover what topics are in use
     *                     on the server.
     *  MOSQ_ACL_READ      when a message is about to be sent to a client (i.e. whether
     *                     it can read that topic or not).
     *  MOSQ_ACL_WRITE     when a message has been received from a client (i.e. whether
     *                     it can write to that topic or not).
     *
     * Return:
     *  MOSQ_ERR_SUCCESS if access was granted.
     *  MOSQ_ERR_ACL_DENIED if access was not granted.
     *  MOSQ_ERR_UNKNOWN for an application specific error.
     *  MOSQ_ERR_PLUGIN_DEFER if your plugin does not wish to handle this check.
     */
    mosq_plugin_EXPORT int mosquitto_auth_acl_check(void *user_data, int access, struct mosquitto *client, const struct mosquitto_acl_msg *msg);
    
    #define MOSQ_ACL_READ 0x01
    #define MOSQ_ACL_WRITE 0x02
    #define MOSQ_ACL_SUBSCRIBE 0x04
    
    struct mosquitto_acl_msg {
        const char *topic;
        const void *payload;
        long payloadlen;
        int qos;
        bool retain;
    };
    

    1)在 mosquitto 项目中的 mosquitto.conf 文件中新增如下配置:

    auth_opt_redis_aclquery GET acl:%s:%s
    

    2)通过 mosquitto_sub 连接到 mosquitto 进程。

    $ /tmp/tmp.rcJYQzXv2I/cmake-build-debug/client/mosquitto_sub -t test -u admin -P 123456
    All subscription requests were denied.
    

    3)在 redis 中设置配置 topic 鉴权使用的 key 和 access 值。

    meikai@test:~$ redis-cli
    127.0.0.1:6379> get acl:admin:test
    (nil)
    127.0.0.1:6379> set acl:admin:test 4
    OK
    127.0.0.1:6379> get acl:admin:test
    "4"
    

    4)再次通过 mosquitto_sub 连接到 mosquitto 进程。

    # 连接成功
    $ /tmp/tmp.rcJYQzXv2I/cmake-build-debug/client/mosquitto_sub -t test -u admin -P 123456
    
    # 连接失败
    $ /tmp/tmp.rcJYQzXv2I/cmake-build-debug/client/mosquitto_sub -t test123 -u admin -P 123456
    All subscription requests were denied.
    

    至此,已经对 mosquitto-auth-plug 实现的【用户鉴权】和【topic 鉴权】进行了初步调试。
    后面有机会再进行深入剖析。

    参考

    相关文章

      网友评论

          本文标题:MQTT(二)在 mosquitto 中调试 mosquitto

          本文链接:https://www.haomeiwen.com/subject/erueultx.html