拓十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

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

RTL8811CU/8821CU Linux驱动一键安装脚本:Kali与树莓派无线网卡编译指南

RTL8811CU/8821CU Linux驱动一键安装脚本:Kali与树莓派无线网卡编译指南

1. 为什么RTL8811CU这块网卡总让人又爱又恨

如果你手头有一块基于 Realtek RTL8811CU 芯片的 USB 无线网卡,大概率经历过这样的场景:在 Windows 上插上就能用,换到 Kali 或者树莓派上,ifconfig里死活看不到wlan0,iwconfig也是一片空白。这块芯片本身素质不差,双频 802.11ac、支持 2.4G/5G、价格便宜、体积小巧,在渗透测试和树莓派联网场景里出镜率极高。问题出在驱动上——Realtek 官方对 Linux 主线的支持一直很敷衍,内核自带的rtl8xxxu驱动对 8811CU 的支持时好时坏,很多发行版干脆默认不加载。

我最早接触这块卡是在一台树莓派 4B 上,想拿它做无线中继,结果折腾了整整一个下午。后来在 Kali 上做无线审计,又踩了一遍同样的坑。反复几次之后,我干脆把整个安装流程写成了一个脚本,从此换机器、重装系统,一条命令搞定。这篇内容就是把这套流程完整拆开讲清楚:驱动从哪来、为什么编译会失败、脚本里每一步在干什么、遇到报错怎么排查。不管你是刚装完 Kali 的新手,还是手里有一堆树莓派要批量部署的老手,都能直接拿去用。

需要先说明一点:RTL8811CU 和 RTL8821CU 是同一颗芯片的不同封装/型号命名,驱动层面基本通用。市面上很多标着“8821CU”“8811CU”的迷你网卡,甚至一些带外置天线的型号,内核里认的都是同一个rtl8821cu模块。所以后面讲的方案,对这两个型号都适用。

2. 驱动来源的选择:为什么我不推荐直接用内核自带的

2.1 内核自带 rtl8xxxu 的真实表现

Linux 内核里确实有一个rtl8xxxu驱动,理论上覆盖了包括 8811CU 在内的一批 Realtek USB 网卡。但实际用下来,它在 8811CU 上的表现可以用“薛定谔的可用”来形容。在部分内核版本(比如 5.15 系列)上,插上卡能识别,dmesg里也能看到固件加载,但一到监听模式或者注入测试就各种掉线;换到 6.x 内核,有时候连wlan0都出不来。

根本原因在于rtl8xxxu是一个社区逆向出来的通用驱动,对 8811CU 这种较新的芯片,很多寄存器初始化序列、射频校准参数并不完整。Realtek 官方其实提供了独立的rtl8821cu驱动源码,功能完整得多,支持监听模式、支持 AP 模式、支持注入。所以我的原则很明确:只要你要用监听、注入、AP 这些进阶功能,就别指望内核自带驱动,老老实实编译官方驱动。

2.2 官方驱动源码的获取渠道

Realtek 官方驱动一般通过 GitHub 上的几个镜像仓库分发,比较活跃的有brektrou/rtl8821CU、morrownr/8821cu-20210916等。这些仓库本质上是把 Realtek 放出的源码做了适配,让它在较新的内核上能编译通过。选仓库的时候有几个判断标准:

  • 最近一年内有提交记录,说明还在维护;
  • README 里明确写了支持的内核版本范围;
  • Issues 区没有大量“编译失败”且无人回复的帖子。

我目前脚本里默认拉取的是morrownr维护的版本,因为他对内核 API 变更跟进比较及时,DKMS 支持也做得干净。下面这张表是我对比过的几个常见来源:

驱动来源优点缺点适用场景
内核 rtl8xxxu免安装,插上即用功能残缺,监听/注入不稳只做普通上网
brektrou/rtl8821CU社区活跃,文档全偶尔滞后于最新内核通用场景
morrownr/8821cuDKMS 支持好,跟进快仓库名带日期,需注意版本Kali/树莓派首选
Realtek 官方压缩包最原始需手动适配内核 API有编译经验者

2.3 为什么脚本里要用 DKMS

DKMS(Dynamic Kernel Module Support)是我强烈建议加进流程的一环。原因很简单:Kali 和树莓派系统都会频繁更新内核,每次内核升级,手动编译的驱动模块就会失效,你得重新make && make install一遍。用 DKMS 注册之后,内核更新时会自动重新编译并安装模块,省掉大量重复劳动。

