jedbillyb/airdrop-mt7921
GitHub: jedbillyb/airdrop-mt7921
在 Linux 上利用内置 MT7921 Wi-Fi 芯片实现 AirDrop 接收,无需额外 USB 网卡。
Stars: 0 | Forks: 0
# airdrop-mt7921
在 Linux 上使用**内置的 MediaTek MT7921** Wi-Fi 芯片实现 AirDrop,无需 USB
适配器。
从 iOS 26 的 iPhone 接收照片已实现端到端成功运行。本仓库包含了用于
环境配置的脚本、使 iOS 26 传输得以正确解析的 OpenDrop 补丁,
以及实现该功能的相关研究。
## 为什么会有这个项目
每一份关于在 Linux 上使用 AirDrop 的指南都会告诉你同样的事情:你需要一块支持
正常工作的 **active monitor mode** 的网卡,而在实际操作中,这意味着必须购买 Atheros
AR9271 或 AR9280 USB 适配器。上游 OWL 的 README 已经明确说明了这一点。
人们此前认为 MT7921 不符合条件。这块芯片上的 active monitor vif 无论你如何请求,
都会被强制锁定在 5180 MHz,并且在其运行期间似乎会破坏接收功能。
事实证明,这两个判断都是错误的,而解决方法只需通过配置即可实现,
无需打补丁:
**首先创建一个普通的 monitor vif 并进行调谐。然后在其旁边添加 active vif。**
它们共享一个 channel context。Active vif 会在普通 vif 的频道上启动,
且不会产生接收损耗,并且重新调谐其中任何一个都会同时移动两者——
这样你就保留了硬件 ACK *以及* AWDL 的频道跳频。
这就是全部的诀窍。详细信息,包括我在发现此方法之前得出的两个错误结论,
都在 [docs/FINDINGS.md](docs/FINDINGS.md) 的 §13-§14 中。
## 状态
| | |
|---|---|
| 从 iPhone 接收 | **可用**(iOS 26,已验证端到端运行) |
| 发送到 iPhone | **未测试** |
| 吞吐量 | ~50 kB/s - 受占空比限制,参见 [FINDINGS §16](docs/FINDINGS.md) |
| 已测试硬件 | MT7921 (Filogic 330), Void Linux, kernel 6.12.97 |
每个人都在警告的身份验证壁垒实际上从未遇到过。在 **Everyone** 模式下,
iPhone 会接受未经签名的接收端。Contacts-only 模式将需要
由 Apple 密钥签名的验证记录,这是确实无法伪造的。
## 要求
- 一块 MT7921(或可能是任何 `mt76`)网卡。其他网卡也许可用;除了下文提到的两个驱动程序变通方法外,这里没有任何内容是
MT7921 专用的。
- `iw`, `tcpdump`, `libpcap`, `libev`, `libnl`
- 已打补丁的 OWL 构建版本 - 见下文
- OpenDrop,需应用补丁 `patches/opendrop-ios26-airdrop.patch`
- Root 权限,并且愿意在程序运行期间断开网络
## 安装说明
**1. 构建已打补丁的 OWL。** 上游的 OWL 可以同步,但无法提供良好的
吞吐量;我的 fork 版本添加了两个针对 mt7921 的变通方法和频道序列
修复:
```
git clone https://github.com/jedbillyb/owl.git ~/owl
cd ~/owl && cmake -S . -B build -DCMAKE_BUILD_TYPE=Release && cmake --build build
```
**2. 安装并为 OpenDrop 打补丁。** iOS 26 在三个独立的
地方破坏了原版 OpenDrop - 参见 [patches/README.md](patches/README.md):
```
python -m venv ~/owl/.venv-opendrop
~/owl/.venv-opendrop/bin/pip install opendrop
git apply --directory=... patches/opendrop-ios26-airdrop.patch # see patches/README.md
```
**3. 运行它。**
```
./airdrop.sh receive # advertise this machine as an AirDrop target
./airdrop.sh # discover nearby devices only
./airdrop.sh send # untested
```
在手机上:**设置 → 通用 → 隔空投送 → 所有人(10 分钟)**,然后
打开分享面板并将其保持打开状态。
文件会存入 `~/Downloads`。每次运行的日志和抓包数据会保存在 `./runs/` 中。
### 配置
以下均为可选项,且均为环境变量:
| 变量 | 默认值 | 含义 |
|---|---|---|
| `IFACE` | 自动检测到的 mt7921 接口 | Wi-Fi 接口 |
| `REG` | `NZ` | 监管域 - **请将其设置为你的国家** |
| `CHAN` | `36` | 起始频道 (6, 36, 44, 149) |
| `OWL_DIR` | `~/owl` | 你已打补丁的 OWL 检出目录 |
| `RECV_DIR` | `~/Downloads` | 接收文件的解压目录 |
| `RECV_TIME` | `300` | 保持广播的秒数 |
| `OUT_DIR` | `./runs` | 日志和抓包数据的保存目录 |
## 安全性
`airdrop.sh` 会独占 Wi-Fi 网卡 - **在它运行期间,你将无法上网**。
它会在退出时通过 bash trap *以及* 一个 `setsid` 分离的 watchdog 来恢复 NetworkManager,因此即使脚本被
`kill -9` 终止或挂起,网络也会恢复。init 系统(runit 或 systemd)会被自动检测。
## 你会遇到两个 mt7921 驱动程序 bug
这两个问题都已由 `airdrop.sh` 进行了变通处理;它们各自浪费了我一天的时间,因此
非常值得明确指出:
1. **运行时电源管理会静默地破坏 monitor RX。** 当 `runtime-pm=1` 时,
芯片会进入休眠状态,导致你什么也抓不到,而且不会出现任何错误。请将
`/sys/kernel/debug/ieee80211//mt76` 中的 `runtime-pm` 和 `deep-sleep` 设置为 0。
2. **原地的接口类型切换永远不会重新调谐无线电。** `iw dev X set
type monitor` 会使无线电保持在原来的位置。你必须创建一个*专用的*
monitor vif。
还有一个比上述两点让我付出更大代价的方法论注意事项:**在这款芯片上,`iw` 会在频道问题上撒谎。** 它报告的是你请求的频道,而不是无线电实际所在的频道。唯一可靠的来源是已捕获帧的 radiotap 频率。`docs/FINDINGS.md` 中有两个被撤回的结论,就是由于轻信了 `iw` 而导致的。
## 仓库布局
```
airdrop.sh the tool
patches/ OpenDrop fixes for iOS 26
docs/FINDINGS.md the full investigation, including what I got wrong
docs/NOTES.md dated lab notebook
tools/ diagnostic harnesses, each answering one question
```
`tools/` 是研究脚本,而不是测试套件。每个脚本都会隔离一个问题,并在运行结束后
恢复你的网络。`activelate2.sh` 和 `activelate3.sh` 是用于
建立该项目所依赖的配对配置的两个脚本。
## 鸣谢
- [seemoo-lab/owl](https://github.com/seemoo-lab/owl) - AWDL 实现
- [seemoo-lab/opendrop](https://github.com/seemoo-lab/opendrop) - AirDrop 层
- [Open Wireless Link](https://owlink.org) 项目的逆向工程
## 许可证
GPLv3,与 OWL 保持一致。
标签:AirDrop, MT7921, Wi-Fi, 内核驱动, 应用安全, 无线网络, 网络协议, 逆向工具