How I Fixed the Alfa rtl88xxau Driver on Linux Kernel 6.15, 6.16 and 6.18
If you do wireless penetration testing on Kali Linux you have probably run into this at some point. You update your system, reboot, plug in your Alfa adapter and nothing works. Airodump-ng throws errors, wifite cannot find your interface and monitor mode is completely broken. That is exactly what happened to me and it took a while to figure out why.
The problem is not your adapter. The problem is that the Linux kernel keeps evolving and the open source rtl88xxau driver that powers most Alfa adapters has not kept up. Three separate kernel API changes across versions 6.15, 6.16 and 6.18 broke the driver source code in different ways. Unless you know exactly what changed and where, you are stuck staring at a wall of compiler errors with no obvious fix.
I went through the kernel changelogs, read the build errors line by line and figured out what needed to change. Then I wrote a bash script that automates the entire fix so you never have to do it manually.
Why the Driver Breaks
To understand what the script fixes you need to understand what broke. The rtl88xxau driver is built from source using DKMS, which means the kernel compiles it fresh every time you update. When the kernel changes internal APIs that the driver relies on, the compilation fails.
Kernel 6.15 made changes to the timer subsystem. Two functions that the driver used extensively were renamed. The old code in osdep_service_linux.h looked like this:
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 0))
_timer *ptimer = from_timer(ptimer, in_timer, timer);
#else
And the timer cancellation looked like this:
*bcancelled = del_timer_sync(&ptimer->timer) == 1 ? 1 : 0;
Kernel 6.15 removed both from_timer and del_timer_sync and replaced them with timer_container_of and timer_delete_sync. Simple renames but enough to completely break compilation.
Kernel 6.16 added a new parameter called radio_idx to several functions in the cfg80211 wireless subsystem. The cfg80211 layer is how wireless drivers communicate with the kernel networking stack. The affected function in ioctl_cfg80211.c originally looked like this:
static int cfg80211_rtw_set_wiphy_params(struct wiphy *wiphy, u32 changed)
Kernel 6.16 changed the expected signature to include radio_idx between the two existing parameters. Because the driver implemented the old signature the compiler rejected it as a mismatch.
Kernel 6.18 made a change to how the kernel build system handles compiler flags. Previously drivers could pass custom compiler flags through EXTRA_CFLAGS in their Makefile. Kernel 6.18 stopped reading that variable entirely and only recognizes ccflags-y. The rtl88xxau Makefile relied on EXTRA_CFLAGS for passing include paths and warning flags so under kernel 6.18 those flags were silently dropped and the build failed in confusing ways.
Three separate bugs across three kernel versions. None of them obvious unless you know where to look.
What the Script Does Step by Step
The script handles everything from start to finish. Here is exactly what happens when you run it.
The first thing it does is check whether your Alfa adapter is actually plugged in. It runs lsusb and looks for any Realtek USB device:
if lsusb | grep -qiE "realtek|0bda:"; then
info "Realtek USB adapter detected"
fi
Realtek's USB vendor ID is 0bda so this catches any adapter in the rtl88xxau family regardless of exact model. If it does not find one it prints a warning but continues anyway because you might be setting up the system before plugging in the adapter.
Next it installs all the build dependencies:
apt-get install -y \
build-essential \
libelf-dev \
python3 \
bc \
git \
curl \
dkms \
linux-headers-"$KERNEL"
This includes build-essential for the C compiler and build tools, libelf-dev which the kernel module build system needs, python3 for the patching step and most importantly linux-headers for your exact running kernel. The script fetches your kernel version automatically using uname -r and installs the matching headers package. Without the correct kernel headers the module simply cannot be compiled.
After dependencies are in place it cleans up any broken existing installation. It removes the old apt package, removes any DKMS managed versions and unloads the old kernel module if it is currently loaded:
apt-get remove -y realtek-rtl88xxau-dkms 2>/dev/null || true
dkms status 2>/dev/null | grep -i rtl88xxau | \
sed 's/[,: ].*//' | sort -u | \
while read -r mod; do dkms remove "$mod" --all 2>/dev/null || true; done
modprobe -r 88XXau 2>/dev/null || true
This ensures you are starting from a completely clean state without leftover files that could interfere with the new build.
Then it installs realtek-rtl88xxau-dkms fresh from apt purely to get the driver source code placed into /usr/src. The script will not use DKMS to build the module but uses apt as a convenient way to get the source files onto the system.
Once the source is located the embedded Python patcher runs and handles all three sets of patches automatically.
For the kernel 6.15 timer changes it patches osdep_service_linux.h so the code becomes version aware:
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(6, 15, 0))
_timer *ptimer = timer_container_of(ptimer, in_timer, timer);
#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 0))
_timer *ptimer = from_timer(ptimer, in_timer, timer);
#else
And for the timer cancellation:
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(6, 15, 0))
*bcancelled = timer_delete_sync(&ptimer->timer) == 1 ? 1 : 0;
#else
*bcancelled = del_timer_sync(&ptimer->timer) == 1 ? 1 : 0;
#endif
The same source code now compiles correctly across all kernel versions by checking the version at compile time.
For the kernel 6.16 cfg80211 changes it patches the three affected functions in ioctl_cfg80211.c. Each gets a version guard that includes radio_idx only when compiling against kernel 6.16 or newer:
static int cfg80211_rtw_set_wiphy_params(struct wiphy *wiphy,
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(6, 16, 0))
int radio_idx,
#endif
u32 changed)
This makes the function signature match exactly what the kernel expects regardless of which version you are running.
For the kernel 6.18 build system change the script takes a simpler approach. Instead of patching individual source files it appends a single line to the Makefile:
ccflags-y += $(EXTRA_CFLAGS)
This bridges the two variables together so anything set in EXTRA_CFLAGS automatically flows into ccflags-y as well. Clean, backwards compatible and works on every kernel version.
Before applying any patches the script backs up every file it touches:
[ -f "$_fp" ] && [ ! -f "${_fp}.bak" ] && cp "$_fp" "${_fp}.bak"
If something goes wrong you have the originals with a .bak extension right next to the modified files.
After patching the script builds the driver directly from source using make rather than going through DKMS:
make KVER="$KERNEL" -j"$(nproc)"
make KVER="$KERNEL" install
depmod -a "$KERNEL"
Building directly avoids path resolution issues that the DKMS build process has on newer kernels. The nproc flag uses all available CPU cores so the build finishes as fast as your machine allows. After installation depmod updates the module database so the kernel can find the new module.
The final step before loading the module is blacklisting the in-kernel rtw88 driver. Modern kernels ship with a built in Realtek driver but it has very limited monitor mode and packet injection support. The script creates a blacklist file at /etc/modprobe.d/blacklist-rtw88.conf:
blacklist rtw88_8812au
blacklist rtw88_8812au_common
blacklist rtw88_usb
blacklist rtw88_core
This prevents the rtw88 modules from loading and conflicting with the properly installed 88XXau driver. Finally the script loads the fresh module and checks for wireless interfaces so you can confirm everything worked.
Using It
The entire process runs with a single command:
curl -sL https://raw.githubusercontent.com/Ac3rN/realtek-rtl88xxau-auto-installer/main/install_alfa_driver.sh | sudo bash
Once it finishes you should see your wlan interface in the output. If the adapter was already plugged in it will be ready immediately. If not, replug it and it will show up. From there you can put it into monitor mode and start using it with your tools of choice:
sudo airmon-ng check kill
sudo airmon-ng start wlan0
sudo airodump-ng wlan0mon
The script has been tested on Kali Linux 2025 with kernels 6.15, 6.16 and 6.18. It supports the Alfa AWUS036ACH, AWUS036AC, AWUS1900 and any other adapter using the rtl88xxau driver family.
The full source code is available on GitHub at https://github.com/Ac3rN/realtek-rtl88xxau-auto-installer

Kommentarer
Skicka en kommentar