代价是 DKMS 需要额外的依赖包(dkms、build-essential、对应内核的 headers),脚本里要先把这些装好。对于树莓派,headers 包名是raspberrypi-kernel-headers;对于 Kali,通常是linux-headers-$(uname -r)。这一步如果漏了,DKMS 注册会直接失败,后面全白搭。

3. 一键脚本的完整拆解:每一行都在解决什么问题

3.1 环境检测与依赖安装

脚本的第一步不是急着拉源码,而是先搞清楚“我在什么系统上、缺什么”。我见过太多人直接复制粘贴编译命令,结果卡在make: command not found或者No such file or directory: /lib/modules/.../build。前者是没装编译工具,后者是没装内核头文件。

脚本里这段逻辑大致是这样:

#!/bin/bash set -e # 检测发行版 if [ -f /etc/os-release ]; then . /etc/os-release OS=$ID fi # 安装基础依赖 install_deps() { case $OS in kali|debian|ubuntu) apt update apt install -y git dkms build-essential bc \ linux-headers-$(uname -r) ;; raspbian) apt update apt install -y git dkms build-essential bc \ raspberrypi-kernel-headers ;; *) echo "未识别的系统,请手动安装 git dkms build-essential 及内核头文件" exit 1 ;; esac }

这里有几个细节值得说。set -e让脚本在任何命令返回非零时立即退出,避免错误被忽略后继续执行导致更混乱的结果。bc这个包很多人会漏,但内核编译过程中计算版本号会用到它,缺了会报一个很隐晦的错误。树莓派那边用raspberrypi-kernel-headers而不是linux-headers,是因为树莓派基金会自己维护了一套内核包命名体系,装错了 headers 版本对不上,编译出来的模块加载会报version magic不匹配。

提示:如果你在 Kali 虚拟机里跑这个脚本,先确认虚拟机已经能联网。有些朋友装完 Kali 发现连不上网,其实是因为 USB 网卡没驱动、而虚拟机又没桥接有线网。这种情况先用 NAT 模式的有线连接把依赖装完,再处理无线网卡。

3.2 源码拉取与分支选择

依赖装好之后,脚本会克隆驱动源码。这里我踩过一个坑:早期直接用git clone默认分支,结果某次仓库主分支合并了一个未测试的提交,编译直接报错。后来改成固定 tag 或者指定一个经过验证的 commit,稳定性大幅提升。

DRIVER_REPO="https://github.com/morrownr/8821cu-20210916.git" DRIVER_DIR="/usr/src/rtl8821cu-20210916" if [ ! -d "$DRIVER_DIR" ]; then git clone --depth 1 "$DRIVER_REPO" "$DRIVER_DIR" fi

--depth 1只拉最近一次提交,省流量也省时间,对树莓派这种存储卡容量有限的设备很友好。把源码放到/usr/src/下是 DKMS 的惯例,因为 DKMS 默认会去这个目录找源码树。

3.3 DKMS 配置文件的生成逻辑

DKMS 需要一个dkms.conf文件来描述模块名、版本、源码位置和编译指令。官方仓库里通常自带一个,但版本号和路径经常和实际不符,所以脚本里我会动态生成一份,确保路径对得上。

cat > "$DRIVER_DIR/dkms.conf" <<EOF PACKAGE_NAME="rtl8821cu" PACKAGE_VERSION="20210916" BUILT_MODULE_NAME[0]="8821cu" DEST_MODULE_LOCATION[0]="/kernel/drivers/net/wireless" MAKE[0]="make" CLEAN="make clean" AUTOINSTALL="yes" EOF

BUILT_MODULE_NAME要和驱动 Makefile 里最终生成的.ko文件名一致。8811CU/8821CU 驱动编译出来通常是8821cu.ko,所以这里写8821cu。如果写错了,DKMS 会提示找不到模块文件。DEST_MODULE_LOCATION指定模块安装到内核模块目录的哪个子路径下,放wireless下比较规范。

3.4 编译、安装与模块加载

配置就绪后,剩下的就是 DKMS 的标准三连:

dkms add -m rtl8821cu -v 20210916 dkms build -m rtl8821cu -v 20210916 dkms install -m rtl8821cu -v 20210916 modprobe 8821cu

dkms add把源码树注册进 DKMS 数据库,build执行编译,install把编译好的模块复制到/lib/modules/$(uname -r)/下并更新依赖。最后modprobe加载模块。如果前面每一步都成功,这时候插上网卡,ip link里应该就能看到一个新的无线接口了。

