ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

EMQX MQTT 连接器与集群链路服务器地址解析增强:IPv6 直连支持与 mqtt/mqtts URI Scheme

EMQX MQTT 连接器与集群链路服务器地址解析增强:IPv6 直连支持与 mqtt/mqtts URI Scheme 后端物联网消息队列通信【免费下载链接】emqxThe most scalable and reliable MQTT broker for AI, IoT, IIoT and connected vehicles项目地址https://gitcode.com/gh_mirrors/em/emqx点击查看免费下载导读本篇文章围绕 EMQX 开源仓库中的变更记录 changes/ee/fix-17859.en.md 展开系统讲解 EMQX 在 MQTT 连接器MQTT Connector与集群链路Cluster Link的server地址解析上的一次关键增强完整支持 IPv6 直连含带方括号的 IPv6 字面量以及官方 MQTT URI Schememqtt://明文 TCP 与mqtts://TLS。读完本文你将掌握如何正确书写可被 EMQX 接受的 broker 地址格式、哪些写法会触发bad_host_port与unsupported_scheme校验错误、IPv6-only broker 的连接原理以及底层地址解析器emqx_utils_uri与emqx_schema:parse_server的实现细节。一、变更背景修复前 MQTT 连接器无法连接 IPv6 broker 的两类失败在本次修复之前为 MQTT 连接器配置一个 IPv6 broker 会遇到两类互不相同的失败保存即失败配置校验阶段直接使用带方括号的 IPv6 字面量例如[::1]:1883在保存配置时会被服务器地址校验器以bad_host_port错误拒绝。原因是旧的地址解析逻辑对[]括起的 IPv6 写法缺乏识别能力无法把它解析为主机 端口。连接阶段失败运行时阶段如果填写的是一个只解析出 IPv6AAAA记录的主机名配置虽能保存但连接时默认走 IPv4 栈最终报 Could not resolve host无法解析主机错误。本次修复从两个层面解决了问题解析器层面服务器地址解析器现在接受带方括号的 IPv6 字面量例如[::1]、[::1]:1883、mqtt://[::1]:1883连接器层面MQTT 连接器建立连接时启用 IPv6 探测IPv6 probing使只提供 AAAA 记录的 IPv6-only broker 可以被成功连上。此外修复还顺带规范化了地址写法MQTT 连接器与集群链路的server地址现在接受官方 MQTT URI 的mqtt明文 TCP与mqttsTLS两种 scheme例如mqtt://broker:1883与mqtts://broker:8883不带 scheme 的host:port写法依然兼容而其他任何 scheme 都会以unsupported_scheme校验错误被拒绝。二、服务器地址格式从host:port到带 Scheme 与 IPv6 的标准写法2.1 官方 MQTT URI Scheme 定义本次修复在 apps/emqx/src/emqx_schema.erl 中集中定义了 MQTT broker 端点的解析选项mqtt_host_opts/0mqtt_host_opts() - #{ default_port 1883, default_scheme mqtt, supported_schemes [mqtt, mqtts] }.也就是说server字段现在支持三种等价写法写法示例说明无 schemebroker:1883兼容写法默认按mqtt明文 TCP处理端口缺省时使用 1883mqtt://mqtt://broker:1883官方明文 TCP schememqtts://mqtts://broker:8883官方 TLS scheme任何不在这份白名单内的 scheme如tcp://broker:1883、ssl://broker:8883都会被check_scheme/2以unsupported_scheme拒绝见 apps/emqx/src/emqx_schema.erlcheck_scheme(Str, Opts) - SupportedSchemes maps:get(supported_schemes, Opts, []), IsSupported lists:member(Str, SupportedSchemes), case IsSupported of true - Str; false - throw(unsupported_scheme) end.2.2 IPv6 字面量写法带方括号的 IPv6 字面量在所有上述写法中均可用端口写在右方括号之后[::1][::1]:1883mqtt://[::1]:1883mqtts://[::1]:88832.3 校验错误速查结合 apps/emqx/src/emqx_schema.erl 的解析逻辑常见的校验失败情形如下输入触发错误原因[::1]:1883修复前bad_host_port旧解析器不识别方括号 IPv6tcp://broker:1883unsupported_scheme非mqtt/mqtts的 scheme:1883expecting_hostname_but_got_a_number空主机名且带端口端口 65535port_number_too_large超出端口范围host:33x之类bad_host_port/bad_port_number冒号后不是合法端口从修复后的源码结构看bad_host_port仍然作为无法构成合法 host:port的兜底错误保留只是 IPv6 字面量不再落入该分支。三、底层实现URI 解析器如何识别带括号的 IPv63.1emqx_utils_uri宽松的 URI 解析器地址解析的核心是 apps/emqx_utils/src/emqx_utils_uri.erl。该模块实现了一个宽松的 URI 解析器其权威段authority正则对三种主机形态分别捕获emqx_utils_uri.erl-define(AUTHORITY_REGEX, (^(?userinfo.*)? (?:(?:\\[(?host_ipv6[a-z\\d\\.:]*)\\])|(?host_regular[^:]*?)|(?host_loose.*?)) (?port:\\d)?$) ).[host_ipv6]方括号包裹的类 IPv6地址解析出的主机类型为ipv6host_regular不含冒号的常规主机名host_loose含冒号但非法如host:33x留给上层做错误判定。解析结果中的host_type会区分ipv6 | regular | loose三种类型而格式化时 IPv6 地址会被重新包上方括号emqx_utils_uri.erlformat_host(ipv6, Host) - [$[, Host, $]]; format_host(_, Host) - Host.该模块内置的 EUnit 测试也覆盖了带 IPv6 字面量的 URL 往返emqx_utils_uri.erlhttp://[2001:0db8:85a3:0000:0000:8a2e:0370:7334]/${path}/to/page, http://[2001:0db8:85a3:0000:0000:8a2e:0370:7334]:4444/to/page,3.2emqx_schema:parse_serverscheme 与端口的裁决层上层 apps/emqx/src/emqx_schema.erl 的do_parse_server/2完成 scheme、主机、端口的组合校验先把输入交给emqx_utils_uri:parse/1对无 scheme 输入自动补//前缀使host:port也能走统一解析路径空 authority 直接抛bad_host_portloose类型含非法冒号抛bad_host_port或bad_port_number对 scheme 做白名单校验缺省 scheme 默认mqtt对端口做范围校验1~65535。emqx_schema中同步提供了servers_sc/2的校验入口server字段在配置加载时即完成上述解析apps/emqx/src/emqx_schema.erl这就是为什么非法地址会在保存/加载阶段就报错而不是等到连接阶段。四、MQTT 连接器从解析到 IPv6 直连4.1 连接器 Schema 与示例配置MQTT 连接器的配置骨架定义在 apps/emqx_bridge_mqtt/src/emqx_bridge_mqtt_connector_schema.erl。server字段通过emqx_schema:servers_sc(..., ?MQTT_HOST_OPTS)声明emqx_bridge_mqtt_connector_schema.erl并在运行时由parse_server/1解析为{Host, Port}元组emqx_bridge_mqtt_connector_schema.erl。一份连接 IPv6 broker 的典型 HOCON 配置示例connectors.mqtt.my_ipv6_bridge { server mqtt://[::1]:1883 # 也支持 [::1]:1883、mqtts://[::1]:8883 proto_ver v5 bridge_mode false clean_start true keepalive 160s connect_timeout 10s retry_interval 15s max_inflight 32 pool_size 8 ssl { enable false } resource_opts { health_check_interval 45s start_after_created true start_timeout 5s } }若使用 TLS只需把server换成mqtts://并把ssl.enable置为true。4.2 Scheme 与 SSL 的一致性检查连接器在启动时会对server的 scheme 与ssl.enable做一致性检查apps/emqx_bridge_mqtt/src/emqx_bridge_mqtt_connector.erl显式写了mqtts://但ssl.enable false直接报错提示要么开启 SSL要么改用mqtt://。这是为了防止明文客户端向 TLS 端口发 CONNECT随后把收到的 TLS alert 字节误当 MQTT 帧解析显式写了mqtt://但ssl.enable true仅告警仍以ssl.enable为准走 TLS兼容历史配置不带 scheme 的地址不参与该检查。对应的判断入口explicit_server_scheme/1实现于 apps/emqx_bridge_mqtt/src/emqx_bridge_mqtt_connector_schema.erl只有显式书写mqtt:///mqtts://的地址才表达是否使用 TLS的意图。4.3 IPv6 探测ipv6_probe连上 IPv6-only broker 的关键连接器构建emqtt客户端选项时会为 TCP 选项注入ipv6_probeapps/emqx_bridge_mqtt/src/emqx_bridge_mqtt_connector.erl%% ipv6_probe lets the client reach an IPv6-only broker (e.g. a host that %% only resolves to an AAAA record); without it the connect defaults to IPv4. TcpOpts emqx_utils:ipv6_probe( emqx_schema:client_tcp_opts_to_proplist(maps:get(tcp_opts, Config, #{})) ),emqx_utils:ipv6_probe/1的实现apps/emqx_utils/src/emqx_utils.erl会检测当前 OTP 是否导出gen_tcp:ipv6_probe/0EMQX 的 OTP fork 支持该能力支持则把{ipv6_probe, true}前置到 TCP 选项列表ipv6_probe(Opts) - case erlang:function_exported(gen_tcp, ipv6_probe, 0) of true - [{ipv6_probe, true} | Opts]; false - Opts end.启用该选项后连接建立会先尝试 IPv6AAAA 解析结果再回退 IPv4从而覆盖主机只解析出 AAAA 记录的 IPv6-only 场景此前默认走 IPv4 导致的 Could not resolve host 因此得到修复。4.4 测试验证连接器 Schema 的单元测试覆盖了本次变更的核心用例apps/emqx_bridge_mqtt/test/emqx_bridge_mqtt_schema_tests.erl127.0.0.1:1883无 scheme可接受mqtt://broker.example:1883可接受mqtt://127.0.0.1:1883可接受mqtts://broker.example:8883可接受mqtt://[::1]:1883IPv6 字面量可接受tcp://broker.example:1883非白名单 scheme抛出unsupported_scheme校验错误。五、集群链路Cluster Linkserver 地址同步升级集群链路Cluster Link的server地址同样采用emqx_schema:mqtt_host_opts()解析见 apps/emqx_cluster_link/src/emqx_cluster_link_schema.erl。链路客户端在构建emqtt选项时通过emqx_schema:parse_servers/2把可逗号分隔的地址列表解析为{Host, Port}列表按配置顺序作为hosts传入apps/emqx_cluster_link/src/emqx_cluster_link_config.erlmk_emqtt_options(#{server : Server, ssl : #{enable : EnableSsl} Ssl} LinkConf) - Hosts [ {Host, Port} || #{hostname : Host, port : Port} - emqx_schema:parse_servers(Server, ?MQTT_HOST_OPTS) ], ...因此集群链路的server同样支持[::1]:1883、mqtt://host:1883、mqtts://host:8883等写法并允许多地址host1:1883,host2:1883做故障转移hosts按配置顺序逐个尝试直到连接成功emqx_cluster_link_config.erl 还实现了第 N 个客户端优先用第 N 个地址的负载分散策略。六、与其他模块的一致性SSRF 检查与通用解析入口修复后的解析器同时保证了跨模块的一致性连接器资源在启动时会再次调用parse_mqtt_host/1apps/emqx_connector/src/emqx_connector_resource.erl解析出主机名用于 SSRF 检查emqx_utils_ssrf:check_host/1emqx_schema中明确注释所有解析 MQTT 端点的地方都必须使用mqtt_host_opts()否则会出现一处能解析、另一处被拒绝的不一致apps/emqx/src/emqx_schema.erl。这意味着从连接器、集群链路到依赖同一解析入口的其他 MQTT 客户端配置对mqtt:///mqtts://与 IPv6 字面量的支持是统一且可预期的。七、升级与兼容性说明向后兼容不带 scheme 的host:port写法继续有效已有配置无需修改更严格的 scheme 校验此前可能被容忍的非标准 scheme如tcp://现在会被明确拒绝升级前请检查现有连接器与集群链路配置中是否使用了非mqtt/mqtts的 schemeIPv6 场景要连接 IPv6 broker请使用带方括号的字面量如[::1]:1883或mqtt://[::1]:1883或使用只解析出 AAAA 记录的主机名——后者依赖ipv6_probe能力EMQX 的 OTP fork 提供gen_tcp:ipv6_probe/0错误提示保存配置时遇到bad_host_port请检查地址是否为合法的host[:port]IPv6 必须带方括号遇到unsupported_scheme请把 scheme 改为mqtt://或mqtts://或直接省略 scheme。参考文件索引变更记录changes/ee/fix-17859.en.md地址解析核心apps/emqx_utils/src/emqx_utils_uri.erlscheme/端口校验与mqtt_host_optsapps/emqx/src/emqx_schema.erlMQTT 连接器实现apps/emqx_bridge_mqtt/src/emqx_bridge_mqtt_connector.erl连接器 Schemaapps/emqx_bridge_mqtt/src/emqx_bridge_mqtt_connector_schema.erl连接器 Schema 测试apps/emqx_bridge_mqtt/test/emqx_bridge_mqtt_schema_tests.erl集群链路配置apps/emqx_cluster_link/src/emqx_cluster_link_config.erl连接器资源 SSRF 检查apps/emqx_connector/src/emqx_connector_resource.erl赞分享后端物联网消息队列通信【免费下载链接】emqxThe most scalable and reliable MQTT broker for AI, IoT, IIoT and connected vehicles项目地址https://gitcode.com/gh_mirrors/em/emqx点击查看免费下载相关推荐如何构建企业级mammoth.js配置管理系统从零到一的实战指南如何构建企业级mammoth.js配置管理系统从零到一的实战指南 mammoth.js是一个功能强大的Word文档.docx转HTML转换库它通过语义化后端物联网消息队列通信EMQX MQTT 连接器地址 Scheme 与 SSL 配置一致性校验告别晦涩内部错误获得清晰故障提示EMQX MQTT 连接器地址 Scheme 与 SSL 配置一致性校验告别晦涩内部错误获得清晰故障提示 导读 本篇文章围绕 EMQX 开源仓库中 MQTT后端物联网消息队列通信EMQX 升级 MQTT 客户端库 emqtt 至 1.13.8桥接重连与 TLS 断连处理增强解析EMQX 升级 MQTT 客户端库 emqtt 至 1.13.8桥接重连与 TLS 断连处理增强解析 EMQX 在 6.x 版本周期中将 MQTT 桥接M后端物联网消息队列通信上一篇3分钟上手Umi-OCR免费开源的离线文字识别神器保护你的隐私安全下一篇从零开始Kimi K2开源大模型本地部署完全指南打造你的专属AI智能体创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表