< All posts | Fediverse | RSS | GitHub | Talks

Jul 22 2017

IP over AX.25 over 802.11 with ESP8266

I love obscure protocols, and while most of the world’s legacy X.25 equipment is slowly being shut down. It’s amateur radio derivative AX.25 is getting along pretty well with a reasonable amount of AX.25 traffic happening in the UK every single day:

A view from aprs.fi, highlighting hotspots of AX.25 activity A view from aprs.fi, highlighting hotspots of AX.25 activity

The majority of this traffic however is either weather or location updates, but this is not all of the protocol can do inside it is also the ability to carry IP packets. Linux itself has had the ability to send and manage AX.25 packets for quite a while, either using the concept of a sound modem using the concept of a sound modem, or using a device called a TNC to modulate and encode APRS packets.

To my surprise it was possible on a modern Ubuntu 17.10 linux install to get ax.25 abilities to work painlessly, a simple sudo apt install ax25-tools was needed to get the basic utilities and I was good to go.

However I don’t have a amateur radio license ( though I should probably get one ) and so I don’t have a TNC nor can I transmit on the bands that APRS uses. However, that won’t stop me!


Here is where the small, tiny and very cheap (3.5$ each for the units pictured) “Internet of things” device comes into the picture. These devices have the ability to do raw frame transmission, and they also have promiscuous mode that allows you to “sniff” raw 802.11 packets on a WiFi channel.

The protocol I decided to implement was called KISS. ( Keep It Simple Stupid )

In fact the protocol is very simple, It has 4 special signalling characters but 3 of them be used to escape the 1st ( the end of packet character )

I wrote up a small TNC that actually uses 802.11 as a transport for frames to order to play around with AX.25 networking, You can find the code and instructions to build on my GitHub: https://github.com/benjojo/kiss_esp

There are a few unfortunate downside however, The packet size MTU of this makeshift TNC is limited to around 89 bytes do to the ESP’s SDK being limited to sniffing the first 128 bytes of a 802.11 frame, You should improve this later on to implement fragmentation, but unless you add another tunnel on top, TCP is not going to work.

With both “TNC”’s running and ready to go, we need to setup both machines with call sign’s. Now if I had a real license, I would have a real call sign, in this case I don’t so I will be making some up for both machines. You need to define these in /etc/ax25/axports like so:

# /etc/ax25/axports
# The format of this file is:
# name callsign speed paclen window description

#1	OH2BNS-1	1200	255	2	144.675 MHz (1200  bps)
#2	OH2BNS-9	38400	255	7	TNOS/Linux  (38400 bps)
aprs	K5DAT-10	57600	256	7	ESP APRS (57600 bps)

Now you can run kissattach to bring up the interface:

sudo kissattach /dev/ttyUSB0 aprs

after that the interface ax0 should exist

ben@metropolis:~$ sudo ifconfig
ax0: flags=67<UP,BROADCAST,RUNNING>  mtu 256
        inet  netmask  broadcast
        ax25 K5DAT-10  txqueuelen 10  (AMPR AX.25)
        RX packets 5  bytes 418 (418.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 12  bytes 1434 (1.4 KB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

You should also add a routing entry for the whole block, Since that is a whole /8 block of IP addresses that are reserved for amateur packet radio systems.

sudo route add -net netmask dev ax0

At this point, the link should come up just fine, You should be able to exchange ( small ) pings between the two systems connected:

ben@metropolis:~$ ping -s 40
PING ( 40(68) bytes of data.
48 bytes from icmp_seq=1 ttl=64 time=221 ms
48 bytes from icmp_seq=2 ttl=64 time=219 ms
48 bytes from icmp_seq=3 ttl=64 time=221 ms
--- ping statistics ---
4 packets transmitted, 3 received, 25% packet loss, time 3003ms
rtt min/avg/max/mdev = 219.950/220.962/221.633/0.728 ms

It’s worth pointing out that not all of the debugging tools you are used to (one example being tcpdump) are going to work with AX.25 links. However wireshark understands these links just fine and was a wonderful debugging tool while writing this:

wireshark showing ax.25 traffic

Perhaps that is understandable for a protocol that has been around for 1984 and sparsely used :)