调试VerneMQ的连接/认证问题,用webhooks和vmq_diversity进行双重认证
TL;DR
https://github.com/vernemq/vernemq/blob/master/apps/vmq_diversity/src/vmq_diversity_plugin.erl
包括一条语句,如果你的Lua脚本返回 "false",它将阻止通过任何其他渠道的认证/授权。
将导致。
而不是像你想象的那样,去尝试其他的插件!
为了避免这个问题,只需 请勿退回任何东西 从你的Lua脚本中,如果你不想处理这个消息的话
调试
VerneMQ有一个内置的跟踪工具,这将帮助你看到哪些问题可能发生。首先,显示会话,以便找出你的客户正在尝试连接哪些数据。
vmq-admin session show
然后运行一个跟踪。
vmq-admin trace client client-id=000000007eaefc47 -mountpoint=5c61a59ba6b76f558d256f42
注意,mountpoint默认为""(Verne的默认mountpoint)--如果你没有在监听器上设置一个自定义的mountpoint(如我),那么你可以省略这个。
最初vmq-admin追踪会报告说没有发现这个客户端的会话--如果你的客户端目前没有连接。
连接你的客户,就会有更多的输出。
将日志记录器的粗略程度提高到调试状态也很有帮助(对于vernemq.conf)。
log.console.level = debug
拒绝的经济
在我的特定情况下,我的webhook端点没有运行。在启动它之后,我现在得到(多次尝试都有类似的输出)。
正如你所看到的,客户端现在被认证了,但没有被授权发布。然后客户端被断开连接(根据MQTT 3.1.1规范)。
而这是日志输出。
这里发生的情况是,客户端使用webhook进行认证,然后它试图使用Lua脚本(MongoDB授权)进行授权。
我不确定为什么客户端的auth_on_publish没有使用webhook来调用。在任何情况下,这个客户端都应该使用MongoDB进行完全认证。
我也只看到关于自动开启注册的请求。
要显示哪些webhooks被注册,你可以运行
vmq-admin webhooks show
见。 https://docs.vernemq.com/plugindevelopment/webhookplugins
所有webhooks都是用POST方法调用的,需要用HTTP代码200来回答才算成功。
对Webhook服务器的请求
下面是Webhook服务器的请求的样子。
头信息被传递,头信息vernemq-hook被设置为 注册时的身份验证(auth_on_register 在这种情况下。
帖子正文将包括试图连接的客户的不同信息。
在使用 "next "作为webhook的回复后,发布工作正常进行--客户端对MongoDB进行了认证,之后发布被授权,如愿以偿。
下面是来自webhook的回答,应该是这样的,以便将认证传递给下一个插件。
{"结果"。"下一个"}
下面是现在的跟踪情况。
在底部,你可以看到客户端的keepalives(PINGREQ, PINGRESP)。
所以,一个客户现在正在工作。继续下一个客户端--它应该使用webhooks进行认证和授权!
Webhook客户端
正如你所看到的,通过MongoDB Lua脚本,mountpoint被从 "piclient "改写为不同的mountpoint。
基本上,我正在使用监听器上的mountpoint来指示这个客户端应该使用哪种认证方法。
在VerneMQ的第二版中,我们得到承诺,每个监听器的插件将被分离 - 因此我们可以避免这些检查,这些检查会增加每个连接的开销。
显然,一次只能运行一个跟踪。在关闭另一个跟踪后再试。
vmq-admin trace client client-id=my_clientid -mountpoint=jsclient
请注意,auth_on_publish debug这个信息是由我在Lua脚本中插入的一个额外语句打印的。
在auth_commons.lua中
了解从Lua脚本返回的内容
我们想要的可能是从Lua脚本中返回下一个钩子应该被调用。
"如果插件不能验证发布信息,最好是返回 下一个
因为这将允许链中的后续插件验证该请求。"
(见 https://docs.vernemq.com/plugindevelopment/publishflow )
我认为,返回 假的 将意味着,但显然不是?
让我们看看vernemq的Erlang源代码
https://github.com/vernemq/vernemq
这是vmq_diversity(Lua脚本所在)的auth_cache的测试套件。
vmq-admin trace client client-id=my_clientid -mountpoint=jsclient
为Lua中的信息增加了一些额外的调试。
函数 auth_on_publish(pub)
print("***auth_on_publish debug***(LUA)")
for k,v in pairs(pub) do
print(k ... " " ... v)
结束
print(pub)
返回错误
结束
请注意,这段代码似乎有问题(假的显然不能在Lua中使用.连接--好的。)
在任何情况下,在作为 "pub "传入的Lua表中,我们有以下参数。
- client_id
- 挂载点
- 有效载荷
- 服务质量
现在我们可以检查挂载点是否为 "jsclient"(应该使用webhooks进行验证),目前强制为true。
函数 auth_on_publish(pub)
print("***auth_on_publish debug***(LUA)")
如果pub["mountpoint"] == "jsclient" 那么
返回true
否则
返回错误
结束
结束
下面是这种人工条件下的跟踪情况。
返回到Erlang
https://github.com/vernemq/vernemq/blob/master/apps/vmq_diversity/src/vmq_diversity_plugin.erl
当调用vmq_diversity_plugin.erl的auth_on_publish时,将得到这样的结果值。
- 如果vmq_diversity_cache:match_publish_acl将返回true,它将是 "ok"。
- 如果它返回false,它将抛出一个错误
- 如果它返回no_cache,结果将取决于all_till_ok函数(与auth_on_publish一起调用)。
正如你所看到的,这里是传递给我们的Lua脚本的值,包括装载点。
conv_res将修改返回的结果。
如果你对Erlang不熟悉,我强烈建议你阅读我之前的文章。 https://pi3g.com/2019/05/12/understanding-erlang-lua-luerl-for-vernemq-mongodb-auth_on_register-hook/
基本上,如果{error, lua_script_returned_false}在结果中没有匹配,对于任何(_)名称和任何其他,结果将是其他--简单地把all_till_ok的结果传递给调用函数。
对于名字 lua_script_returned_false,错误将是not_authorized。
我不完全确定这个vmq_plugin_helper.erl是否是主要的控制逻辑(传递到下一个)。
在任何情况下,可能 "next "都会被返回。
这里,在vmq_diversity_plugin.erl中定义了all_till_ok。
https://github.com/vernemq/vernemq/blob/master/apps/vmq_diversity/src/vmq_diversity_plugin.erl
正如你所看到的,如果脚本返回的是 "true",则返回值被设置为 "ok"。
如果从脚本中返回 "false",就会返回前面提到的错误,并停止执行-->未授权。
这意味着,如果你在Lua脚本中返回false,就不会有其他插件被调用。
或者,可以返回修饰语。
诀窍是 不退任何东西。 以防你不想处理这个请求。
函数 auth_on_publish(pub)
print("***auth_on_publish debug***(LUA)")
如果pub["mountpoint"] == "jsclient" 那么
print("*** jsclient detected ***")
print("不返回任何东西")
- 返回true
否则
print("++其他客户端检测到++")。
返回错误
结束
结束
注意,-(两个破折号)在Lua中是一个注释。
在这种情况下,auth_on_publish钩子被使用webhooks调用。
奖金
用墨鱼生成配置时发生错误。
这可以通过将docker-compose.yml中的命令设置为进一步调试。
命令。"vernemq config generate -l debug /vernemq/etc/vernemq.conf.local"
并把容器带起来(注意,我已经创建了一个.local文件,所以某些设置不会再被覆盖了)。
我得到的错误信息是。
jalpine_morpheus | escript: 异常错误:没有匹配的函数条款
jalpine_morpheus | lists:unzip([[ws,ws],
jalpine_morpheus | {["log", "console", "file"], "./log/console.log"},
显然,这与墨鱼被只包含一个空格的线条噎住有关。
https://github.com/basho/cuttlefish/issues/222
迫切 Alt + P 在nano中会启用空白显示--对调试这个特殊问题很有帮助。
我的配置中的问题部分看起来是这样的。
这里有两个标签(?),它们应该是没有的。
删除有问题的一行,将允许VerneMQ再次启动。
进一步阅读
这可能也是有帮助的。
http://www.steves-internet-guide.com/mqtt-protocol-messages-overview/
VerneMQ的更新日志。
https://github.com/vernemq/vernemq/blob/fe514561cbeebb2ac4f7c98a87c64d766587c1d7/changelog.md
注意:在1.8版本中,一个有趣的新插件是vmq_pulse插件,它将通过HTTP(S)将集群信息推送到一个脉冲后端。
显示一些额外的Lua脚本,用于VerneMQ的多样性。