本知识地图由AI根据大纲编写
一边改一边学~~
实验边界:本文所有攻防实验只用于自己拥有或明确获授权的设备、网络与本地 SITL/虚拟靶场。涉及消息伪造、任务替换、口令强度验证等内容时,默认目标一律是
127.0.0.1、本机虚拟机或自己搭建的测试 AP。不要把命令直接换成陌生公网 IP、他人 Wi-Fi、真实飞行中的无人机或未经授权的遥控/数传链路。
0. 先看这里:最终要练成什么能力?
学完这套路线,你不应该只是“记住几个命令”,而应该能回答下面这些问题:
- 一条“起飞”命令,从地面站发出后,经过哪些模块,最后怎样变成电机转速?
- MAVLink 一帧数据里,谁表示发送者、谁表示消息类型、谁负责完整性?
- 为什么“能收到合法格式的 MAVLink”不等于“这个发送者可信”?
- GPS、IMU、气压计等数据是怎样进入 EKF/状态估计器,再进入控制器的?
- ROS / MAVROS 在无人机系统中扮演什么角色?攻击面为什么会突然变大?
- 怎样在 Wireshark 里从一堆 UDP 流量中认出 MAVLink?
- 怎样用 Pymavlink 只写几十行 Python 就完成监听、解析、统计和异常检测?
- 怎样在 本地 SITL 中复现实验:消息伪造、未经授权的命令、任务替换、状态异常?
- 如何设计检测:白名单、签名、频率检测、来源约束、状态机一致性、传感器交叉验证?
- 面对一个未知二进制协议,如何从“十六进制乱码”一步步推出帧头、长度、计数器、命令字和 CRC?
eg.如果这些问题我觉得对理解基础无人机架构挺重要的,可以简单看看想想。
一、推荐顺序
按下面的顺序推进:
阶段 A:能把无人机跑起来
1.1 构成
1.2 PX4 / ArduPilot
1.6 SITL 仿真环境
阶段 B:能看懂它在说什么
1.3 MAVLink(一)
1.4 MAVLink(二)
Pymavlink 入门
阶段 C:能看懂它和 ROS 怎么连
1.5 ROS → MAVROS
阶段 D:建立安全视角
1.7 常见漏洞
2.2 端口侦察
2.3 数据嗅探 / 指纹 / 分析
2.1 Wi-Fi 安全审计
阶段 E:进入 MAVLink 安全研究
MAVLink 安全总述(一)(二)
传感器型消息欺骗
状态型消息欺骗
阶段 F:受控注入与任务完整性实验
注入基础(一)(二)
起飞与飞行条件分析
航线篡改 / 任务替换
阶段 G:组件攻击面
Wi-Fi 服务
ROS 服务
阶段 H:未知协议分析
AI 辅助逆向实体无人机通信协议
二、统一实验室:一次搭好,后面一直用
推荐环境
eg.其实这里的环境我没有安装,因为我去看了一下github项目里面,这个PX4从无人机开发者从业者角度,我们只要了解一下大致原理就可以,主要以无人机攻防为主,在学习基础知识的同时可以移步今天发的另一篇文章,那个是以无人机安全为主的,在学基础知识的同时把那篇的无人机攻防环境搭建起来
搭建无人机的环境和了解其架构不是我们的主线任务,应该是怎么去攻击
主线:
Ubuntu 24.04 LTS
├── Git / build-essential
├── PX4-Autopilot
├── Gazebo
├── QGroundControl(可选但强烈推荐)
├── Python 3 + venv
├── pymavlink
├── Wireshark / tshark / tcpdump
├── nmap
├── ROS 2 Jazzy
└── MAVROS
为什么这样选?
- PX4 官方当前支持在 Ubuntu 22.04/24.04 上运行现代 Gazebo;
- ROS 2 Jazzy 的官方 Ubuntu 二进制包对应 Ubuntu 24.04;
- SITL 允许你把“危险动作”关在软件模拟器里;
- Pymavlink、Wireshark、ROS 2 正好覆盖协议、网络、机器人三条线。
系统基础工具
sudo apt update
sudo apt install -y \
git curl wget vim tmux htop jq \
build-essential python3 python3-pip python3-venv \
wireshark tshark tcpdump nmap net-tools iproute2 aircrack-ng
查看版本:
python3 --version
git --version
nmap --version
tshark --version
建议建立专用目录
mkdir -p ~/uav-sec-lab/{code,pcap,notes,missions,logs}
cd ~/uav-sec-lab
以后所有实验结果都放这里。
安装 PX4 与 SITL
cd ~
git clone https://github.com/PX4/PX4-Autopilot.git --recursive
bash ./PX4-Autopilot/Tools/setup/ubuntu.sh
安装结束后重新打开终端,然后:
cd ~/PX4-Autopilot
make px4_sitl gz_x500
你应该看到 Gazebo 中出现一架 x500 多旋翼。
不开 3D 场景的轻量测试
cd ~/PX4-Autopilot
make px4_sitl
PX4 Shell 中第一批必须会的命令
help
commander status
mavlink status
uorb top
listener vehicle_status
listener vehicle_attitude
listener vehicle_global_position
param show SYS_AUTOSTART
把 uorb top 想成 PX4 内部世界的“任务管理器 + 消息流监视器”。
安装 Pymavlink(这个是要装的,后面攻防会用到)
python3 -m venv ~/uav-sec-lab/.venv
source ~/uav-sec-lab/.venv/bin/activate
python -m pip install -U pip
pip install pymavlink
验证:
python - <<'PY'
from pymavlink import mavutil
print('pymavlink import OK')
print('dialect:', mavutil.mavlink.WIRE_PROTOCOL_VERSION)
PY
每次开实验终端先:
source ~/uav-sec-lab/.venv/bin/activate
安装 ROS 2 Jazzy
ROS 官方推荐 Ubuntu 24.04 使用 Jazzy 的 deb 包。安装仓库步骤可能随时间变化,因此如果以下仓库初始化失败,优先参考 ROS 2 官方 Jazzy 安装页。
完成 ROS 2 仓库初始化后,核心安装命令是:
sudo apt update
sudo apt install -y ros-jazzy-desktop ros-dev-tools
配置:
echo 'source /opt/ros/jazzy/setup.bash' >> ~/.bashrc
source /opt/ros/jazzy/setup.bash
验证:
终端 A:
ros2 run demo_nodes_cpp talker
终端 B:
ros2 run demo_nodes_py listener
能看到 Hello World 连续出现即通过。
eg.这边要能成功监听到需要确定同源source
# 查看ROS2发行版本
cici@9ue33pro:/tools$ echo $ROS_DISTRO
jazzy
#两个终端都配置source
cici@9ue33pro:/tools$ source /opt/ros/jazzy/setup.bash
安装 MAVROS
sudo apt update
sudo apt install -y ros-jazzy-mavros ros-jazzy-mavros-extras
安装 GeographicLib 数据:
ros2 run mavros install_geographiclib_datasets.sh
如果这个命令在你的发行包里发生变化:
ros2 pkg executables mavros | grep -i geographic
先查实际可执行文件。
第一章 无人机基础知识
1.1 无人机的构成:从开发者视角 DIY 一台无人机
如果这一节没真正理解,后面 MAVLink、欺骗、注入很容易变成“背命令”。
硬件层
一架典型开发型无人机可拆成:
Ground Control Station
QGroundControl
|
MAVLink
|
-------------------------------------------------
| |
Flight Controller 飞控主板 Companion Computer
PX4 / ArduPilot Linux / ROS / AI
| |
| uORB / Control | ROS2
| |
IMU / GPS / Baro -------------------------- camera / lidar
|
Mixer / Allocator
|
ESC 电子调速器
|
Motors
ROS作为无人机上层控制核心,其无认证、无授权、明文通信的设计缺陷,是攻击者突破无人机系统的关键入口。结合MAVROS的桥梁作用,攻击者可通过节点劫持、话题注入、服务伪造等方式,篡改无人机控制指令、窃取敏感数据、破坏飞行任务。
Flight Controller:飞控主板;
IMU:加速度计 + 陀螺仪;
Magnetometer:磁力计;
Barometer:气压计;
GNSS/GPS:位置与时间;
ESC:电子调速器;
Motor + Propeller;
RC Link:遥控链路;
Telemetry Link:数传;
Companion Computer:树莓派、Jetson、x86 等;
Payload:摄像头、雷达、云台。

