ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Mosquitto 的 IPv6 支持与实践:从 test.mosquitto.org 的 AAAA 记录说起

Mosquitto 的 IPv6 支持与实践:从 test.mosquitto.org 的 AAAA 记录说起 Mosquitto 的 IPv6 支持与实践从 test.mosquitto.org 的 AAAA 记录说起【免费下载链接】mosquittoEclipse Mosquitto - An open source MQTT broker项目地址: https://gitcode.com/gh_mirrors/mos/mosquitto本文以 2012 年官方博客《IPv6 on Test Server》为核心脉络围绕 Eclipse Mosquitto 公共测试服务器 test.mosquitto.org 开通 IPv6 访问这一事件展开讲解 DNS 记录与 IPv6 服务的关系、Mosquitto broker 与服务端库的 IPv6 实现原理并结合 mosquitto.conf 与源码给出可落地的 IPv6 客户端测试方案。读完本文你将理解 Mosquitto 双栈监听的底层机制并能独立完成 IPv6 环境下的 MQTT 连接测试。事件背景为 test.mosquitto.org 补上 IPv6 的 DNS 记录2012 年 1 月Mosquitto 项目上线了面向公众的测试服务器 test.mosquitto.org供 MQTT 开发者验证客户端实现与协议行为见公告博文。同年 6 月的这篇《IPv6 on Test Server》则披露了一个容易被忽视的细节公共测试服务器自上线起就在软件层面支持 IPv6但一直缺少对应的 DNS 记录这个缺口现在已修复待记录在全球传播完成后即可用它测试 IPv6 客户端。这里揭示了一个常见误区服务端支持 IPv6与可以通过 IPv6 域名访问是两回事。前者取决于监听套接字是否绑定 IPv6 地址族后者还额外依赖 DNS 中是否存在 AAAA 记录。只有 AAAA 记录IPv6 地址记录随 DNS 传播到位后客户端用test.mosquitto.org解析到的地址才会包含::开头的 IPv6 地址连接才能走上 IPv6 链路。为什么支持 IPv6还需要 AAAA 记录DNS 体系中同一主机名可以同时拥有两种记录A 记录映射 IPv4 地址如80.96.1.44AAAA 记录映射 IPv6 地址如2001:41d0:2:b6c::1。当服务端监听套接字已经具备 IPv6 能力时缺了 AAAA 记录客户端通过域名解析只会得到 IPv4 地址连接仍会走 IPv4 栈——这正是 test.mosquitto.org 早期支持 IPv6 却无法用 IPv6 访问的根因。2016 年项目进一步设立了独立主机名test6.mosquitto.org它指向与 test.mosquitto.org 相同的地址但只发布 AAAA 记录见test6.mosquitto.org 公告从而保证使用该主机名连接时一定走 IPv6便于开发者确认自己的客户端确实在使用 IPv6 协议栈。Mosquitto 的 IPv6 实现源码级解析监听器socket_domain 与双栈默认行为broker 端对 IPv6 的支持核心在 src/net.c 的net__socket_listen_tcp()。该函数通过getaddrinfo()解析监听地址关键逻辑如下若未显式配置地址族hints.ai_family取AF_UNSPEC由系统返回 IPv4/IPv6 全部可用地址broker 会为每个地址族分别创建监听套接字并打印Opening ipv4 listen socket on port X/Opening ipv6 listen socket on port X日志见 src/net.c若配置了socket_domain则hints.ai_family被固定为AF_INET或AF_INET6见 src/net.c。配置解析位于 src/conf.csocket_domain选项接受ipv4或ipv6两个取值分别将监听器的socket_domain字段置为AF_INET/AF_INET6。mosquitto.conf中对此有明确说明mosquitto.conf# By default, a listener will attempt to listen on all supported IP protocol # versions. ... # Set to ipv4 to force the listener to only use IPv4, or set to ipv6 to # force the listener to only use IPv6. If you want support for both IPv4 and # IPv6, then do not use the socket_domain option. #socket_domain也就是说默认配置下 Mosquitto 即原生双栈——不需要任何额外开关就能同时监听 IPv4 与 IPv6这也解释了 test.mosquitto.org上线即支持 IPv6的说法。双栈套接字细节IPV6_V6ONLY在 src/net.c 中每个 IPv6 监听套接字创建后会尝试设置IPV6_V6ONLY为 1#ifdef IPV6_V6ONLY ss_opt 1; (void)setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, (const void *)ss_opt, sizeof(ss_opt)); #endif该选项将 IPv6 套接字与 IPv4 映射地址如::ffff:1.2.3.4隔离使 broker 在双栈模式下为每个地址族维护独立套接字行为更可预期。代码注释也说明该设置失败无关紧要Unimportant if this fails因为对功能无致命影响。客户端连接AF_UNSPEC 自动尝试 IPv6IPv6 支持不仅存在于 broker 端Mosquitto 客户端库同样如此。lib/net_mosq.c 的net__try_connect_tcp()使用hints.ai_family AF_UNSPEC解析主机名遍历getaddrinfo()返回的地址链表为AF_INET填充sin_port、为AF_INET6填充sin6_port后依次尝试连接hints.ai_family AF_UNSPEC; hints.ai_socktype SOCK_STREAM; s getaddrinfo(host, NULL, hints, ainfo); ... for(rp ainfo; rp ! NULL; rp rp-ai_next){ *sock socket(rp-ai_family, rp-ai_socktype, rp-ai_protocol); ... if(rp-ai_family AF_INET){ ((struct sockaddr_in *)rp-ai_addr)-sin_port htons(port); }else if(rp-ai_family AF_INET6){ ((struct sockaddr_in6 *)rp-ai_addr)-sin6_port htons(port); }这意味着客户端侧无需任何 IPv6 专属配置只要目标主机解析出 AAAA 记录且网络可达mosquitto_pub、mosquitto_sub及基于 libmosquitto 的应用会自动尝试 IPv6 连接。这正是 test.mosquitto.org 补上 AAAA 记录后即可测试 IPv6 客户端的技术前提。实战用 IPv6 测试你的 MQTT 客户端连接公共测试服务器的 IPv6 地址DNS 传播完成后可直接用主机名测试客户端会自动解析并优先/尝试 IPv6# 订阅端 mosquitto_sub -h test.mosquitto.org -p 1883 -t test/topic -v # 发布端另开终端 mosquitto_pub -h test.mosquitto.org -p 1883 -t test/topic -m hello ipv6若想强制验证确实走了 IPv6使用只含 AAAA 记录的主机名mosquitto_sub -h test6.mosquitto.org -p 1883 -t test/topic -v mosquitto_pub -h test6.mosquitto.org -p 1883 -t test/topic -m definitely ipv6由于 test6.mosquitto.org 只发布 AAAA 记录连接成功即可确认 IPv6 链路全程可用失败则会提示解析/连接错误便于定位问题在 DNS、路由还是客户端实现。本机自建 IPv6 监听公共服务器之外也可在本地验证 broker 的 IPv6 能力。修改 mosquitto.conf# 仅 IPv6 监听注意 IPv6 地址在配置中的写法 listener 1883 ::1 # 或强制地址族 listener 1883 socket_domain ipv6启动后观察日志中的Opening ipv6 listen socket on port 1883再用mosquitto_pub连接::1回环 IPv6 地址即可mosquitto_pub -h ::1 -p 1883 -t test/topic -m loopback ipv6 mosquitto_sub -h ::1 -p 1883 -t test/topic -v注意 mosquitto.conf 的语法为listener port-number [ip address/host name/unix socket path]使用 IPv6 字面量时按上文方式书写即可broker 会通过getaddrinfo()正确解析。仓库中的 IPv6 测试佐证项目测试套件对 IPv6 地址族有直接覆盖可作为实现事实的旁证test/broker/21-proxy-v2-ipv6.py通过 PROXY 协议 v2 传入 IPv6 源地址2001:db8:506:708:900::1并断言 broker 日志输出New client connected from 2001:db8:506:708:900::1:6275 ...验证 broker 对 IPv6 地址的完整处理链路test/broker/21-proxy-v1-success.py 同样覆盖了 PROXY TCP6 场景上述用例已注册在 test/broker/CMakeLists.txt 与 test/broker/Makefile 中随常规测试运行。结合 src/net.c 中inet_ntop(AF_INET6, ...)的地址打印逻辑可以看到从监听、接收连接到日志输出的完整 IPv6 支持链路在源码中都有明确落点。小结这篇 2012 年的短公告背后实际串起了 IPv6 落地的三个层次DNS 层AAAA 记录决定域名能否解析出 IPv6 地址、broker 层src/net.c 默认双栈监听可用socket_domain强制单栈IPV6_V6ONLY保证地址族隔离、客户端层lib/net_mosq.c 通过AF_UNSPEC自动尝试 IPv6。对开发者而言最实用的结论是测试 IPv6 客户端时优先使用仅含 AAAA 记录的 test6.mosquitto.org以排除名义上 IPv6、实际走 IPv4的假阳性自建 broker 无需额外配置即支持 IPv6双栈默认开启若需强制或限制地址族使用socket_domain ipv4|ipv6配置说明见 mosquitto.conf。【免费下载链接】mosquittoEclipse Mosquitto - An open source MQTT broker项目地址: https://gitcode.com/gh_mirrors/mos/mosquitto创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表