我习惯在脚本最后加一段验证逻辑,自动检查模块是否加载、接口是否出现:

if lsmod | grep -q 8821cu; then echo "驱动模块已加载" else echo "模块加载失败,请检查 dmesg" dmesg | tail -20 fi

4. 那些年我踩过的编译报错与排查路径

4.1 内核头文件版本不匹配

这是最高频的报错,没有之一。典型症状是make阶段报error: implicit declaration of function或者直接提示找不到generated/autoconf.h。根因就是/lib/modules/$(uname -r)/build这个软链接指向的 headers 目录不存在,或者版本和当前运行内核不一致。

排查方法很直接:

uname -r ls -l /lib/modules/$(uname -r)/build

如果build是断链,或者指向的目录不存在,就说明 headers 没装对。Kali 上执行apt install linux-headers-$(uname -r),如果提示找不到包,先apt update,或者检查是不是用了 backports 内核但没加对应源。树莓派上如果raspberrypi-kernel-headers装完还是对不上,可能是系统内核被手动升级过而 headers 没跟着升,这种情况要么降内核,要么手动编译对应版本 headers。

4.2 GCC 版本过高导致的语法报错

较新的 Kali(比如 2024 以后的版本)默认 GCC 版本比较高,而 Realtek 官方驱动源码里有些老式写法在新标准下会报错,比如-Werror=implicit-function-declaration被当成错误。我遇到过好几次error: ‘strncpy’ specified bound depends on the length of the source argument这类警告升级成错误的情况。

解决办法有两个:一是给make加上KCFLAGS="-Wno-error"参数,把警告降级;二是直接修改源码里出问题的行。脚本里我倾向于用前者,因为改源码在 DKMS 重新编译时会被覆盖,不如在编译参数上做文章:

MAKE[0]="make KCFLAGS='-Wno-error'"

4.3 树莓派上的 ARM 架构编译问题

树莓派是 ARM 架构,驱动源码里有些针对 x86 的内联汇编或者字节序假设,在 ARM 上会编译失败。好在morrownr的仓库对 ARM 做了适配,大部分情况直接能过。但如果你的树莓派是 64 位系统(aarch64),而驱动默认按 32 位编译,可能会报指针长度相关的错误。这时候需要确认make时传了正确的ARCH=arm64参数,或者直接用 64 位适配的分支。

另外树莓派的 USB 供电是个隐形杀手。8811CU 在 5G 频段高负载时功耗不低,树莓派 USB 口供电不足会导致网卡反复掉线重连,dmesg里会刷usb disconnect之类的日志。这种情况换一个有源 USB Hub 就能解决,跟驱动本身没关系,但很容易被误判成驱动问题。

4.4 模块加载后接口不出现的排查顺序

编译安装都成功,lsmod也能看到模块,但ip link里就是没有wlan0。这时候按下面顺序排查:

  1. dmesg | grep -i 8821看驱动加载日志,有没有固件加载失败的提示;
  2. rfkill list看无线是不是被软/硬开关禁用了;
  3. modprobe -r 8821cu && modprobe 8821cu重新加载一次;
  4. 换一个 USB 口,排除供电和端口问题;
  5. 检查是不是内核自带的rtl8xxxu抢先占用了设备,用lsmod | grep rtl8确认,如果有就把它加入黑名单。

黑名单的做法是在/etc/modprobe.d/blacklist-rtl8xxxu.conf里写blacklist rtl8xxxu,然后update-initramfs -u更新。

5. 装完之后:监听模式、接口命名与日常维护

5.1 开启监听模式验证驱动完整性

驱动装好只是第一步,真正验证它是否“完整”的方法是看能不能进监听模式。普通上网对驱动要求很低,但监听模式需要驱动正确实现cfg80211相关回调。命令很简单:

sudo ip link set wlan0 down sudo iwconfig wlan0 mode monitor sudo ip link set wlan0 up iwconfig wlan0

如果Mode显示为Monitor,说明驱动支持监听。如果报SET failed on device wlan0 ; Operation not supported,那多半是内核自带驱动在起作用,或者编译时没启用监听相关宏。8811CU 官方驱动默认是支持监听的,所以出现这个错误优先怀疑驱动没装对。

5.2 接口名不叫 wlan0 怎么办

新版 Kali 和树莓派系统默认启用了可预测网络接口命名(Predictable Network Interface Names),USB 无线网卡的接口名可能变成wlx00e04cxxxxxx这种带 MAC 地址的长名字。这本身不影响使用,但很多教程和脚本里写死了wlan0,对不上就会出错。

