MQTT(二)在 mosquitto 中调试 mosquitto

2021-07-02  本文已影响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.

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 鉴权】进行了初步调试。
后面有机会再进行深入剖析。

参考

上一篇下一篇

猜你喜欢

热点阅读