软件层
传感器采样
↓
状态估计 EKF
↓
位置 / 速度 / 姿态状态
↓
飞行模式 / 导航器
↓
控制器
↓
控制分配
↓
执行器输出
安全研究中,你以后永远在问:
“我现在看到的数据,在这条链的哪一层?”
通信层

1.2 飞控介绍:APM / ArduPilot 和 PX4
APM 更准确地说是 ArduPilot 生态历史中的名称;主要比较 ArduPilot 与 PX4。
简单区别一下
| 维度 | PX4 | ArduPilot |
|---|---|---|
| 典型定位 | 模块化、开发/研究生态强 | 功能成熟、机型覆盖极广 |
| 内部消息机制 | uORB | AP_* 模块/库体系 |
| 常见 GCS | QGroundControl | Mission Planner / MAVProxy / QGC |
| 仿真 | PX4 SITL | ArduPilot SITL |
| 协议 | MAVLink | MAVLink |
安全研究最大的好处是:
两个完全不同的飞控都使用 MAVLink,因此可以区分“协议层问题”和“某一个飞控实现问题”。
PX4 必懂模块
commander → 状态机、arm/disarm、failsafe
navigator → Mission / RTL / navigation
mavlink → MAVLink 通信
EKF2 → 状态估计
mc_pos_control → 多旋翼位置控制
mc_att_control → 多旋翼姿态控制
实验:
mavlink status
commander status
listener vehicle_status
listener estimator_status
ArduPilot SITL 对照实验
安装 ArduPilot 的完整依赖过程较长,完成官方 Linux build environment 后可运行:
cd ~/ardupilot
./Tools/autotest/sim_vehicle.py -v ArduCopter --console --map -w
或在 ArduCopter 目录:
sim_vehicle.py --console --map -w
-w 用来在第一次实验时清掉虚拟 EEPROM 参数,恢复默认参数。
MAVProxy 里观察
status
mode
param show ARMING_CHECK
1.3 MAVLink 详解(一):数据帧与消息模型
一句话理解
MAVLink 不是“无人机遥控协议”这么简单,它更像无人机系统里的:
一套带大量标准消息定义的轻量级二进制消息总线协议。
MAVLink协议版本与格式
MAVLink有两个主流版本:V1.0(明文无签名) 、V2.0(可选消息签名)。
- V1.0帧格式 :STX(0XFE)→LEN→SEQ→SYSid→COMid→MSGid→payload→CRC,无签名、明文传输、无完整性校验。
- V2.0帧格式 :STX(0XFD)→LEN→INC_FLAGS→CMP_FLAGS→SEQ→SYSid→COMid→MSGid→payload→CRC→SIGNATURE(可选),新增消息签名、向后兼容功能,但默认关闭签名,易降级至V1.0。
MAVLink核心安全缺陷
- 身份认证缺失 :V1.0无任何认证机制;V2.0签名默认关闭,开启后也存在密钥管理漏洞、签名绕过风险。
- 数据明文传输:即使开启V2.0签名,payload数据仍明文传输,攻击者可直接读取飞行状态、位置、电量等敏感数据。
- 消息易伪造/重放:无随机数、时间戳防重放机制,攻击者嗅探合法消息后,可直接重放或篡改部分字段后发送,飞控无法识别。
- 协议降级风险:V2.0设备为兼容V1.0,可被强制降级至V1.0,导致签名机制失效,安全防护归零。
- MAVLink 1 / MAVLink 2;
- Frame;
- Message;
- Dialect;
- System ID;
- Component ID;
- Message ID;
- Sequence;
- Payload;
- CRC;
- MAVLink 2 Signing。
MAVLink 2 可以粗略看成:
STX
LEN
INCOMPAT FLAGS
COMPAT FLAGS
SEQ
SYSID
COMPID
MSGID (3 bytes)
PAYLOAD
CHECKSUM
SIGNATURE (optional)
注意:CRC 不是身份认证。
CRC 能帮助发现传输错误,但不能证明“这条消息一定来自可信地面站”。
eg.这里听起来很有用的样子,能不能利用呢???
高频消息
先熟悉这些:(eg.可以多背背,取证里面肯定有相关的,比如流量、固件逆向、存储)
HEARTBEAT
SYS_STATUS
ATTITUDE
GLOBAL_POSITION_INT
GPS_RAW_INT
LOCAL_POSITION_NED
COMMAND_LONG
COMMAND_ACK
MISSION_COUNT
MISSION_ITEM_INT
MISSION_REQUEST_INT
MISSION_ACK
PARAM_VALUE
动手实验:写第一个 MAVLink 监听器
创建:
cd ~/uav-sec-lab/code
nano mav_listener.py
代码:
from pymavlink import mavutil
from collections import Counter
import time
connection = mavutil.mavlink_connection('udpin:127.0.0.1:14550')
print('[*] waiting for heartbeat...')
connection.wait_heartbeat()
print('[+] heartbeat:', connection.target_system, connection.target_component)
counter = Counter()
last_report = time.time()
while True:
msg = connection.recv_match(blocking=True, timeout=1)
if msg is None:
continue
name = msg.get_type()
if name == 'BAD_DATA':
continue
counter[name] += 1
if time.time() - last_report >= 5:
print('\n=== last interval / cumulative message counts ===')
for k, v in counter.most_common(15):
print(f'{k:28s} {v}')
last_report = time.time()
运行:
source ~/uav-sec-lab/.venv/bin/activate
python ~/uav-sec-lab/code/mav_listener.py
如果 14550 被 QGroundControl 占用,可让 SITL/MAVProxy 另开一个 UDP 输出端口,例如 14560,再让脚本监听那个端口。
eg.所以其实如果有攻防,很有可能都要利用这个协议,上传什么,或者进行监听
观察任务
记录 30 秒:
- 哪种消息频率最高?
- HEARTBEAT 多久一条?
- ATTITUDE 大约多少 Hz?
- 静止时 GLOBAL_POSITION_INT 是否还一直更新?
1.4 MAVLink 详解(二):命令、任务、参数与状态
第一节是“帧”,第二节要理解“交互协议”。
1. Command Protocol
典型流程:
Sender
|
| COMMAND_LONG
v
Flight Controller
|
| COMMAND_ACK
v
Sender
必懂:
MAV_CMD_*;- ACK;
- accepted / denied / failed 等结果;
- command 和 telemetry 不一样。
2. Mission Protocol
典型上传不是“发一个航点就完事”:
GCS FCU
|--- MISSION_COUNT ------>|
|<-- MISSION_REQUEST_INT -|
|--- MISSION_ITEM_INT ---->|
|<-- MISSION_REQUEST_INT -|
|--- MISSION_ITEM_INT ---->|
|<------ MISSION_ACK ------|
安全研究必须理解这个状态机,否则你只看到“很多消息”。
3. Parameter Protocol
参数实际上影响了大量安全相关行为:
- failsafe;
- arming checks;
- communication;
- estimator;
- flight modes。
因此参数访问也是重要安全面。
动手实验:只打印关键协议消息
from pymavlink import mavutil
m = mavutil.mavlink_connection('udpin:127.0.0.1:14550')
interesting = {
'COMMAND_LONG', 'COMMAND_ACK',
'MISSION_COUNT', 'MISSION_REQUEST', 'MISSION_REQUEST_INT',
'MISSION_ITEM', 'MISSION_ITEM_INT', 'MISSION_ACK',
'PARAM_VALUE'
}
while True:
msg = m.recv_match(blocking=True, timeout=1)
if msg and msg.get_type() in interesting:
print(msg)
然后在 QGroundControl 中:
- 查看参数;
- 创建一个三航点 Mission;
- 上传 Mission;
- 回到终端观察消息序列。
这比背协议文档有效十倍。
1.5 ROS 系统入门到 MAVROS
ROS核心安全缺陷
ROS为简化开发、提升兼容性,默认采用开放设计,存在三大核心安全隐患:
- 无身份认证机制:ROS Master对节点注册无身份校验,任意节点(恶意/合法)均可接入系统,注册话题、发布消息、调用服务,无权限隔离。
- 通信数据明文传输:ROS话题、服务数据均以明文传输,无加密、无完整性校验,攻击者通过网络嗅探即可获取全部通信数据,甚至篡改数据后重放。
- 话题/服务无访问控制:ROS无细粒度权限管理,任意节点可订阅所有话题、调用所有服务,无"最小权限"约束,单点突破即可影响整个系统。
ROS 2 五个词
Node 节点
Topic 发布/订阅
Service 请求/响应
Action 长时间任务
Parameter 参数
第一组 ROS 2 命令
ros2 node list
ros2 topic list
ros2 service list
ros2 action list
ros2 param list
查看 Topic 类型:
ros2 topic type /某个topic
查看 Topic 数据:
ros2 topic echo /某个topic
查看频率:
ros2 topic hz /某个topic
查看接口:
ros2 interface show sensor_msgs/msg/Imu
MAVROS 的位置
Flight Controller
|
MAVLink
|
MAVROS
|
------------------------------------------------
| ROS 2 |
Topics / Services / Parameters / TF / Nodes
你应该把 MAVROS 理解成“协议桥 + 数据模型转换器”。
例如:
MAVLink ATTITUDE
↓
MAVROS plugin
↓
ROS geometry/sensor message
安全视角
ROS 一接进来,攻击面多了:
MAVLink attack surface
+
DDS discovery
+
ROS nodes
+
Topics
+
Services
+
Companion computer OS
下面两个1.6 1.7可以直接跳过,不要用Ai的搭法,我们直接用现成的github项目
1.6 无人机仿真漏洞环境搭建
从这一节以后,“攻击性实验”全部先在这里完成。
推荐拓扑
+-------------------+
| QGroundControl |
+---------+---------+
|
MAVLink
|
+--------------+ +--------v--------+ +-------------+
| Python Lab |<--->| PX4 SITL |<--->| Gazebo |
| pymavlink | | localhost only | | Physics |
+--------------+ +--------+--------+ +-------------+
|
MAVROS
|
+---------v---------+
| ROS 2 |
+-------------------+
实验日志目录
mkdir -p ~/uav-sec-lab/{pcap,logs,code,missions}
每次实验都做的记录
date | tee -a ~/uav-sec-lab/logs/session.log
ss -lunp | tee -a ~/uav-sec-lab/logs/session.log
抓取回环 UDP
sudo tcpdump -i lo -nn -s0 -w ~/uav-sec-lab/pcap/px4_lab.pcap udp
另一个终端启动 PX4 和实验。
结束:Ctrl+C。
分析:
tshark -r ~/uav-sec-lab/pcap/px4_lab.pcap -q -z conv,udp
如果 Wireshark 已正确识别 MAVLink,可尝试显示过滤:
mavlink
否则先按 UDP 端口定位。
实验原则
每一个安全实验都保存:
01_before.pcap
02_during.pcap
03_after.pcap
notes.md
这会逼你从“我感觉发生了攻击”升级到“我有证据说明发生了什么”。
1.7 无人机常见漏洞介绍
不要背“漏洞列表”,学会威胁建模。
攻击面地图
UAV SYSTEM
|
--------------------------------------
| | | |
Wireless MAVLink ROS/DDS Firmware
| | | |
Wi-Fi/RF commands topics boot/update
mission services
params
|
Ground Station / Cloud / Mobile App
五个安全问题
对任何接口都问:
- Authentication:你是谁?
- Authorization:你有权做什么?
- Integrity:消息被改了吗?
- Confidentiality:别人能看吗?
- Freshness / Replay:这是新消息还是旧消息重放?
这里开始特别重要,是主要考点
常见漏洞类别
默认密码 / 弱口令; 【这个感觉是真实生产场景的最大可能】
这边再加一下积累一下

