FEATURED · 精选文章

LoRaWAN数据包分析实战:从空口抓包到Wireshark解密与故障排查

发布时间 / 2026/9/15 19:06:24
来源 / 创域科博编辑部
栏目 / 资讯中心
LoRaWAN数据包分析实战:从空口抓包到Wireshark解密与故障排查 很多人第一次接触LoRaWAN数据包分析这个事儿都是被逼的。设备明明发上来了数据后台却收不到或者后台显示入网成功了设备端却一直在重试。你去翻厂商文档永远写着“检查信号强度”“确认网关在线”等于没说。我自己做LoRaWAN网关和节点调试这几年最大的感受就是不亲自看一眼空口上跑的原始数据包排查问题永远都是在猜。LoRaWAN数据包分析工具说白了就是给LoRaWAN网络做“抓包体检”的一套方法组合。它既能抓空口的无线帧也能在服务器侧解出应用负载然后告诉你每一帧从哪来、到哪去、加密没加密、MIC对不对、帧计数连续不连续。这篇文章我会把我实际用过的抓包方案、Wireshark解密链路、密钥派生逻辑、还有三个真实的排查案例一起整理出来希望能给正在做节点开发、网关运维或者LoRaWAN入门的朋友一条能直接落地的路子。1. 为什么必须亲手抓一次LoRaWAN数据包先理解这个工具的定位1.1 LoRaWAN数据包分析工具到底能做什么先给个明确的功能画像。一套完整的LoRaWAN数据包分析方案通常包含四个能力空口抓取把设备发出的无线帧PHYPayload截获下来看到的是最原始的16进制字节流包含前导码、物理头、MAC层内容。协议解析把原始字节按LoRaWAN规范拆成结构字段比如MType消息类型、DevAddr设备短地址、FCnt帧计数、FPort、MIC、payload等。解密与解包结合设备会话密钥AppSKey/NwkSKey或者直接用根密钥AppKey/NwkKey派生出会话密钥把AES-128加密的FRMPayload还原成明文。统计与对比计算RSSI、SNR、Airtime占用空中时间、到达率、丢包率定位是无线质量问题还是协议问题。市面上常见的载体有两种一种是大而全的协议分析软件比如Wireshark加上LoRaWAN解析插件配合抓包硬件做离线分析另一种是网络服务器自带的调试界面比如ChirpStack的设备日志、TTN的MQTT数据流它们能让你看到“后台收到了什么”但看不到“空口上到底发生了什么”。1.2 什么时候你会被逼到非抓包不可我整理了几个高频场景基本覆盖了LoRaWAN调试中80%的痛点入网反复失败设备发Join Request服务器收不到服务器下发了Join Accept设备端却提示入网超时。这种情况只看服务器日志往往一头雾水。上行数据丢失传感器上报间隔明明很正常后台却经常丢点而且丢包没有规律。下行命令石沉大海App下发开关指令设备没有执行。越是有ADR自动速率调整这种问题越隐蔽。payload全是乱码后台显示收到数据了但Base64解出来根本不是你发的那个格式。先别怀疑节点代码多半是会话密钥没配对。MIC校验持续报错FCnt不连续、密钥不匹配、跨了不同运营商平台迁移任何一个都可能让MIC校验失败。1.3 三种视图的对比空口抓包能多看到什么我把后台面板、服务器日志和空口抓包放到一张表里对比差异一目了然观察维度平台控制台服务器/NS日志空口抓包无线信号质量RSSI/SNR部分平台有取决于网关上报全部可见空口原始字节不可见不可见完整可见设备重传行为看不到部分网关会记录清晰可见Join交互过程只看到结果只看到处理结果Request和Accept都能看到实际下行窗口只看到NS发出只看到NS发出能看到节点是否真的收到帧计数与MIC验证后台可能报错但不给原因有日志但要翻直接显示校验状态平台控制台告诉你“发生了什么”后台日志告诉你“服务器怎么想的”空口抓包告诉你“设备实际做了什么”。2. LoRaWAN帧结构拆解看懂空口字节才好谈分析2.1 PHYPayload的骨架MHDR、MACPayload与MICLoRaWAN的空中帧结构看起来复杂其实骨架非常清晰。每一帧都可以抽象为PHYPayload MHDR MACPayload MICMHDR1字节消息头高3位表示MType低2位表示Major版本。MType决定了这条消息是Join Request0、Join Accept1、Unconfirmed数据上/下行2/3还是Confirmed数据上/下行4/5。MACPayload真正的消息内容。不同消息类型内部结构不一样。MIC4字节消息完整性校验码相当于数据包的数字签名。它由AES-128算法对整帧内容计算得出密钥不对或者内容被篡改MIC立刻就会被Wireshark标记为invalid。我调试时习惯在Wireshark里先看MType再看MIC状态。MType告诉你“这是一条什么包”MIC状态告诉你“这条包是否被合法设备发出”。这两步能过滤掉大量无效线索。2.2 三种核心消息格式Join Request、Join Accept与数据帧Join流程是LoRaWAN设备入网的第一关也是最值得抓包分析的地方。Join Request的MACPayload结构很固定就三个字段AppEUI8字节DevEUI8字节DevNonce2字节设备随机数这条消息用根密钥计算MIC不携带应用数据。如果一个节点反复发Join Request说明它一直没有收到Join Accept或者在等待接收窗口超时后重新入网。Join Accept的MACPayload包括AppNonce3字节服务器随机数NetID3字节DevAddr4字节服务器分配的短地址DLSettings1字节含RX1/RX2速率偏移等RXDelay1字节CFList可选的频率列表0或16字节这条消息整个是用根密钥做AES-128加密的所以你在Wireshark里不导入根密钥看到的就是一团密文。数据帧Unconfirmed Data Up等的MACPayload又分成两部分MACPayload FHDR FPort FRMPayloadFHDR里包含DevAddr4字节、FCtrl1字节、FCnt2字节、FOpts0-15字节通常用来携带MAC命令。FPort用于区分是应用数据通常用1以上还是MAC命令固定用0。FRMPayload就是真正的负载不过会用AppSKey加密如果是FPort0的MAC命令则用NwkSKey加密。2.3 密钥派生链路从AppKey/NwkKey到NwkSKey/AppSKey这一步是解密分析的核心。LoRaWAN的密钥体系可以理解为“晚上回家进门的两把钥匙”根密钥是“备用钥匙”LoRaWAN 1.0.x叫AppKey1.1开始拆成NwkKey和AppKey。它在OTAA入网时用用来加密Join Accept、计算Join Request的MIC同时负责派生后续的会话密钥。会话密钥是“日常钥匙”入网成功后就换成NwkSKey和AppSKey。NwkSKey负责MAC层完整性和网络层加密也就是FPort0的MAC命令AppSKey负责应用数据的加解密。密钥派生公式1.0.x大致是这样NwkSKey aes128_encrypt(AppKey, 0x01 | AppNonce | NetID | DevNonce | pad16) AppSKey aes128_encrypt(AppKey, 0x02 | AppNonce | NetID | DevNonce | pad16)pad16是补零到16字节的填充。这就是为什么Wireshark里只要配置了AppKey/NwkKey它就能自动跟完整个入网过程然后推算出NwkSKey和AppSKey一路上把后面的数据帧也解了。理解了这条派生链你就知道为什么很多抓包教程都让你优先去拿根密钥而不是会话密钥——拿到根密钥就相当于拿到了一整段会话的解密能力。3. 抓包环境搭建三条路线以及它们的边界3.1 路线一SX1301网关做空中监听LoRaWAN数据包分析最“正统”的办法是用一台标准的SX1301网关改造成空中监听器。SX1301是Semtech的LoRa基带芯片市面上大多数八通道LoRaWAN网关都在用它。抓包思路很简单把网关收到的无线帧全部转发出来。具体做法是Linux环境下跑Semtech的packet forwarder包转发器修改global_conf.json里的server地址把UDP 1680端口的数据导到本机再用Wireshark或tshark去监听这个端口。不过这里有几个坑要提醒你不是所有网关都能全频段监听。SX1301虽然标称八通道但实际监听时你只能让它监听配置里的那8个频率点。如果设备跳频到别的频点你就漏了。下行窗口要单独考虑。LoRaWAN节点通常先在上行频点接收RX1窗口是在上行频率加偏移RX2窗口是固定频点比如868.1MHz或923.3MHz。监听下行时我习惯把抓包器锁定在RX2频点因为绝大多数网络的下行都走RX2抓到完整下行帧的概率最大。抓包网关不要和数据网关共用。如果同一台网关既做业务转发又做监听日志会混在一起很难分辨。有条件就单独拿一台网关当分析仪。3.2 路线二板载RFM95嗅探器适合单信道小范围如果你只是在家里调试一个设备没必要搬一台八通道网关。用一块支持LoRa的射频模块比如RFM95、SX1276搭配Arduino或树莓派就可以做成简易嗅探器。代码方面可以参考一些开源项目做单信道抓包。单信道嗅探器一次只能锁定一个频率所以你需要提前知道设备的工作频率比如868MHz或915MHz再设置对应的扩频因子。这条路线我强烈建议只用于近距离、固定频点、固定SF的调试场景。设备只要做了ADR自适应速率调整或者网关侧配置了跳频单信道嗅探器基本就废了。但它的好处是便宜、便携、能快速验证“节点是不是真的在发”。3.3 路线三服务器日志与MQTT订阅非空口视角的“软抓包”严格来说这不是抓包但它是很多人忽略的一个高效入口。ChirpStack和TTN这类网络服务器都提供了详细的上下行日志并且支持通过MQTT订阅设备事件。以ChirpStack为例它会在MQTT主题application/{applicationID}/device/{devEUI}/event/up上推送上行事件的JSON里面包含了phy_payload的Base64、RSSI、SNR、数据速率、网关信息等。拿到这些数据你可以写个简单的脚本解析把repeated包过滤掉按时间线还原设备的完整上报轨迹。TTN v3也有类似能力它提供ttn-lw-cli命令行工具可以直接查询设备的session keys和上下行事件。这个方法能看到NS最终收到的内容适合排查“服务器是否成功处理了帧”但看不到“空口上设备到底发了什么”所以它必须跟空口抓包互补。3.4 三种方案的选型取舍方案成本抓取范围适合场景局限SX1301网关监听较高8通道多频点现场问题定位、入网排查配置复杂下行频点需注意RFM95单信道嗅探器低单频点单SF桌面调试、小范围验证无法跟踪ADR跳频服务器日志/MQTT基本为零NS可见的数据日常监控、云端确认看不到空口真实情况我的建议是办公桌上放一台单信道嗅探器做快速验证现场带一台SX1301网关做完整抓包分析日常运维再配合服务器日志形成“云端空口”的双视角闭环。4. Wireshark解密实操从乱码字节到可读数据的完整链路4.1 解密前的密钥准备去哪个环节拿钥匙Wireshark本身只是工具你不给它正确的密钥它给你看的就是一堆加密后的十六进制。所以在开始解密前必须先拿到设备的密钥。分两种情况OTAA设备优先拿根密钥也就是AppKeyLoRaWAN 1.0.x或NwkKey/AppKeyLoRaWAN 1.1。这个密钥通常在设备烧录脚本里、网络服务器的设备配置里或者产品出厂清单里。ABP设备没有入网过程直接拿NwkSKey和AppSKey。这类设备短地址DevAddr是固定的没有Join流程所以Wireshark没办法自动派生密钥你必须手动填两把会话密钥。从ChirpStack拿OTAA密钥很简单设备配置界面就能看到root_keys字段从TTN v3拿也方便ttn-lw-cli devices get加上对应参数把session keys导出来即可。4.2 在Wireshark里配置解密密钥以Wireshark 4.x为例进入Preferences - Protocols - LoRaWAN在解密区域填入密钥。格式基本是DevAddr:密钥十六进制字符串例如260B1F3C:2B7E151628AED2A6ABF7158809CF4F3C你还可以通过下拉列表指定密钥类型可选AppSKey、NwkSKey、AppKey或NwkKey。这里有一个非常容易踩的坑如果你把AppKey当AppSKey填Wireshark虽然能认出字段但不会用它去自动派生后续会话密钥结果就是Join Accept照样解不开后面数据帧也是一堆-密文。正确的做法是如果你有根密钥就填根密钥并选择对应的AppKey/NwkKey类型让Wireshark自动跑完Join流程并派生会话密钥如果你只有会话密钥那就手动填AppSKey和NwkSKey两种类型。TTN v3用户尤其要注意TTN v3默认采用LoRaWAN 1.0.x兼容模式时它把根密钥称为NwkKey很多教程里会看到“TTN v3设备要用NwkKey而不是AppKey”的说法。实际填的时候在Wireshark里选择NwkKey类型去尝试解密Join Accept大概率能解开。4.3 Join Request/Join Accept的完整分析示范假如你已经抓到了一组完整的空口包我推荐按下面这个顺序看先过滤出Join RequestWireshark显示过滤器用lorawan.mtype 0。双击一条Join Request展开LoRaWAN协议树看DevEUI、AppEUI、DevNonce。如果能看到这些字段说明物理层解析正常。再过滤Join Acceptlorawan.mtype 1。如果配置了根密钥Wireshark会自动展开明文内容你能直接看到服务器分配的DevAddr、DLSettings、RXDelay。看整个时序用时间列观察Join Request发出和Join Accept返回之间的间隔这个间隔是否落在节点的接收窗口里。一次正常的OTAA入网时间线上应该出现Request然后间隔约1-5秒出现Accept最后设备立刻在Accept里的DevAddr下发第一条数据帧。如果只看到Request没有Accept问题基本可以锁定在“服务器没收到”或“服务器回了但节点没听到”如果看到Accept但后续没有数据帧那重点去查设备端是否正确保存了DevAddr和会话密钥。4.4 上下行数据帧的过滤与统计技巧解密成功后最常用的过滤表达式我整理在这# 只看设备上行数据 lorawan.mtype 2 # 只看服务器下发 lorawan.mtype 3 || lorawan.mtype 5 # 看某个设备的所有帧DevAddr替换成实际值 lorawan.devid 0x260B1F3C # 看MAC命令FPort0 lorawan.fport 0 # 找MIC校验失败的帧 lorawan.mic_status 0mic_status是Wireshark自动帮我们检查的一个字段非常实用。如果一帧数据在分析工具里标记MIC invalid说明密钥不匹配或帧内容被修改这种帧就算解出明文也不能轻信。统计方面我经常用Wireshark的Statistics - Flow Graph看完整会话时序再用Telephony - LORA如果版本支持看RSSI分布。不支持的版本就直接导出CSV用Excel或者Python画个时间-信号强度散点图很容易发现下行空窗和丢包的位置。5. 三个排查实录我是怎么用这些工具定位问题的5.1 入网失败Join Request发了服务器就是不理去年我一个项目里现场部署了30多台温湿度传感器其中一台上电之后始终无法入网而且没有任何规律时好时坏。后台显示网关在线其他设备都正常只有这一台反复重试。我用SX1301网关做了空中监听抓到的现象很有意思这台设备确实在疯狂发Join Request频率大概每30秒一次RSSI从-50到-110都出现过SNR也正常。但是服务器侧却一个Request都没收到。问题出在哪我把抓到的PHYPayload拿去对比了一下发现它的AppEUI和我配置在服务器上的AppEUI不一样。设备端固件默认烧了一个通用AppEUI服务器端却配置成了另一个。这导致服务器端看到AppEUI不匹配直接丢弃设备不知道自己发得对不对只能无限重试。这事的教训是设备发不出去和服务器不认账在空口抓包上看起来一模一样但分析工具能帮你区分“有没有信号”和“协议对不对”。没有空口数据我可能还在调天线方向。5.2 FCnt乱跳导致的MIC校验失败另一个案例是某个客户反馈设备上线后每两分钟上报一次温湿度但后台只偶尔收到一条而且间隔完全对不上。平台面板报错信息是“MIC mismatch”。我用服务器日志先做了过滤发现后台确实源源不断在收包但大部分包在入站网关之后就被ChirpStack扔掉了日志里有MIC mismatch字样。继续翻节点日志发现设备用的是ABP方式入网而它的FCnt在每次重启之后会重置成0。LoRaWAN协议要求FCnt必须单调递增服务器会拒收明显小于上次计数的消息。ABP设备重启后FCnt归零正好踩到服务器这层保护机制上。修复方案不复杂要么在服务器里允许FCnt重置要么在节点端把FCnt保存到flash重启后接着上次的值继续发。我后来查了一下市面很多便宜ABP模组默认是不保存FCnt的这个坑在量产阶段特别容易爆发建议做ABP产品的朋友提早预防。5.3 下行命令丢失ADR把灵敏度调“没”了第三个案例比较隐蔽。设备在实验室里一切正常部署到现场后App侧下发“关阀”指令设备偶尔能执行偶尔延迟很久才执行。从后台看服务器确实发了下行帧没有报错从设备日志看设备压根没收到。空口抓包派上了大用场。我分别抓了RX1和RX2窗口的数据发现RX1窗口里根本没有下行帧服务器实际上是在RX2窗口才发出去的。但RX2这个频点距离设备有点远RSSI很弱设备自然收不到。再深挖原因是ADR起了反作用。节点在上行信号好的时候被ADR逐步拉高了速率也就是把扩频因子调小灵敏度随之下降。上行没问题但下行的信噪比余量不足于是数据开始丢。解决思路是两个方向一是调整DLSettings让RX1窗口覆盖更合适的频率偏移二是关闭某些场景的ADR在链路余量不足时固定用较低速率。空口抓包让我第一次直观地看到“服务器以为发了不等于设备真的收到了”这个事实。6. 顺手沉淀的调试脚本和过滤表达式6.1 tshark命令行快速解析有些情况下你抓包设备在一台没有图形界面的服务器上没法打开Wireshark主界面。这时候tshark就派上用场了比如# 列出所有LoRaWAN数据帧的基本信息 tshark -r capture.pcapng -Y lorawan -T fields \ -e frame.number -e frame.time -e lorawan.devid -e lorawan.mtype -e lorawan.fcnt -e lorawan.payload如果只想看某个设备的帧加一个显示过滤器tshark -r capture.pcapng -Y lorawan.devid 0x260B1F3C -T fields \ -e frame.number -e frame.time -e lorawan.mtype -e lorawan.fcnt注意字段名在不同Wireshark版本里可能略有差异我建议先用tshark -G fields | grep lorawan看当前版本支持的字段名。6.2 常用过滤表达式清单有些过滤条件我几乎每次排查都会用到统一汇总在这里找ACK重传lorawan.mtype 4Confirmed Data Up一般会伴随重传。找下行lorawan.mtype 3 || lorawan.mtype 5。找MAC命令lorawan.fport 0。找帧计数异常可以把帧计数导出来用脚本检查跳变。找解密失败的帧没有直接的decrypt_failed字段但可以通过lorawan.payload字段里全是密文且MIC状态异常来辅助判断。6.3 别忘了算Airtime最后提醒一个所有LoRaWAN人都会遇到的问题Airtime。LoRaWAN是半双工且受占空比限制的协议Airtime直接关系到设备上报频率的合法性也和ADR策略、丢包率强相关。一个12字节的payload在常见配置SF7、125kHz带宽下总Airtime大约是多少我们可以算一下符号时间2^7 / 125000 ≈ 1.024毫秒preamble部分约12.544毫秒payload部分28个符号约28.672毫秒整包Airtime大约是41毫秒换成SF12之后Airtime会暴涨到几百毫秒甚至更多。所以当你看到某个设备丢包率异常时别急着怀疑硬件先算算它是不是已经逼近占空比红线了。数据包分析工具里的帧时间戳就是帮你看这个问题的。把相邻两帧时间间隔拉出来排序低于规定占空比间隔的那些点基本就是要排查的嫌疑对象。我个人在项目收尾前一定会做一轮“全量帧回放”用tshark把pcap里的所有帧按时间排序再用脚本算出每秒钟的并发数、每台设备的平均发送间隔看看有没有节点在物理层上互相踩踏。这个习惯帮我提前规避过好几次同频干扰导致的上报率下降问题算是抓包之外的一个附加价值。
RELATED — 相关阅读

相关资讯

LATEST — 最新资讯

最新发布

TODAY — 本日精选

新闻

WEEKLY — 本周精选

新闻

MONTHLY — 本月精选

新闻