有两个处理方式:一是临时用ip link查到实际名字,后续命令替换;二是永久改回wlan0,通过创建 udev 规则:

sudo tee /etc/udev/rules.d/70-wifi-name.rules <<EOF SUBSYSTEM=="net", ACTION=="add", ATTR{address}=="你的网卡MAC", NAME="wlan0" EOF

MAC 地址用ip link查,注意大小写要和规则里一致。改完重启或者udevadm trigger生效。

5.3 内核升级后的自动重编译验证

用了 DKMS 之后,内核升级时模块会自动重编译,但“自动”不等于“一定成功”。我建议每次apt upgrade涉及内核更新后,重启完手动确认一下:

dkms status

正常应该显示rtl8821cu/20210916, $(uname -r), x86_64: installed。如果显示built但没installed,说明编译过了但没装进当前内核,手动dkms install一下。如果显示broken,通常是新内核的 headers 还没装,装上再dkms autoinstall即可。

注意:树莓派上如果用了rpi-update升级到非稳定内核,DKMS 重编译失败的概率会明显升高。生产用途的树莓派建议只走apt的稳定内核更新,别追新。

6. 脚本的进阶改造与批量部署思路

6.1 加一个“卸载/重装”开关

脚本用久了会发现,有时候驱动出问题需要彻底清掉重来。手动删/usr/src下的目录、dkms remove、modprobe -r一套下来很繁琐。我在脚本里加了个参数开关:

if [ "$1" == "--clean" ]; then dkms remove -m rtl8821cu -v 20210916 --all || true rm -rf /usr/src/rtl8821cu-20210916 modprobe -r 8821cu || true echo "已清理,重新运行脚本即可重装" exit 0 fi

这样sudo ./install.sh --clean就能一键回到干净状态,再跑一次就是全新安装。对于反复调试的场景非常省事。

6.2 树莓派集群的批量分发

如果你手上有好几台树莓派要做同样的无线配置,一台台 SSH 上去跑脚本太慢。我的做法是把脚本放到一个内网 HTTP 服务上,然后用一条循环命令批量执行:

for ip in 192.168.1.101 192.168.1.102 192.168.1.103; do ssh pi@$ip "curl -s http://192.168.1.10/install.sh | sudo bash" done

前提是各台机器已经配好了 SSH 免密登录。这个思路同样适用于 Kali 虚拟机模板——把脚本塞进模板镜像,克隆出来的新虚拟机开机跑一次就行。

6.3 把驱动版本号做成变量

驱动仓库会更新,硬编码版本号以后维护起来麻烦。我把仓库地址、版本号、模块名都提到脚本顶部做成变量,升级时只改变量值:

DRIVER_VER="20210916" DRIVER_REPO="https://github.com/morrownr/8821cu-${DRIVER_VER}.git" MODULE_NAME="8821cu"

这样脚本的可维护性高很多,也方便你 fork 之后改成自己习惯的驱动源。

7. 一些零散但很关键的经验

最后分享几个我在实际使用中攒下来的小经验,都是文档里不太会写、但遇到时能救命的东西。

第一,编译前先make clean。有时候改了配置重新编译,旧的.o文件残留会导致链接出奇怪错误。DKMS 的CLEAN字段就是干这个的,手动编译时也别忘了。

第二,dmesg是你最好的朋友。驱动相关的绝大多数问题,dmesg | tail -50都能给出线索。固件加载失败、USB 断连、版本不匹配,日志里都有明确提示,比盲目搜索高效得多。

第三,别在监听模式下长时间高负载跑。8811CU 是 USB 接口,带宽和供电都有限,长时间监听加注入容易过热掉线。真要长时间跑,加个散热片或者小风扇,成本几块钱,稳定性提升明显。

第四,保留一份编译成功的驱动备份。把编译好的8821cu.ko和对应的dkms.conf打包存起来,万一哪天网络不通、仓库拉不下来,直接手动insmod也能应急。

这套流程我从 Kali 2022 一直用到现在的版本,树莓派从 3B+ 用到 5,中间除了内核大版本跳跃时需要更新一下驱动源,基本没出过什么大问题。脚本本身不复杂,核心就是把“装依赖、拉源码、配 DKMS、编译安装、验证”这几步串起来,再加上错误处理和清理开关。真正花时间的从来不是写脚本,而是搞清楚每一步为什么这么做、出错时往哪查。把这两点想明白了,以后换任何一块 Realtek 网卡,套路都是相通的。

返回列表