AX.25 HOWTO: packet radio and APRS on Linux with Dire Wolf
AX.25 is the link-layer protocol of amateur packet radio, and APRS (the position and messaging network) is built on it. On Linux in 2026 the usual set-up is a radio, a cheap USB sound interface and the Dire Wolf software TNC. The big change this year: the kernel's own AX.25 stack was removed from mainline Linux in version 7.1, so how you connect applications now depends on your kernel.
The classic AX25-HOWTO (2001), which covers NET/ROM, ROSE and the node software in depth, is kept by the Linux Documentation Project at tldp.org.
You need an amateur radio licence to transmit. Receiving and decoding is open to anyone, but every transmission, including automatic beacons and digipeating, must come from a licensed station using its own callsign. In the United States, Part 97 of the FCC rules applies: for example, you must identify at least every 10 minutes and at the end of a contact (47 CFR 97.119), and you may not send messages encoded to hide their meaning (47 CFR 97.113), so no encryption on the air. Other countries have similar rules; check your national regulator.
How the pieces fit
A TNC (terminal node controller) turns AX.25 frames into audio tones and back. Hardware TNCs still exist, but a sound card plus Dire Wolf does the same job in software. Applications talk to the TNC in one of three ways:
- KISS, a simple framing protocol, over a serial line, a pseudo-terminal or TCP (Dire Wolf's default TCP port is 8001).
- AGW, the network protocol of the old AGWPE program (default port 8000). Dire Wolf's own connected-mode AX.25 is reached through this interface.
- The kernel AX.25 stack:
kissattachturns a KISS port into a network interface (ax0), and programs fromax25-toolsandax25-appsuse AX.25 sockets.
The kernel AX.25 situation
In April 2026 the network maintainers removed the AX.25, NET/ROM and ROSE protocols and all hamradio drivers (mkiss, 6pack, bpqether, baycom, yam, scc) from the kernel tree. The commit says the code had long attracted a flood of bug reports and nobody had stepped up to help handle them; it moves the code to an out-of-tree repository, linux-netdev/mod-orphan, from which it can return if it is cleaned up. Linux 7.0 is the last release that contains it.
| Kernel | Kernel AX.25 | Examples |
|---|---|---|
| 7.0 and older | In the source tree (whether your distribution builds it is up to the distribution) | Debian 13 (6.12, which builds ax25 and mkiss as modules), Ubuntu 24.04 (6.8), Ubuntu 26.04 LTS (7.0), the 6.12 and 6.18 long-term kernels |
| 7.1 and newer | Gone; only with the out-of-tree modules | Fedora 43, 44 and 45 and Arch Linux (all on 7.2 kernels), the Debian 13 backports kernel (7.2), and every newer mainline or stable kernel |
Check your own system:
uname -r
modinfo ax25 mkiss 2>&1 | grep -E '^(filename|modinfo)'
If modinfo finds both modules, the kernel route works. If not, either use applications that speak KISS or AGW over TCP directly (no kernel support needed), or build the out-of-tree modules. Their README says to build on the machine that will load them: make, sudo make install, sudo depmod -a. They must be rebuilt for every kernel update, and with Secure Boot they must be signed (see the Kernel HOWTO).
Set up Dire Wolf
Dire Wolf decodes and sends 300 baud AFSK (HF), 1200 baud AFSK (the usual VHF/UHF packet and APRS speed), 2400/4800 PSK and 9600 baud G3RUH, adds FX.25 forward error correction, and can act as an APRS digipeater and Internet gateway (IGate). As of November 2026 the current release is 1.8.1 (November 2025); Debian 13 packages 1.7, and 1.8.1 is in trixie-backports. The project notes that distribution packages lag behind.
sudo apt install direwolf # Debian, Ubuntu
arecord -l # find the card number of your USB sound interface
aplay -l
Dire Wolf reads direwolf.conf from the current directory, then from your home directory, or from the file given with -c. A minimal configuration for one 1200 baud channel on USB sound card 1, keying the radio through the CM108 chip's GPIO (common on radio interface boards):
# ~/direwolf.conf
ADEVICE plughw:1,0
CHANNEL 0
MYCALL N0CALL-10
MODEM 1200
PTT CM108
AGWPORT 8000
KISSPORT 8001
Replace N0CALL-10 with your own callsign and an SSID (1 to 15). Other PTT choices are a serial control line (PTT /dev/ttyUSB0 RTS) and a GPIO line (PTT GPIOD 0 25, chip and line number). Start it in a terminal so you can watch the decoded traffic:
direwolf -c ~/direwolf.conf
It reports the audio device in use, then "Ready to accept AGW client application 0 on port 8000" and the same for KISS on port 8001. Tune the radio to a busy packet or APRS frequency and decoded frames should scroll past. If you see nothing, the audio level is the usual cause: Dire Wolf prints the received level, and its User Guide and Radio Interface Guide explain how to set it.
Network ports. Dire Wolf's guide suggests disabling the AGW or KISS port (set it to 0) on systems exposed to the Internet. Otherwise firewall ports 8000 and 8001 so that only your own machines can reach them, since anything connecting there can transmit under your callsign.
APRS without any kernel support
For APRS you do not need kernel AX.25 at all. Dire Wolf can beacon your position (PBEACON), digipeat (DIGIPEAT 0 0 ^WIDE1-1$ ^WIDE1-1$ for a simple fill-in digipeater) and gate traffic to the APRS-IS Internet network (IGSERVER and IGLOGIN), all from its configuration file. Mapping programs such as Xastir connect to its AGW or KISS TCP port. Read the APRS sections of the User Guide before you enable digipeating; badly chosen paths flood the channel for everyone.
Connect Dire Wolf to kernel AX.25
On a kernel that still has AX.25 (7.0 or older, or with the out-of-tree modules), install the tools and describe the port in /etc/ax25/axports:
sudo apt install ax25-tools ax25-apps
# /etc/ax25/axports
# name callsign speed paclen window description
radio N0CALL-10 1200 255 2 Dire Wolf 1200 baud
Remove blank lines from axports; the Dire Wolf guide warns that they cause trouble. Start Dire Wolf with -p, which creates a KISS pseudo-terminal and the link /tmp/kisstnc, then attach it. kissattach wants the real device, not the symbolic link:
direwolf -p -c ~/direwolf.conf &
sudo kissattach "$(readlink -f /tmp/kisstnc)" radio
ip link show ax0
Now the AX.25 programs work with the port name from axports:
sudo axlisten -a -c # monitor all frames, in color
axcall radio N0CALL-1 # connect to a station or BBS; ~. to disconnect
sudo beacon -s radio "Test from N0CALL-10" # send one beacon frame
The Dire Wolf guide notes that the pseudo-terminal can stall if nothing reads from it, and prefers the network ports where an application supports them. Also, if you give the ax0 interface an IP address, programs that broadcast on every interface (Samba, Avahi and others) will start transmitting over the radio. Bind those services to specific interfaces or filter ax0 with your firewall.
Common mistakes
- Audio too loud or too quiet. Most decoding failures are level problems, not software bugs.
- Transmitter stuck on or never keying: wrong
PTTmethod or line. Test with a dummy load before going on the air. - Same callsign and SSID on two stations: each running station needs its own SSID.
- Expecting kernel AX.25 on a new kernel: on Linux 7.1 and newer,
kissattachfails because the modules are missing. - Exposing the KISS/AGW ports to the network without a firewall.
Sources
- net: remove ax25 and amateur radio (hamradio) subsystem, Linux kernel commit (April 2026)
- mod-orphan: out-of-tree AX.25, NET/ROM, ROSE and hamradio modules
- kernel.org current releases
- Kernel versions in distributions: Fedora Packages, Arch Linux and Debian sources (including trixie-backports)
- direwolf in Debian 13 backports
- Ubuntu 26.04 LTS ships with the 7.0 kernel, Ubuntu Discourse
- Dire Wolf software TNC, project page
- Dire Wolf releases
- Dire Wolf User Guide (version 1.8)
- direwolf(1), Debian 13
- kissattach(8), Debian 13
- axports(5), Debian 13
- axcall(1), Debian 13
- axlisten(1), Debian 13
- beacon(8), Debian 13
- Linux AX.25 tools and libraries (LinuxHam wiki)
- 47 CFR 97.113, prohibited transmissions
- 47 CFR 97.119, station identification
- Linux Amateur Radio AX.25 HOWTO (classic), Linux Documentation Project