感觉国内这些会比较多一些

结合实战研究与公开CVE漏洞,无人机系统典型漏洞可分为硬件漏洞、固件漏洞、通信漏洞、软件漏洞四大类:
硬件漏洞:调试接口未关闭、硬件后门、传感器易干扰、加密芯片缺失。
固件漏洞:未修复开源组件漏洞、固件明文存储、完整性校验缺失、安全启动未开启、调试信息泄露。
通信漏洞:WiFi弱口令(CVE-2023-6951)、MAVLink无认证、ROS无授权、RTSP未授权访问、GPS信号易欺骗。
软件漏洞:ROS节点劫持、MAVROS数据校验缺失、机载计算机Linux系统漏洞、网页服务SQL注入/目录遍历、相机信息泄露/篡改。
第二章 无人机安全攻防入门:前期侦察篇
2.1 Wi-Fi 安全审计
这个和常见的wifi攻击方式是一样的,简单复习复现一下就行
无线接口识别 → 安全配置审计 → 被动抓取自己实验 AP 的握手 → 离线验证弱口令风险 → 加固。
基础枚举
ip link
nmcli device status
nmcli dev wifi list
无线接口能力:
iw dev
iw phy
安全实验:只审计你自己的测试 AP
被动观察
可使用 Wireshark / tshark 抓取你自己的实验 AP 流量。不要对别人的 AP 发断连、干扰或强制重连帧。
如果你已经通过正常“断开 → 手工重新连接”的方式获得自己的握手抓包,可以用 Aircrack-ng 对 你自己创建的测试词表 做离线强度验证:
printf '%s\n' 'password123' 'DroneLab-Weak-2026' 'a-long-random-passphrase' > ~/uav-sec-lab/lab_words.txt
aircrack-ng ~/uav-sec-lab/pcap/own_ap_handshake.cap \
-w ~/uav-sec-lab/lab_words.txt
这里只验证一个结论:如果密码落在攻击者的小词典里,离线验证会很便宜。
不要下载大型泄漏密码库去跑陌生网络。
这里找到一个和无人机有点搭边的WiFi暴力破解实战(WPA2)可以看看
WiFi暴力破解实战(WPA2)
1、无线网卡监听模式配置** :关闭无线网卡正常模式,开启监听模式,扫描附近WiFi信号。
# 停止无线网卡服务
sudo airmon-ng check kill
# 开启监听模式(wlan0为网卡名)
sudo airmon-ng start wlan0
# 扫描附近WiFi信号,获取BSSID、信道、加密方式
sudo airodump-ng wlan0mon
2、目标WiFi锁定与握手包捕获** :锁定无人机WiFi(如Drone_Wifi),针对性捕获握手包,保存至文件。
# -c:信道,--bssid:目标WiFi MAC,-w:保存握手包
sudo airodump-ng -c 6 --bssid 02:00:00:00:01:00 -w capture wlan0mon
这里注意:WSL2 环境看不到物理无线网卡
如果你是想在 WSL2 里做无线渗透测试,通常需要:
用 USB 无线网卡 + USB 直通 的方式,把网卡直通给虚拟机(比如 VMware/VirtualBox 里的 Kali)。
或者直接在物理机上装 Kali。
所以要研究这个wifi还需要网卡

