在 WSL2 Kali 中 编译 USB 无线网卡驱动

C. Qiu 于 2022-05-03 发布

在 WSL2 中使用 Kali 进行网络安全学习时,一个常见的需求就是利用外置 USB 无线网卡来执行扫描、监听等操作。然而,此事在 VMWare 等传统虚拟机中相对简单,在 WSL2 架构下却是一条漫长征途。

本文记录了从连接 USB 设备开始,到最终让 Kali 系统成功识别并加载 RTL8188CUS 无线网卡驱动的全过程,其中涉及了驱动编译、内核头文件准备、网络代理配置、以及各种意想不到的编译错误排查。

第一步:连接 USB 设备与第一个问题

WSL2 使用 usbipd-win 项目来实现 USB 设备的网络穿透。

  1. 在 Windows PowerShell (管理员) 中安装并配置 usbipd
    # 1. 安装
    winget install --interactive --exact dorssel.usbipd-win
    # 2. 列出 USB 设备,找到网卡的 BUSID
    usbipd wsl list
    # 3. 将设备附加到 WSL
    usbipd wsl attach --busid <你的BUSID> -d kali-linux
    
  2. 在 Kali 中安装客户端工具
    sudo apt update
    sudo apt install -y linux-tools-$(uname -r) hwdata
    sudo modprobe vhci-hcd
    

操作完成后,在 Kali 中运行 lsusb,可以清楚地看到我的 Realtek Semiconductor Corp. RTL8188CUS 网卡,证明 USB 设备本身已经成功“传递”给了 WSL。

但第一个问题出现了:运行 iwconfigip addr,没有出现 wlan0 无线接口。这说明 Kali 内核虽然识别了 USB 设备,但没有加载对应的驱动。

第二步:编译社区驱动

Kali 自带的 rtl8192cu 驱动对 RTL8188CUS 芯片的支持非常糟糕,特别是缺少监听模式。因此,必须手动编译社区维护的、功能更全的驱动。这里选用 aircrack-ng 团队维护的版本。

# 安装编译依赖
sudo apt install -y build-essential bc dkms git
# 拉黑自带的旧驱动
echo "blacklist rtl8192cu" | sudo tee /etc/modprobe.d/blacklist-rtl8192cu.conf
# 下载新驱动源码
git clone https://github.com/aircrack-ng/rtl8188eus.git
cd rtl8188eus
# 尝试用 dkms 安装
sudo ./dkms-install.sh

第三步:内核头文件的黑洞

执行安装后,马上遇到了第二个、也是最核心的问题:编译失败

失败的原因是找不到与当前 WSL2 内核版本匹配的 linux-headers

Error: Unable to locate package linux-headers-6.6.87.2-microsoft-standard-WSL2

原因(大概):WSL2 使用的是微软定制的 Linux 内核,其版本更新频繁,而 Kali 的官方源中并未提供这些特定版本的头文件包。

解决方案:既然无法 apt install,就只能从微软的 GitHub 仓库下载内核源码,并手动编译生成需要的头文件。

第四步:编译

4.1 配置代理访问 GitHub

由于众所周知的原因,直接在 WSL 中 git clone GitHub 仓库可能会失败。需要配置代理让 WSL 的流量走 Windows 宿主机。

  1. Windows 端:在代理工具(如 v2rayN)中,开启“允许来自局域网的连接”。
  2. Kali 端:
    # 1. 动态获取 Windows 主机的 IP 地址
    export HOST_IP=$(cat /etc/resolv.conf | grep nameserver | awk '{print $2}')
    # 2. 设置代理环境变量 (端口号需与代理工具一致)
    export http_proxy="http://${HOST_IP}:10809"
    export https_proxy="http://${HOST_IP}:10809"
    

    为了方便,可以将这几行命令写入 ~/.bashrc 文件中。

4.2 编译内核源码

这是整个过程中最复杂、极耗时的部分。

  1. 下载源码并切换到正确版本
    # 下载
    git clone https://github.com/microsoft/WSL2-Linux-Kernel.git
    cd WSL2-Linux-Kernel
    # 获取所有历史版本标签
    git fetch --all --tags
    

    坑1:直接 git checkout $(uname -r) 会失败,因为 uname -r 的输出 (6.6.87.2-microsoft-standard-WSL2) 和 Git 标签 (linux-msft-wsl-6.6.87.2) 并不完全匹配。需要手动 git checkout linux-msft-wsl-6.6.87.2

  2. 准备并生成内核编译配置

    坑2:直接 make 会失败,因为它找不到 .config 配置文件。正确的做法是先从微软提供的模板复制一份,再用 olddefconfig 自动更新它。

    # 复制模板为 .config
    cp Microsoft/config-wsl .config
    # 根据 .config 自动为新内核选项选择默认值
    make olddefconfig
    
  3. 完整编译内核

    坑3:仅仅 make modules_prepare 是不够的。驱动编译的后期链接阶段需要内核的完整符号表 Module.symvers,而这个文件只有在完整编译内核后才会生成。

    # 使用所有CPU核心进行完整编译,花费很长时间
    make -j$(nproc)
    

    等待编译完成后,ls -l Module.symvers 能看到生成的文件,说明最艰难的一步已经完成。

第五步:临门一脚

在内核源码万事俱备后,回到驱动目录,再次运行 sudo ./dkms-install.sh。这一次,编译过程顺利通过。

然而,重启 WSL、重新附加 USB 设备后,运行 iwconfig,依然没有 wlan0

通过 dkms statusmodprobe 命令进行诊断,发现了最终的问题:

# dkms status
8188eu/5.3.9, ...: installed (Differences between built and installed modules)

# modprobe 8188eu
modprobe: FATAL: Module 8188eu not found in directory /lib/modules/...

根本原因:DKMS 成功编译了驱动模块 8188eu.ko,但最后一步——将它从临时目录复制到系统模块目录 /lib/modules/.../updates/dkms/——因为某种原因失败了。

最终解决方案:手动复制

  1. 找到编译好的模块文件
    sudo find /var/lib/dkms -name "8188eu.ko"
    # 输出类似: /var/lib/dkms/8188eu/5.3.9/build/8188eu.ko
    
  2. 找到目标目录
    # 模块应该被放在这里
    ls /lib/modules/$(uname -r)/updates/dkms/
    
  3. 手动复制过去
    sudo cp /var/lib/dkms/8188eu/5.3.9/build/8188eu.ko /lib/modules/$(uname -r)/updates/dkms/
    
  4. 更新模块依赖关系
    sudo depmod -a
    
  5. 手动加载模块
    sudo modprobe 8188eu
    

    这个命令执行后,没有任何输出。此时,再次运行 iwconfig,终于看到了阔别已久的 wlan0 接口。

总结

为 WSL2 Kali 手动安装一个兼容性不佳的 USB 无线网卡驱动,几乎把内核编译和驱动安装过程中所有可能的坑都踩了一遍。过程虽然曲折,但完整折腾了一轮 Linux 内核、驱动编译、DKMS 工作原理以及 WSL2 网络和文件系统架构,希望能帮助遇到类似问题的朋友。