From: http://ohiopacket.org/index.php/Replacing_JNOS_with_Linux
Replacing JNOS with Linux
From Ohio Packet
When we think about packet radio and TCP/IP, most of us think of JNOS. The efforts of all current and past developers has given us a "swiss army knife" of packet programs. No other software package comes close to providing as many services as JNOS. The cost of offering so many options is the ability to have feature rich components. While no component of JNOS is bad, the prospect of being able choose what flavor of services can be an attractive one. This article is intended to a somewhat seasoned Linux veteran. It assumes you are capable of setting up LinuxNode and any other network daemons such as Postfix (SMTP), Apache (HTTP), etc. As time permits, we will try to add additional setup steps.
Out of the box, LinuxNode can support AXIP and AXUDP connections, support KISS type TNCs and can even be setup to accept telnet sessions (with help if (x)inetd). The other component of JNOS which is used heavily in our installations is the ability to encapsulate AMPRNet (44.x.x.x) traffic into normal IP frames. This is often used to bridge "pockets" of AMPRNet traffic across Internet links. Fortunately, Linux can natively handle this as well, but the documentation and examples we found seemed confusing. With a bit of research and some trial and error, we discovered that what takes one line in JNOS, takes 3 lines in Linux.
For those of you who subscribe to the AMPRNet robot provided by http://www.ampr-gateways.org, you are probably receiving encap.txt files in the format of
route addprivate 44.x.x.x/nn encap internet.ip.of.gateway
JNOS can happily accept this syntax, but Linux needs it to be broken apart into 3 steps.
# This creates the interface with the destination gateway. Only one of these is needed per gateway
ip tunnel add <interfacename> mode ipip remote internet.ip.of.gateway local local.ip.of.linux
# This sets the IP address on the interface. We've used the AMPRNet address. We will use 44.128.0.1 for this example.
ifconfig <interfacename> 44.128.0.1 netmask 255.255.255.255
# Lastly, we must create a route to the target AMPRNet host or
network via the newly created interface (which implies the gateway). We
will use 44.128.1.0/24 for this example.
route add 44.128.1.0/24 dev <interfacename>
The union of these 3 commands will produce the same IPIP encapsulation that JNOS uses. The next hurdle is how to convert the encap.txt to a format that will work within Linux. One solution is the following bash script. It will
1) Read the native formatted encap.txt and translate it into the Linux command set
2) Create a tunnel interface per remote gateway (starts with ampr0 and
adds additional per gateway) The limit of interface is not limited to
255, in our testing we've had 512 without any trouble.
3) Replace empty octets of the target IP address with zeros (required by route command)
4) Perform sanity checking for incorrect network addresses (some entries
in encap.txt don't have the correct network address for a given subnet,
if fed directly, the Linux route command will fail).
5) Remove any preexisting tunnels (if you kernel has the ipip compiled in a module)
6) It will error out if it encounters any issue with any command. This
is useful to ensure everything is running before it gets added to
crontab.
#!/bin/bash IPIPLOAD=$(lsmod | grep -c ipip) if [ ${IPIPLOAD} != "0" ]; then rmmod ipip fi modprobe ipip ENCAP=encap.txt LOCALENCAP=$(/sbin/ifconfig eth0) LOCALAMPR=44.128.0.1 ENCAPGW=$(cat $ENCAP | grep -v '#' | awk '{print $5}' | sort | uniq) for gw in $ENCAPGW do
AMPRIFCHK=$(/sbin/ifconfig | grep -c ampr) # This will assign the next available interface, we're calling these amprN if [ ${AMPRIFCHK} = "0" ] then DEVICE=ampr0 else DEVNUMBER=$(expr $(/sbin/ifconfig | grep ampr | awk '{print $1}' | tail -n 1 | sed s/'ampr'//g) + 1) DEVICE=ampr${DEVNUMBER} fi
iptunnel add $DEVICE mode ipip remote $gw local $LOCALENCAP RETVAL=$? if [ ${RETVAL} != "0" ]; then exit 1 fi ifconfig $DEVICE $LOCALAMPR netmask 255.255.255.255
RETVAL=$? if [ ${RETVAL} != "0" ]; then exit 1 fi
for net in $(cat $ENCAP | grep $gw | awk '{print $3}') do
# We need to omit -net to route when it is a host record (CIDR = 32) # If no CIDR is specified, host is assumed, set CIDR to 32
CIDR=$(echo $net | awk -F '/' '{print $2}') if [ -z $CIDR ]; then CIDR=32 fi
# We need a host route if [ ${CIDR} = "32" ] then route add $net dev $DEVICE
RETVAL=$? if [ ${RETVAL} != "0" ]; then exit 1 fi
else # We need a network route OCTET1=$(echo $net | awk -F '.' '{print $1}' | awk -F '/' '{print $1}') OCTET2=$(echo $net | awk -F '.' '{print $2}' | awk -F '/' '{print $1}') OCTET3=$(echo $net | awk -F '.' '{print $3}' | awk -F '/' '{print $1}') OCTET4=$(echo $net | awk -F '.' '{print $4}' | awk -F '/' '{print $1}')
# Check to see if octets are empty, if they are, insert 0 if [ -z $OCTET1 ]; then OCTET1=0 fi
if [ -z $OCTET2 ]; then OCTET2=0 fi
if [ -z $OCTET3 ]; then OCTET3=0 fi
if [ -z $OCTET4 ]; then OCTET4=0 fi
net="${OCTET1}.${OCTET2}.${OCTET3}.${OCTET4}/${CIDR}"
# In some cases, the target network has an incorrect network number # This causes the route addition to fail. # # Fortunately, ipcalc can handle the calculation of the correct network # Just to be safe, we will pass all networks through ipcalc to verify # their accuracy. # NETSCRUB=$net
net=$(ipcalc --nocolor $NETSCRUB | grep Network | awk '{print $2}')
route add -net $net dev $DEVICE
RETVAL=$? if [ ${RETVAL} != "0" ]; then exit 1 fi
fi
echo "Adding route to $net via $gw on $DEVICE"
done done
The end result is an output of routes, their gateways and device names
Adding route to 44.x.x.x/32 via <internet.ip.of.gateway147> on ampr147
Adding route to 44.x.x.y/32 via <internet.ip.of.gateway148> on ampr148
Adding route to 44.x.x.z/32 via <internet.ip.of.gateway149> on ampr149
It is recommended that the system run iptables with sensible rules to restrict access to certain services. We will try to add this information as time permits.
Please contact us with any questions or comments