不过好像找到了相关的解决方法:
sudo apt install wireless-tools sudo su wget https://mirror2.openwrt.org/sources/compat-wireless-2010-06-28.tar.bz2 tar -xjvf compat-wireless-2010-06-28.tar.bz2 cd compat-wireless-2010-06-28 sudo make unload sudo make load # 在kali 中 输入 iwconfig 可以看到
2.2 端口侦察
你要从:
“这是一台无人机”
升级到:
“这台主机开放 UDP 14550、TCP 22、HTTP 8080;其中哪个属于飞控,哪个属于伴随计算机?”
2.3 数据嗅探、指纹识别、数据分析
协议安全研究的黄金技能:抓包。
tcpdump 必会
看接口:
ip -br addr
回环抓 UDP:
sudo tcpdump -i lo -nn udp
抓到文件:
sudo tcpdump -i lo -nn -s0 \
-w ~/uav-sec-lab/pcap/mavlink_session.pcap \
udp
只抓常见实验端口:
sudo tcpdump -i lo -nn \
'udp port 14540 or udp port 14550 or udp port 14551'
tshark
会话统计:
tshark -r ~/uav-sec-lab/pcap/mavlink_session.pcap -q -z conv,udp
包长:
tshark -r ~/uav-sec-lab/pcap/mavlink_session.pcap \
-T fields -e frame.time_relative -e frame.len | head
Wireshark 分析思路
不要打开包就乱点。
按这个顺序:
Endpoints
↓
Conversations
↓
Protocol Hierarchy
↓
UDP/TCP stream
↓
Message timing
↓
Payload / protocol fields
指纹识别思路
如果不知道协议:
- 固定包长?
- 周期性?
- 开头字节固定?
- 每包某字段 +1?
- 静止与运动时哪些字节变化?
- 单击某按钮时只改变哪个字段?
第三章 无人机安全攻防入门:协议欺骗(简单看看)
3.1 MAVLink 安全研究总述(一)
先纠正一个常见误区
“消息能被正常解析”只说明:
格式合法
CRC 基本正确
不自动等于:
发送者可信
发送者有权限
消息没有被恶意构造
MAVLink 安全问题从五层看
L1 Transport
UDP / Serial / RF
L2 Framing
MAVLink v1/v2 frame
L3 Identity
SYSID / COMPID
L4 Authorization
谁有权发 COMMAND / MISSION / PARAM?
L5 Operational Safety
飞控是否会因为异常命令进入危险状态?
MAVLink 2 Signing
MAVLink 2 支持消息签名,目的是帮助接收方验证消息来自持有密钥的可信来源,并提供防重放相关机制。
必须记住:
Signing ≠ Encryption。
签名主要解决身份 / 完整性 / 新鲜度,不会自动把遥测内容变成密文。
Threat Model 作业
给以下消息分类:
HEARTBEAT
ATTITUDE
GPS_RAW_INT
COMMAND_LONG
MISSION_ITEM_INT
PARAM_SET
按:
Confidentiality impact
Integrity impact
Availability impact
Authorization requirement
写表。
3.2 MAVLink 安全研究总述(二):Pymavlink 入门
Pymavlink 对你来说是:
MAVLink 的“瑞士军刀”。
第一阶段:只收不发
heartbeat_reader.py
from pymavlink import mavutil
m = mavutil.mavlink_connection('udpin:127.0.0.1:14550')
print('[*] waiting heartbeat')
m.wait_heartbeat()
print('[+] system:', m.target_system)
print('[+] component:', m.target_component)
while True:
msg = m.recv_match(type='HEARTBEAT', blocking=True)
print(msg.to_dict())
第二阶段:统计消息频率
from pymavlink import mavutil
from collections import defaultdict
import time
m = mavutil.mavlink_connection('udpin:127.0.0.1:14550')
counts = defaultdict(int)
t0 = time.time()
while True:
msg = m.recv_match(blocking=True, timeout=1)
if msg is not None and msg.get_type() != 'BAD_DATA':
counts[msg.get_type()] += 1
if time.time() - t0 >= 10:
for k, v in sorted(counts.items(), key=lambda x: -x[1])[:20]:
print(f'{k:30s} {v/10:.1f} msg/s')
counts.clear()
t0 = time.time()
第三阶段:检查来源身份
msg = m.recv_match(blocking=True)
print(
msg.get_srcSystem(),
msg.get_srcComponent(),
msg.get_type()
)
然后开始问:
SYSID=1 是真实身份,还是一个任何发送者都能填写的字段?
这就是协议欺骗研究的入口。
3.3 传感器型消息欺骗(一):先理解数据面
先理解攻击对象
传感器类信息可能包括:
GPS
IMU
Barometer
Magnetometer
Optical Flow
Rangefinder
Vision Pose
但安全研究不能看到 GPS_RAW_INT 就说“改它等于 GPS 欺骗”。
关键问题:
这条消息只是遥测输出,还是飞控当前配置下真正会作为 estimator 输入?
遥测消息 ≠ 输入消息。
这是本节最重要的一句话。
安全实验:搭一个纯回环“欺骗靶场”
我们先不碰飞控控制环,只证明:
在无额外认证的 UDP 消息通道中,不同进程可以声称相同 SYSID/COMPID。
receiver.py
from pymavlink import mavutil
from collections import defaultdict
import time
PORT = 14660
m = mavutil.mavlink_connection(f'udpin:127.0.0.1:{PORT}')
last = defaultdict(float)
print(f'[*] listening on localhost:{PORT}')
while True:
msg = m.recv_match(blocking=True, timeout=1)
if not msg or msg.get_type() == 'BAD_DATA':
continue
key = (msg.get_srcSystem(), msg.get_srcComponent(), msg.get_type())
now = time.time()
delta = now - last[key] if last[key] else 0
last[key] = now
print(
f'sys={msg.get_srcSystem():3d} '
f'comp={msg.get_srcComponent():3d} '
f'type={msg.get_type():20s} '
f'dt={delta:.3f}'
)
sender_legit.py
from pymavlink import mavutil
import time
TARGET_HOST = '127.0.0.1'
PORT = 14660
if TARGET_HOST != '127.0.0.1':
raise SystemExit('localhost-only lab')
m = mavutil.mavlink_connection(
f'udpout:{TARGET_HOST}:{PORT}',
source_system=42,
source_component=1,
)
while True:
m.mav.heartbeat_send(
mavutil.mavlink.MAV_TYPE_QUADROTOR,
mavutil.mavlink.MAV_AUTOPILOT_PX4,
0,
0,
mavutil.mavlink.MAV_STATE_ACTIVE,
)
time.sleep(1)
sender_spoof.py
from pymavlink import mavutil
import time
TARGET_HOST = '127.0.0.1'
PORT = 14660
if TARGET_HOST != '127.0.0.1':
raise SystemExit('localhost-only lab')
# 故意声明成和 legit sender 相同的 system/component。
m = mavutil.mavlink_connection(
f'udpout:{TARGET_HOST}:{PORT}',
source_system=42,
source_component=1,
)
while True:
m.mav.heartbeat_send(
mavutil.mavlink.MAV_TYPE_GCS,
mavutil.mavlink.MAV_AUTOPILOT_INVALID,
0,
0,
mavutil.mavlink.MAV_STATE_CRITICAL,
)
time.sleep(1.3)
依次运行三个终端。
观察 receiver:
sys=42 comp=1 HEARTBEAT ...
sys=42 comp=1 HEARTBEAT ...
对 receiver 来说,“同一个逻辑身份”出现了相互冲突的语义。
这就是安全问题的最小模型。
3.4 传感器型消息欺骗(二):从“伪造”升级到“检测”
异常检测思路
1. 频率异常
正常 GPS 5 Hz
突然出现 100 Hz 同类消息
→ suspicious
2. 跳变异常
t0: lat=31.20 lon=121.50
0.1s 后:lat=40.71 lon=-74.00
→ 物理上不可能
3. 多传感器不一致
GPS says: east 30 m/s
IMU / optical flow says: almost stationary
→ inconsistency
4. 来源冲突
同一个 SYSID/COMPID:
- 消息序列节奏突然改变;
- autopilot/type 字段矛盾;
- 网络源地址突然改变;
- 签名状态改变。
实验:位置跳变检测器(使用你自己的测试数据)
下面脚本不控制无人机,只读取本地 MAVLink 并根据连续 GLOBAL_POSITION_INT 做粗略速度检测:
from pymavlink import mavutil
from math import radians, sin, cos, sqrt, atan2
import time
m = mavutil.mavlink_connection('udpin:127.0.0.1:14550')
prev = None
R = 6371000.0
def distance_m(lat1, lon1, lat2, lon2):
p1, p2 = radians(lat1), radians(lat2)
dp = radians(lat2 - lat1)
dl = radians(lon2 - lon1)
a = sin(dp/2)**2 + cos(p1)*cos(p2)*sin(dl/2)**2
return 2 * R * atan2(sqrt(a), sqrt(1-a))
while True:
msg = m.recv_match(type='GLOBAL_POSITION_INT', blocking=True, timeout=2)
if not msg:
continue
now = time.time()
lat = msg.lat / 1e7
lon = msg.lon / 1e7
if prev:
dt = now - prev[0]
d = distance_m(prev[1], prev[2], lat, lon)
speed = d / dt if dt > 0 else 0
if speed > 80: # 示例阈值,不是通用飞行规则
print(f'[ALERT] impossible-looking jump: {speed:.1f} m/s')
else:
print(f'[OK] {speed:.1f} m/s')
prev = (now, lat, lon)
重点不在 80 这个数字,重点在“物理约束可以成为安全信号”。
3.5 状态型消息欺骗
状态型消息是什么?
例如:
HEARTBEAT
SYS_STATUS
EXTENDED_SYS_STATE
BATTERY_STATUS
STATUSTEXT
它们可能影响:
- 地面站 UI 判断;
- 运维人员决策;
- 自动化系统;
- 告警系统。
一个非常典型的研究角度不是“把飞机弄坏”,而是:
能不能让监控端误以为系统处于另一种状态?
本地安全实验
继续使用 14660 回环靶场。
一个 sender 发:
MAV_STATE_ACTIVE
另一个同 SYSID sender 发:
MAV_STATE_CRITICAL
然后写接收器规则:
同一逻辑身份在 2 秒内出现互斥状态
→ identity_conflict
防御思路
- 消息签名;
- 网络源地址 + system ID 双绑定;
- 连接上下文绑定;
- 状态变迁合法性检查;
- 多消息交叉验证;
- 可信设备白名单;
- 日志记录签名验证结果。
第四章 无人机安全攻防入门:注入攻击【重点】
本章所有“发控制消息”的代码必须指向本地 SITL。不要改成真实无线链路或未授权设备。
4.1 MAVLink 注入攻击基础(一):什么叫 Injection?
定义
在安全研究里,“注入”不是神秘技巧:
接收端接受了原本不应该由当前发送者产生或授权的消息。
所以核心问题其实是:
格式验证?
身份验证?
授权?
状态机条件?
安全保护?
三种注入研究层级
Level 1:回环协议靶场
不连接飞控,只观察消息接受
Level 2:SITL
连接模拟飞控,验证状态机
Level 3:真实硬件
只允许在明确授权 + 安全场地 + 去桨/约束条件下
本文只覆盖 Level 1/2。
回环实验:自定义消息发送
你已经做过 HEARTBEAT 双发送者实验。
现在改成 NAMED_VALUE_FLOAT:
from pymavlink import mavutil
import time
HOST = '127.0.0.1'
PORT = 14660
if HOST != '127.0.0.1':
raise SystemExit('localhost-only')
m = mavutil.mavlink_connection(
f'udpout:{HOST}:{PORT}',
source_system=50,
source_component=190,
)
for i in range(20):
m.mav.named_value_float_send(
int(time.time() * 1000) & 0xffffffff,
b'LAB_TEST',
float(i),
)
time.sleep(0.2)
观察 receiver。
这一步就是你第一次“主动构造 MAVLink message”。
4.2 MAVLink 注入攻击基础(二):安全状态机
飞控不是“收到起飞包就起飞”。
通常至少有:
connected?
↓
health checks OK?
↓
arming allowed?
↓
armed?
↓
flight mode permits operation?
↓
setpoint / mission available?
↓
controller acts
因此真正的研究对象是状态机。
动手:观察 PX4 Commander
PX4 shell:
commander status
listener vehicle_status
在 QGC 中做:
disarmed
→ arm
→ takeoff
→ hover
→ land
→ disarm
每一步都记录 vehicle_status。
DISARMED
|
| arm checks pass
v
ARMED
|
| takeoff
v
IN_AIR
|
| land
v
LANDED
|
| disarm
v
DISARMED
4.3 阶段一:起飞与飞行条件分析
推荐做法
先不用 Python 控制,使用 QGroundControl 或 MAVProxy 对 SITL 起飞。
ArduPilot SITL / MAVProxy 示例
仅对自己的 SITL:
mode GUIDED
arm throttle
takeoff 10
官方 ArduPilot SITL 教程使用这一流程演示 GUIDED 模式起飞。
观察什么
抓包并过滤:
COMMAND_LONG
COMMAND_ACK
HEARTBEAT
EXTENDED_SYS_STATE
GLOBAL_POSITION_INT
回答:
- arm 命令前后 heartbeat 的 base_mode 如何变化?
- takeoff 是否有 ACK?
- 高度变化由哪个遥测消息体现?
- 如果健康检查失败,命令层和状态层分别表现为什么?
4.4 阶段二:航线篡改与任务完整性(一)
先从合法 Mission 做起
在 QGroundControl 对 SITL:
- 创建 3 个航点;
- Upload;
- Save Plan 到
~/uav-sec-lab/missions/mission_A.plan; - 抓包;
- 看 Mission Protocol。
你要找的消息
MISSION_COUNT
MISSION_REQUEST_INT
MISSION_ITEM_INT
MISSION_ACK
安全实验设计
不做网络中间人,不拦截别人通信。
在自己的 SITL 里做:
1. GCS 上传 Mission A
2. 记录 Mission A
3. 本地第二个受控客户端连接 SITL
4. 通过正常 Mission API 上传 Mission B
5. GCS 再次下载任务
6. 验证任务是否发生变化
7. 分析“为什么第二个客户端被接受”
这已经足够证明授权边界问题,不需要真实劫持无线链路。
4.5 阶段二:航线篡改与任务完整性(二)——写检测器
Mission 指纹思想
把任务标准化后计算 hash:
Mission Items
↓
canonical serialization
↓
SHA-256
↓
mission fingerprint
Python 基础版:
import hashlib
import json
mission = [
{"seq": 0, "cmd": 16, "lat": 47.0, "lon": 8.0, "alt": 20},
{"seq": 1, "cmd": 16, "lat": 47.0001, "lon": 8.0001, "alt": 30},
]
canonical = json.dumps(
mission,
sort_keys=True,
separators=(',', ':'),
).encode()
print(hashlib.sha256(canonical).hexdigest())
第五章 无人机安全攻防入门:组件服务
5.1 组件服务之 Wi-Fi 篇(一):服务发现
无人机系统经常不是“一个飞控”,而是:
Wi-Fi router
Linux companion computer
camera server
video streaming
web UI
SSH
MAVLink router
ROS 2
本地服务地图
ss -lntup
只扫描自己的实验机:
nmap -sT -sV 127.0.0.1
如果你有一台自己控制的 Ubuntu VM,例如 192.168.56.20,且它属于 Host-only 虚拟网络:
nmap -sT -sV 192.168.56.20
不要把网段随手换成公司、学校、酒店或陌生网络。
识别结果后分类
22/tcp SSH → admin plane
80/tcp HTTP → management UI
554/tcp RTSP → video
14550/udp MAVLink → control/telemetry
DDS ports → ROS 2 middleware
安全研究关键是“服务 → 权限 → 资产”的映射。
5.2 组件服务之 Wi-Fi 篇(二):加固
Linux 主机基本加固
查看监听:
ss -lntup
查看防火墙:
sudo ufw status verbose
实验机可以采用“默认拒绝、按需开放”:
sudo ufw default deny incoming
sudo ufw default allow outgoing
然后只开放你明确需要的管理服务。
不要机械复制开放端口命令——先确认架构。
最佳实践
User Wi-Fi
X
| 不应直接抵达飞控控制端口
v
Gateway / firewall
|
Companion network
|
MAVLink router
|
Flight controller
5.3 组件服务之 ROS 篇(一):ROS 2 攻击面枚举
自己的 ROS 2 实验环境
终端 A:
source /opt/ros/jazzy/setup.bash
ros2 run demo_nodes_cpp talker
终端 B:
source /opt/ros/jazzy/setup.bash
ros2 node list
ros2 topic list
ros2 topic info /chatter
ros2 topic echo /chatter --once
5.4 组件服务之 ROS 篇(二):SROS2 与最小权限
从:
“同一个 DDS 网络里大家都能说话”
变成:
“这个 node 只能 publish A,subscribe B,不能调用 C。”
需要了解:
- DDS Security;
- identity certificate;
- governance;
- permissions;
- encryption;
- access control;
- SROS2 keystore。
推荐学习命令
先确认工具:
ros2 security --help
查看子命令:
ros2 security create_keystore --help
ros2 security create_key --help
由于 SROS2 CLI 在不同发行版可能有变化,实验时始终以本机 --help 为准,不要盲抄旧博客。
第六章 实体攻防:使用 AI 逆向无人机通信协议
只分析你自己拥有、明确授权或公开提供用于研究的设备/数据。本文不涉及破解加密无线链路、绕过配对或干扰射频。
6.1 协议逆向的正确姿势
这项能力不仅适用于无人机,所有 IoT/嵌入式/机器人协议都通用。
典型流程
Acquire data
↓
Find framing
↓
Find length
↓
Find sequence / counter
↓
Find command / type
↓
Infer payload fields
↓
Find checksum / CRC
↓
Build parser
↓
Build state model
↓
Validate hypotheses
第一步:不要急着问 AI“这是什么协议”
先做差分实验。
例如遥控器有 4 个动作:
idle
throttle up
yaw left
button A
每个动作抓 20 个包。
建立:
idle_01.bin ... idle_20.bin
throttle_01.bin ...
yaw_01.bin ...
button_a_01.bin ...
然后统计每个 byte offset 的变化率。
6.2 先逆向一个 Toy Drone Protocol
为了合法、安全地练完整流程,我们自己造一个未知协议。
generator.py
import os
import random
import struct
# frame:
# AA 55 | LEN | TYPE | SEQ | X(int16) | Y(int16) | BAT(uint8) | CRC8
# 学习时假装你不知道格式。
def crc8(data):
c = 0
for b in data:
c ^= b
return c
os.makedirs('captures', exist_ok=True)
seq = 0
for label, typ, xbase, ybase in [
('idle', 1, 0, 0),
('forward', 2, 100, 0),
('left', 3, 0, -100),
('button_a', 9, 0, 0),
]:
with open(f'captures/{label}.bin', 'wb') as f:
for _ in range(30):
x = xbase + random.randint(-3, 3)
y = ybase + random.randint(-3, 3)
bat = random.randint(70, 90)
payload = struct.pack('<BBhhB', typ, seq & 0xff, x, y, bat)
body = bytes([len(payload)]) + payload
frame = b'\xaa\x55' + body + bytes([crc8(body)])
f.write(frame)
seq += 1
运行:
mkdir -p ~/uav-sec-lab/code/toyproto
cd ~/uav-sec-lab/code/toyproto
python generator.py
xxd captures/idle.bin | head
xxd captures/forward.bin | head
现在先把代码盖住,只看 bin,当作真实抓包。
你的逆向任务
Task A:找帧头
搜索重复:
xxd -p captures/idle.bin | tr -d '\n' | grep -o 'aa55' | wc -l
Task B:找帧长
看看 aa55 后的 byte 是否稳定。
Task C:找 counter
对齐 10 个 frame,找哪一列近似 +1。
Task D:动作差分
比较:
cmp -l captures/idle.bin captures/forward.bin | head -30
更好的做法是写 Python 对齐帧后按 byte offset 统计。
6.3 写通用“字节变化率分析器”
from pathlib import Path
from collections import Counter
FRAME_LEN = 11 # 逆向过程中这是你的假设,不一定正确
def frames(path):
data = Path(path).read_bytes()
return [data[i:i+FRAME_LEN] for i in range(0, len(data), FRAME_LEN)
if len(data[i:i+FRAME_LEN]) == FRAME_LEN]
for file in Path('captures').glob('*.bin'):
fs = frames(file)
print('\n', file)
for off in range(FRAME_LEN):
values = [f[off] for f in fs]
unique = len(set(values))
common = Counter(values).most_common(3)
print(f'offset={off:02d} unique={unique:02d} common={common}')
你会看到某些 offset:
- 永远固定;
- 每帧变化;
- 随动作变化;
- 缓慢变化。
这四类特征分别很像:
magic/header
counter/timestamp
command/control field
battery/sensor
6.4 AI 在协议逆向里真正有用的地方
不要直接扔 5 MB hex 给 AI。
最好给 AI:
1. 20 个已经对齐的 frame
2. 每个 frame 的实验动作标签
3. byte offset 变化率
4. 你的猜测
5. 问它“提出可证伪的假设”
好问题:
Offset 0-1 永远是 AA55;offset2 永远是 07;offset4 每帧+1;
在 forward 样本里 offset5-6 接近 100,idle 接近 0。
请给出三个字段布局假设,并告诉我下一步如何设计实验区分它们。
坏问题:
这串 hex 是什么?帮我破解。
真正的逆向是“实验科学”,AI 是假设生成器,不是魔法解码器。
第七章、贯穿全课程的四个大项目
Project 1:MAVLink Telemetry Inspector
目标:
写一个终端工具:
连接本地 MAVLink
↓
列出 system/component
↓
统计 message rate
↓
打印关键状态
↓
检测来源冲突
↓
保存 JSONL 日志
最低功能:
--endpoint udpin:127.0.0.1:14550
--duration 60
--json log.jsonl
完成后,你对 MAVLink 的理解会明显上一个台阶。
Project 2:MAVLink IDS Lite
检测:
Unexpected SYSID
Unexpected COMPID
Message rate spike
Position jump
Impossible state transition
Duplicate/conflicting identity
Unsigned critical traffic(如果环境启用了 signing policy)
输出示例:
[INFO] system 1 discovered
[WARN] HEARTBEAT rate changed 1Hz -> 15Hz
[ALERT] same SYSID/COMPID produced conflicting autopilot types
[ALERT] position jump implies 932m/s
Project 3:Mission Integrity Monitor
目标:
Mission download
↓
normalize
↓
SHA-256
↓
compare with approved hash
↓
audit log
安全价值非常高,而且完全不需要写“攻击武器”。
Project 4:ROS 2 Attack Surface Auditor
自动收集:
nodes
publishers
subscribers
services
actions
parameters
DDS domain
最后输出:
high-risk bridge node
flight-control related topic
write-capable services
unexpected publisher
第八章、真正需要背下来的命令
Linux / 网络
ip -br addr
ip route
ss -lntup
sudo tcpdump -i lo -nn udp
nmap -sT -sV 127.0.0.1
tshark -r file.pcap -q -z conv,udp
PX4
help
commander status
mavlink status
uorb top
listener vehicle_status
listener vehicle_attitude
listener vehicle_local_position
listener vehicle_global_position
param show <NAME>
启动:
cd ~/PX4-Autopilot
make px4_sitl gz_x500
ArduPilot SITL
./Tools/autotest/sim_vehicle.py -v ArduCopter --console --map -w
ROS 2
ros2 node list
ros2 topic list
ros2 topic info <topic>
ros2 topic echo <topic> --once
ros2 topic hz <topic>
ros2 service list
ros2 action list
ros2 param list
ros2 interface show <type>
Python / Pymavlink
from pymavlink import mavutil
m = mavutil.mavlink_connection('udpin:127.0.0.1:14550')
msg = m.recv_match(blocking=True)
print(msg.get_type())
print(msg.get_srcSystem(), msg.get_srcComponent())
print(msg.to_dict())
第九章、哪些内容必须精学,哪些可以暂时跳过
S 级:必须精学
★★★★★ 无人机数据流 / 控制链
★★★★★ PX4 Commander / Navigator / EKF 的角色
★★★★★ MAVLink frame / SYSID / COMPID / message ID
★★★★★ HEARTBEAT / COMMAND / MISSION
★★★★★ Pymavlink receive / parse
★★★★★ SITL
★★★★★ tcpdump / Wireshark
★★★★★ 身份认证、完整性、授权、重放
★★★★★ 状态机
★★★★★ Mission 完整性
A 级:必须会用
★★★★☆ ROS 2 node/topic/service
★★★★☆ MAVROS
★★★★☆ nmap / ss
★★★★☆ Linux 网络
★★★★☆ 异常检测
★★★★☆ MAVLink 2 signing 概念
B 级:学到能解释即可
★★★☆☆ Wi-Fi 握手原理
★★★☆☆ ArduPilot 与 PX4 全面源码差异
★★★☆☆ DDS 底层协议
★★★☆☆ 复杂 RF PHY
暂时跳过
大规模公网扫描
未授权 Wi-Fi 攻击
无线干扰 / jamming
真实无人机飞行中的注入测试
真实设备去安全限制
固件持久化植入
规避检测技巧
它们不是成为优秀无人机安全研究者的必要前置。
第十章、最终能力自测
不要看答案,自己回答:
基础
- 飞控和伴随计算机有什么区别?
- uORB 是什么?
- Commander 与 Navigator 的职责有什么不同?
- EKF 为什么是安全研究的关键点?
MAVLink
- SYSID / COMPID 的作用?
- CRC 和 signing 有何本质区别?
- HEARTBEAT 有什么用途?
- COMMAND_LONG 与 COMMAND_ACK 什么关系?
- Mission 上传为什么是状态机?
- 参数写入为什么属于安全面?
网络
open|filtered为什么经常出现在 UDP 扫描?- tcpdump 和 Wireshark 各适合什么阶段?
- 如何从未知 UDP 流量里寻找协议指纹?
欺骗与检测
- 为什么伪造遥测消息不一定影响飞控状态?
- 如何判断某条 sensor message 是输入还是输出?
- 两个 sender 声称相同 SYSID/COMPID,如何检测?
- GPS 跳变可以通过哪些物理约束发现?
ROS
- Topic 和 Service 区别?
- MAVROS 的本质是什么?
- ROS_DOMAIN_ID 为什么不是完整安全机制?
- SROS2 解决什么问题?
逆向
- 如何找 frame header?
- 如何猜 sequence 字段?
- 怎样通过“控制一个变量”确定某个 byte 的含义?
- AI 在逆向中最好的角色是什么?
第十一章、推荐参考资料(以官方文档为主)
PX4
- PX4 User Guide: https://docs.px4.io/
- PX4 Simulation: https://docs.px4.io/main/en/simulation/
- PX4 Gazebo Simulation: https://docs.px4.io/main/en/sim_gazebo_gz/
- PX4 ROS 2 User Guide: https://docs.px4.io/main/en/ros2/user_guide
MAVLink
- MAVLink Guide: https://mavlink.io/en/
- Pymavlink: https://mavlink.io/en/mavgen_python/
- MAVLink 2 Signing: https://mavlink.io/en/guide/message_signing.html
ArduPilot
- ArduPilot Developer Docs: https://ardupilot.org/dev/
- SITL: https://ardupilot.org/dev/docs/using-sitl-for-ardupilot-testing.html
ROS 2
- ROS 2 Jazzy Docs: https://docs.ros.org/en/jazzy/
- MAVROS Docs: https://docs.ros.org/en/rolling/p/mavros/
参考文章:
不知道是不是原文,不过这篇写的蛮好的


说些什么吧!