ampr-ripd and Amprnet Net-44 notes for a

Two Interface Debian Linux Amprnet Gateway

First some history:

In early 2012, Heikki Hannikainen, OH7LZB (the ham behind modernized the amprnet routing by writing a custom RIPv2 daemon to receive RIP updates from the 44/8 routing service, and insert them in the Linux routing table.  This has replaced the encap.txt and munge script method.

In late 2012 a new unified interface was given to  

To clarify the rip announcer at UCSD is one-way so the gateways robot is still there so that hams can create/define gateways that RIP packets will be directed to.  The rip packets are sent encapsulated from

For inbound IPIP/IPENCAP encapsulation and the RIP packets to reach your gateway you'll need to forward protocol 4 (IPIP) to your gateway server.  Most consumer grade router/gateways and modems will lack a direct way to specify this via the GUI.  If nothing else; if you ssh/telnet into your router can can specify it there.  Or it may just be easier to enable the DMZ and point it to your ampr gateway.  If its your first time with new customer premise equipment, or first time trying to set up a gateway I suggest;  connect something directly to your cable or DSL modem.  And enable DMZ to its address.  Or bridge mode if that fails.  And then run the tcpdump command.  Once you know your modem is passing the traffic from UCSD, then you can work out to more complex setups. 

Just to make it clear, IPENCAP (4) is a Layer 4 IP protocol, like ICMP (1), TCP (6), UDP (17), GRE(47), OSPF(89), AXIP (93) and a lot of others, with the difference that it transports another L3 protocol (IP).  It works on top of IP, which is the Layer 3 protocol on the internet. And there are other L3 protocols, like ARP, IPv6, AppleTalk DDP, IPX, IPSEC and others. IPENCAP has no port numbers. Those are specific for TCP and UDP, and that's it. You can not "simulate" it by port numbers.

Heikki wrote the original daemon in the Perl programming language.  Later Marius, YO2LOJ, wrote a ampr-ripd dameon in C.  

Here are some notes using Ubuntu Server 10.04.4 LTS,  but also confirmed to work on Debian Wheezy & Jessie. In these notes, using the gateways portal we have specified that subnet can be reached by gateway  We use Marius YO2LOJ's ampr-ripd dameon (v 1.13)  (Note: worst case is a two hour wait from the time you first create a gateway in the portal to the time you start receiving route information)


eth0 directly connected to the internet ( WAN
eth1 faces the wireless LAN (
tunl0 is the IPIP wormhole tunnel to the rest of the AMPRNet (
tun0 is for the optional OpenVPN server.

Wireless hosts use these routes to reach each other and the rest of the amprnet::

route add netmask  dev eth0
route add netmask gw dev eth0
You can use these notes as a basis for your setup, but you'll need to make changes accordingly.

I have successfully installed this on a low power, cheap Raspberry Pi and added a USB network adapter.


Debian drives me insane, I suggest making a root account so you don't go mad:

sudo passwd root

Or at the very least switch to root:

sudo -i

Install the tools and dependencies you'll need:

apt-get install tcpdump dnsutils iptables-persistant ipset fail2ban lynx

Enable IP forwarding and/or edit in /etc/sysctl.conf:

echo 1 > /proc/sys/net/ipv4/ip_forward

If you run a firewall, ensure IPIP protocol 4 is allowed:

iptables -A INPUT -p 4 -j ACCEPT
iptables -A INPUT -p udp --dport 520 -j ACCEPT
Or if you are behind NAT, something like (where is your gateway):
#iptables -t nat -A PREROUTING -p 4 -j DNAT --to
iptables -t nat -A WANPREROUTING -p 4  -j DNAT --to-destination
iptables -A wanin  -p 4 -d -j ACCEPT

To reduce traffic, drop neighbor discovery and SMB as well as MikroTik Neighbor Discovery Protocol on tunl0 (optional, but a good idea):

iptables -A OUTPUT -o tunl0 -p udp --dport 10001 -j DROP
iptables -A OUTPUT -o tunl0 -p udp --dport 137:139 -j DROP
iptables -A OUTPUT -o tunl0 -p udp --dport 5678 -j DROP 
# Drops destination unreachable replies to various probe responses saving bandwidth
iptables -A OUTPUT -o tunl0 -p icmp --icmp-type destination-unreachable -j DROP
Other highly recommended good practice rules:
# This prevents nested ipencap
iptables -t raw -I PREROUTING -p 4 -i tunl0 -j DROP
# This prevents a general loop
iptables -I FORWARD -i tunl0 -o tunl0 -j DROP
# Drops outbound unassigned IPs from looping though tunl0 via ipencap
# You Must add accept rules under this line to make exceptions
iptables -I FORWARD ! -s -o tunl0 -j DROP

Create a tunnel interface (this should reflect the ampr IP address of your gateway) :

ifconfig tunl0 up netmask
Download the latest daemon,  untar it, compile it, and copy it to a proper location (/usr/sbin)
tar -xvzf  ampr-ripd-xxx.tgz
cd ampr-ripd-*
cp ampr-ripd /usr/sbin
mkdir /var/lib/ampr-ripd

Run it for the first time:

Run it first with the -d -i tunl0 option to verify that it sees the route announcements from amprgw, and to learn the plaintext password used to authenticate the RIP packets (it's not included in the script, and I'm not posting it here, so that spoofing can only be done by those who are already receiving the announcements). Wait up to 5 minutes until the routes are transmitted, and it'll complain about the password it's not expecting.  (Note if you just submitted/changed your gateway in the portal, those updates are only loaded every hour):

root@hsmm-gw:~# ./ampr-ripd -d -i tunl0
found local address:
found local address:
found local address:
found local address:
opening UDP socket...
entering main loop, waiting for RIPv2 datagrams
received from 520: 504 bytes
RIPv2 packet contains password PasswordFoundHere but we require none


Configure it all to start at boot:

Set up your system so the startup script should be run automatically, e.g. call it in /etc/rc.local.

My full startup script:

Explanation of the above startampr script:

You may see things that you may not have encountered before.  Like route tables and route priorities.  This is policy routing.  It's fairly common in VLAN environments.  It gives us great deal of flexibility in how we direct traffic in and out of a Linux host.  

We need a default route for tunnel traffic that uses one interface, but a different default route for your separate management network that uses its own interface. This is why people in the outside world would use policy routing in this configuration. Using source routing (i.e., policy routing based on the source of the traffic), you could easily define a table for tunnel traffic that has its own default route while still allowing management traffic to use the hostís default routing table.

Since we route different for traffic coming from the general internet compared to that coming from other IPIP hosts, and from our own local networks this becomes essential.

The two key switches are "route" and "rule", and they do exactly what they sound like; one manages routes and route-tables, while the other manages the ruleset in which these routes/tables are called upon. Linux begins with a main route table and a default ruleset in which that table is used. Typically you don't even notice this as it's created with the configuration of the standard network devices upon boot. Two rules will be applied for this main route table: 1) main  2) default  The rules are such that the priority to these tables is so low almost any other rule will take priority over it. That's what makes amprnet routing for Linux quite simple.

The rule you want to make for amprnet is such that any inbound OR outbound routing sourced as 44-net uses it's own route table, with a priority higher than the main table rule. As long as the routes are in this matched table, the kernel will act as an amprnet router just fine even to entities such as xNOS, Xnet, etc. So if you want proper packet flow make sure all paths and rules match for the source you wish to route - in our case it's 44/8.

Your system has usually 3 preexisting routing tables, 'local' (255),'main' (254) and 'default' (253).

Usually, regular routes go to the table 'main', the table 'local' holds local interface IPs and broadcast routes, and the table 'default' is empty, and holds last resort routes.

The specific 44 routes could go to table main, but for easier management, most people choose separate routing table for those, in this case it is number 44.

For the system to use table 44 for its decision on routing ampr traffic, a rule has to be set to specify to use another table than 'main'.

This is done by 'ip rule add to table 44', meaning 'all packets with destination 44/8 will use table 44'

So, it will hold all '44.x.x.x/n via GW_Address dev tunl0' routes. To have a specific default route for 44 packets, something like '44/8 via something' has to be added.

A specific default destination via your public interface should be added to table 44 if the IP falls through without finding any matching subnet.

The stuff described up to this point, ensures IPIP tunnel and regular internet routing.

To be able to accept incoming connections from the internet, another step has to be taken, usually using another table (e.g. 'default' which is empty).

To understand this, remember that internet to 44/8 will come through the default UCSD tunnel (where you get your RIP broadcasts, too), from a public IP to your 44 address. Responses to these requests have to go back to the  same tunnel.

For this, we need a default route to ucsd in that separate table:
'ip route add default via dev tunl0 onlink table default'
And create our rule:
'ip rule add from (your ip/range) table default'
combined with the next rule:
'ip rule add from (your ip/range) to table 44'

Take care that the rules are applied by priority, the newest added rule having precedence. So the order is important.

Rules can be shown with 'ip rule list', the number shown being the priority, the lower the number, the higher the priority.

This gives the following behavior:
- packets to from your 44 sources to 44/8 destinations will go via table 44
(directly to peers via IPIP)
- on non match they (should) go to the default public IP interface
- packets to from your 44 sources to non-44/8 destinations will go via table
'default' (and to ucsd via IPIP to their internet peers)

All other routing should be done in table 'main', e.g. for LAN and non 44net traffic.

Contrary to routes, rules get not erased when bringing down an interface, so they must be explicitly deleted or set only once on system startup. Take care if restarting the interfaces by script.

I hope this explains some of the cryptic stuff.
Marius, YO2LOJ

These are handy for troubleshooting:

tcpdump -i eth0 -vvv host or ip proto \\icmp
tcpdump -vvv -s0 -n proto ipencap
tcpdump not arp and not rarp and not port ssh and not port domain and not port bootps and not port netbios-dgm and not port ssdp
For traceroute to work over IPIP one must adjust the TTL:
#gives tunnel its own TTL of 64 enabling traceroute over tunnel
ip tunnel change ttl 64 mode ipip tunl0
ip link set dev tunl0 up
#Or you can try to set the TTL at tunnel creation:
ip tun add tunl0 mode ipip ttl 64 local <your_local_ip>

Adding the second network interface:

I recommend a USB 2.0 to LAN RJ45 Ethernet Network Adapter for Apple Mac MacBook Air PC OS.  These are those popular white dongles with Windows 98/2000/Vista/XP/CE as well as Linux, MacOS and Android support.

Plug into the USB port and look for it with:

root@hsmm-gw:~# dmesg | grep eth
[173882.287625] eth1: register 'asix' at usb-0000:00:1d.7-7, ASIX AX88772 USB 2.0 Ethernet, 00:0e:c6:f0:3e:83
Note the MAC address and assigned interface name.   You'll add/relect some files to the mac and device name detected/assigned above.
On Debian systems, network interface configuration is placed in /etc/network/interfaces.  
On Red Hat systems you configure the interfaces then you add your routing.  Both are placed in /etc/sysconfig/network-scripts/
On Debian edit/add: (/etc/network/interfaces)
auto eth1
iface eth1 inet static
hardware 00:0e:c6:f0:3e:83
up ip route add via

On Red Hat create: (/etc/sysconfig/network-scripts/ifcfg-eth1)

On Red Hat create: /etc/sysconfig/network-scripts/route-eth1 via dev eth1
root@hsmm-gw:~# ifconfig
eth0      Link encap:Ethernet  HWaddr d0:27:88:62:f4:6c
          inet addr:  Bcast:  Mask:
          inet6 addr: fe80::d227:88ff:fe62:f46c/64 Scope:Link
          RX packets:24689 errors:0 dropped:0 overruns:0 frame:0
          TX packets:520 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:1587407 (1.5 MB)  TX bytes:63859 (63.8 KB)
          Interrupt:26 Base address:0x8000

eth1      Link encap:Ethernet  HWaddr 00:a0:cc:c0:11:20
          inet addr:  Bcast:  Mask:
          inet6 addr: fe80::2a0:ccff:fec0:1120/64 Scope:Link
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:6 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:0 (0.0 B)  TX bytes:480 (480.0 B)

lo        Link encap:Local Loopback
          inet addr:  Mask:
          inet6 addr: ::1/128 Scope:Host
          UP LOOPBACK RUNNING  MTU:16436  Metric:1
          RX packets:14 errors:0 dropped:0 overruns:0 frame:0
          TX packets:14 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0
          RX bytes:1424 (1.4 KB)  TX bytes:1424 (1.4 KB)
tun0      Link encap:UNSPEC  HWaddr 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00
          inet addr:  P-t-P:  Mask:
          RX packets:31 errors:0 dropped:0 overruns:0 frame:0
          TX packets:47 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:100
          RX bytes:1356 (1.3 KiB)  TX bytes:11581 (11.3 KiB)

tunl0     Link encap:IPIP Tunnel  HWaddr
          inet addr:  Mask:
          UP RUNNING NOARP MULTICAST  MTU:1480  Metric:1
          RX packets:49 errors:0 dropped:0 overruns:0 frame:0
          TX packets:23 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0
          RX bytes:14584 (14.5 KB)  TX bytes:12334 (12.3 KB)
I found this was needed on the IP/IP/OpenVPN server to get data to flow between eth1 and tun0 (OpenVPN):
iptables -t nat -A POSTROUTING -s -d -j MASQUERADE
Needed to allow local wireless LAN user access to the internet:
iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE

root@hsmm-gw:~# ip route show table 44
....    ip-74-85.192.mi   UG    0      0        0 tunl0      radio.augsburg.   UG    0      0        0 tunl0   UG    0      0        0 tunl0      *        U     0      0        0 eth1
...    reverse.133.61.   UG    0      0        0 tunl0    corley.roglab.p   UG    0      0        0 tunl0   *        U     0      0        0 eth0   UG    0      0        0 tunl0      db0fhn.efi.fh-n     UG    0      0        0 tunl0
....        *            U     0      0        0 tunl0
default         cpe-174-103-224         UG    100    0        0 eth0

[kb9mwr@kb9mwr ampr]$ host has address

[root@kb9mwr ~]# ping
PING ( 56(84) bytes of data.
64 bytes from ( icmp_seq=1 ttl=42 time=235 ms
64 bytes from ( icmp_seq=2 ttl=42 time=239 ms
64 bytes from ( icmp_seq=3 ttl=42 time=239 ms
64 bytes from ( icmp_seq=4 ttl=42 time=238 ms

[root@kb9mwr ~]# traceroute
traceroute to (, 30 hops max, 40 byte packets
 1  router.localdomain (  0.191 ms  0.170 ms  0.154 ms
 2 (  7.009 ms  10.468 ms  10.401 ms
 3 (  11.152 ms  11.144 ms  11.130 ms
 4 (  12.052 ms  12.049 ms  12.018 ms
 5 (  17.532 ms  17.550 ms  17.518 ms
 6 (  12.049 ms  12.028 ms  12.040 ms
 7 (  20.337 ms  17.266 ms  18.033 ms
 8 (  20.398 ms  17.965 ms  20.069 ms
 9 (  21.883 ms (  21.781 ms (  21.828 ms
10 (  21.972 ms  21.963 ms  21.969 ms
11 (  74.427 ms  74.449 ms  74.478 ms
12 (  83.576 ms  83.443 ms 83.513 ms
13 (  84.244 ms  84.194 ms  84.169 ms
14 (  78.299 ms  80.359 ms  80.639 ms
15 (  87.980 ms  87.858 ms  91.943 ms
16 (  92.941 ms  89.077 ms  88.924 ms
17 (  90.805 ms  89.957 ms  92.641 ms
18 (  99.255 ms  99.246 ms  99.258 ms
19 (  99.240 ms  96.693 ms  97.809 ms
20 (  95.547 ms  98.140 ms  98.116 ms
21 (  98.228 ms  98.098 ms  98.221 ms
22 (  98.019 ms * *
23 (  236.116 ms  240.000 ms  236.073 ms address DNS mapping defined in the ampr DNS robot.
44.92.21/24 Gateway is defined at the robot

Network dump of Incoming RIP
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 96 bytes
04:00:00.218059 IP > RIPv2, Response, length: 504
04:00:00.218108 IP > ICMP udp port 57644 unreachable, length 540
04:00:00.218121 IP > IP > RIPv2, Response, length: 504 (ipip-proto-4)
04:00:00.218130 IP > RIPv2, Response, length: 504
04:00:00.218141 IP > ICMP udp port 57644 unreachable, length 540
04:00:00.218262 IP > IP > RIPv2, Response, length: 504 (ipip-proto-4)
04:00:00.218550 IP > RIPv2, Response, length: 504
04:00:00.218573 IP > ICMP udp port 57644 unreachable, length 540
04:00:00.218582 IP > IP > RIPv2, Response, length: 504
Some firewall files that might come in handy:
# Block all non 44 incoming traffic
iptables -A INPUT ! -s -i tun0 -j DROP
# Block all non 44 hosts from incoming SMTP
iptables -A INPUT -p tcp --dport 25 -s ! -j DROP
# Logging Pings
iptables -I OUTPUT -o tunl0 -p icmp -j LOG --log-prefix 'Ping: ' -m limit --limit 2/min
# This will log to default kernel logging location, typically /var/log/messages

Good test hosts only reachable via IPIP are: (run by KB3VWG) and (

Here is how to setup the optional OpenVPN server.  This will allow you (and anyone you share your keys with) to remotely connect in and get on with a 44 address. 

Theory and background:

If your openvpn server is behind a firewall, you'll need to open/forward the default port of 1194 UDP.  Obviously the client(s) needs no firewall modifications.  The client creates and maintains an active (stateful) connection to the server at all times. This allows the server to track a reverse way back to the client.  (Handshakes are about every 5 seconds, yet it only amounts to about 14 MB per month for an idle connection per client)

The following are my install notes for OpenVPN 2.2.1 on a Debian Linux system.


Install openvpn and it's dependencies.

apt-get install openvpn openssl

After the install finishes, you need to generate keys for the server and the client(s). OpenVPN ships with the 'easy-rsa'-tool. It's easiest to copy the example folder and work from there.

cp -R /usr/share/doc/openvpn/examples/easy-rsa /etc/openvpn
cd /etc/openvpn/easy-rsa/2.0

The 'easy-rsa'-tool has a file called 'vars' that you can edit to set some defaults. That will save you time later on but it's not required to do so.

Load the vars like this (note the two dots):

. ./vars

Then we need to generate keys:

./build-key-server server
./build-key client1

The first line makes sure we start from scratch. The second generates a key for the Certificate Authority (ca.crt and ca.key). The key for the server itself is generated on the third line (server.crt, server.key, and server.csr) . Repeat the forth line for each client that needs to connect (client1.key, client1.csr, client.crt, etc). Finally, we need the Diffie Hellman key as well, which is generated on the fifth line (dh1024.pem).

When creating the keys and certificates most parameters can be left to their default values. The only parameter which must be explicitly entered is the Common Name. So for each client, make sure to type the appropriate Common Name when prompted, i.e. "client1", "client2", or "client3". Always use a unique common name for each client.

kb9mwr:easy-rsa # ./build-ca
Generating a 1024 bit RSA private key
writing new private key to 'ca.key'
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
Country Name (2 letter code) [KG]:
State or Province Name (full name) [NA]:
Locality Name (eg, city) [BISHKEK]:
Organization Name (eg, company) [OpenVPN-TEST]:
Organizational Unit Name (eg, section) []:
Common Name (eg, your name or your server's hostname) []:OpenVPN-CA
Email Address [[email protected]]:

We need to copy the keys to the OpenVPN folder.  (You'll need to copy ca.crt, ca.key, client1.crt, client1.csr, client1.key that you generated on the server to your client(s))

cd /etc/openvpn/easy-rsa/2.0/keys
cp ca.crt ca.key dh1024.pem server.crt server.key /etc/openvpn

Last step is to configure the server. You can copy the example config and make sure it points to the certs you just created.  (Example client config: /usr/share/doc/openvpn/examples/sample-config-files/client.conf)

cp /usr/share/doc/openvpn*/examples/sample-config-files/server.conf.gz /etc/openvpn
gunzip /etc/openvpn/server.conf.gz
vim /etc/openvpn/server.conf

When you're done, start OpenVPN like this:

/etc/init.d/openvpn start

On a Centos 5.x machine you start it a bit different, as you must specify path to a config:

openvpn /etc/openvpn/client.conf

port 1194
proto udp
dev tun
ca ca.crt
cert server.crt
key server.key
dh dh1024.pem
ifconfig-pool-persist ipp.txt
push "route"
keepalive 10 120
status openvpn-status.log
verb 3
Further help can be obtained on the 44net mailing list.

Go back to the TCP/IP page.

Go to the WAPR Home Page and index