Jeoss Full Bandwidth WIFI Extender

The idea is to set up a Jeoss box able to "roam" among several APs, to dynamically connect to the one with the strongest signal/highest priority while at the same time providing routed AP services downstream. It is required the Station and AP functions to be performed independently from each other in order to keep full WIFI bandwidth.


Our controlled zone only includes our Jeoss box, even when we have to know the upstream AP's association credentials we cannot perform any configuration change on them.
The full bandwidth requirement forces us to use two radios; the one upstream always performing as a Station and the one downstream always performing as AP.
The Station interface has to be able to get its IP, Default Gateway, and DNS servers as DHCP client of the associated upstream AP. Of course these addresses will not always be the same nor correspond to the same network either.
Downstream the scenario is the opposite; it is our AP interface the one that has to provide DHCP server services assigning IPs to its clients.
Finally Between both interfaces we need routing services that have to self-adapt to situations where the upstream AP can dynamically change re-assigning a new IP every time.

Jeoss Station side

On the Jeoss Station side we have to:

  1. Transform our ath0 radio into a Station
  2. Implement roaming capabilities among several APs

We start using the wpa_supplicant package in roaming mode. This package name is a bit misleading suggesting it only works handling the station side of a WPA wireless encryption connection. But in fact it can handle dynamic connections to a variety of encrypted and open networks.

let's (partially) edit /etc/network/interfaces considering ath0 is our Station side radio

# The ath0 Station Upstream connection************************************
# "manual" is required 
iface ath0 inet manual
   
# ensure ath0 is down (never fails because of || "true")
pre-up wlanconfig ath0 destroy || true

# set up the ath0 device in sta mode before bringing up the interface
pre-up wlanconfig ath0 create wlandev wifi0 wlanmode sta
wpa-driver madwifi

# we configure wpa_supplicant.conf with our upstream APs info
wpa-roam /etc/wpa_supplicant/wpa_supplicant.conf

# madwifi Station settings
up /etc/network/madwifiST.sh ath0
# set tx power up iwconfig ath0 txpower 7 # remove the ath0 device when bringing the interface down
post-down wlanconfig ath0 destroy || true # define the WIFI interfaces iface wireless1 inet dhcp iface wireless2 inet dhcp iface default inet dhcp #*************************************************************************

now let's edit /etc/wpa_supplicant/wpa_supplicant.conf adding the info of our upstream APs

	ctrl_interface=/var/run/wpa_supplicant
  ap_scan=1
	eapol_version=1
  fast_reauth=1

# Examples connecting to WEP APs

  network={
  ssid="WLAN_XX"
  key_mgmt=NONE
  wep_key0=5A303031333439354535323738
  wep_tx_keyidx=0
  id_str="wireless1"
  priority=6
  }

	network={
  ssid="WLAN_YY"
  key_mgmt=NONE
  wep_key0=43303033304441453532444641
  wep_tx_keyidx=0
  id_str="wireless2"
  priority=5
  }
 
# Example connecting to a WPA-Personal (PSK) APs
#	network={
# ssid="WPAPSK_SSID"
# key_mgmt=WPA-PSK
# psk="myWPA-PSK_PassPhrase"
#	id_str="wirelessWPA-PSK"
#	priority=10
# }

# Example connecting to Open APs
#	network={
# ssid="OPEN_SSID"
# key_mgmt=NONE
#	id_str="wirelessOPEN"
#	priority=5
# }

# More Examples at wpa_supplicant.conf(5) - Linux man page

# default open connection
network={
   key_mgmt=NONE
   }
 

At this point our Station side is able to automatically roam among the upstream APs, connecting to them, and getting its IP parameters by DHCP.

Jeoss AP side

On the Jeoss AP side we have to:

  1. Transform our ath1 radio into an AP
  2. Run DHCP server services on ath1
  3. Set an iptables NAT rule between the Jeoss Station (ath0) and AP (ath1) sides

let's (partially) edit /etc/network/interfaces considering ath1 is our AP side radio

# The ath1 AP Downstream connection***************************************
auto ath1
iface ath1 inet static
   
# ensure ath1 is down (never fails because of "true")
pre-up wlanconfig ath1 destroy || true
   
# set up the ath1 device in AP mode before bringing up the interface
pre-up wlanconfig ath1 create wlandev wifi1 wlanmode ap
   
# set AP specific data
wireless-channel 8
wireless-essid JeossAP
wireless-key 6A656F7373
address 192.168.30.1
network 192.168.30.0
netmask 255.255.255.0
broadcast 192.168.30.255

# Set the NAT rule 
pre-up /etc/network/repeaterNAT.sh 192.168.30.0/24 ath0
# madwifi AP settings up /etc/network/madwifiAP.sh ath1 # set tx power up iwconfig ath1 txpower 7 # remove the ath1 device when bringing the interface down post-down wlanconfig ath1 destroy #*************************************************************************

Now its time to set the DHCP server using dnsmask. Dnsmasq is a lightweight, easy to configure, DNS forwarder and DHCP server, designed to provide DNS (and optionally DHCP) services to a small-scale network. It results perfect for our downstream DHCP server needs.

let's edit /etc/dnsmasq.conf adding the following uncommented lines

# If you want dnsmasq to listen for DHCP and DNS requests only on
# specified interfaces (and the loopback) give the name of the
# interface (eg eth0) here.
# Repeat the line for more than one interface.
interface=ath1
 
# Uncomment this to enable the integrated DHCP server, you need
# to supply the range of addresses available for lease and optionally
# a lease time. If you have more than one network, you will need to
# repeat this for each network on which you want to supply DHCP
# service.
dhcp-range=192.168.30.31,192.168.30.40,255.255.255.0,12h

The Ipatbles NAT rule makes the downstream stations able to initiate upstream connections sharing ath0 IP address. Considering ath0 gets a dynamic IP we use MASQUERADE instead of SNAT.
Let's create /etc/network/repeaterNAT.sh and add execution permissions to it.

#!/bin/bash
   
# activate ip forwading
/bin/echo "1" > /proc/sys/net/ipv4/ip_forward
   
# Flush all rules
iptables -F
iptables -t nat -F
iptables -t mangle -F
   
# Erase all non-default chains
iptables -X
iptables -t nat -X
iptables -t mangle -X
   
# set default Policies
iptables -P INPUT ACCEPT
iptables -P OUTPUT ACCEPT
iptables -P FORWARD ACCEPT

#SNAT + dynamic IP => MASQUERADE   
iptables -t nat -A POSTROUTING -s "$1" -o "$2" -j MASQUERADE
   
#logger "repeater_nat_setup ON; Network: $1  Interface: $2"


Considering the hardware used has an additional Ethernet interface the /etc/networks/interface file would finally look like:

# The loopback network interface
   auto lo
   iface lo inet loopback

# The Ethernet network interface
   auto eth0
   iface eth0 inet dhcp

auto eth0:0
   iface eth0:0 inet static
   address 192.168.20.2
   netmask 255.255.255.0
   broadcast 192.168.20.255
   #    gateway 192.168.20.1   # it has to be commented

 
# The ath0 Station Upstream connection************************************
# "manual" is required 
iface ath0 inet manual
   
# ensure ath0 is down (never fails because of || "true")
pre-up wlanconfig ath0 destroy || true
   
# set up the ath0 device in sta mode before bringing up the interface
pre-up wlanconfig ath0 create wlandev wifi0 wlanmode sta
wpa-driver madwifi
   
# we configure wpa_supplicant.conf with our upstream APs info
wpa-roam /etc/wpa_supplicant/wpa_supplicant.conf

# madwifi Station settings
up /etc/network/madwifiST.sh ath0
# set tx power up iwconfig ath0 txpower 7 # remove the ath0 device when bringing the interface down
post-down wlanconfig ath0 destroy || true # define the WIFI interfaces iface wireless1 inet dhcp iface wireless2 inet dhcp iface default inet dhcp #************************************************************************* # The ath1 AP Downstream connection*************************************** auto ath1 iface ath1 inet static # ensure ath1 is down (never fails because of "true") pre-up wlanconfig ath1 destroy || true # set up the ath1 device in AP mode before bringing up the interface pre-up wlanconfig ath1 create wlandev wifi1 wlanmode ap # set AP specific data wireless-channel 8 wireless-essid JeossAP wireless-key 6A656F7373 address 192.168.30.1 network 192.168.30.0 netmask 255.255.255.0 broadcast 192.168.30.255 # Set the NAT rule pre-up /etc/network/repeaterNAT.sh 192.168.30.0/24 ath0
# madwifi AP settings up /etc/network/madwifiAP.sh ath1 # set tx power up iwconfig ath1 txpower 7 # remove the ath1 device when bringing the interface down post-down wlanconfig ath1 destroy || true #*************************************************************************


Now it's time to reboot and give a try to our new WIFI extender.

The wpa_cli is the wpa_supplicant front end that (if necesary) will allow us to manually list the available upstream APs, to force a re-association, to associate to a different one, etc. See wpa_cli man page for details.

root@jeoss804:~# wpa_cli
   wpa_cli v0.5.8
   Copyright (c) 2004-2007, Jouni Malinen <j@w1.fi> and contributors
   
   This program is free software. You can distribute it and/or modify it
   under the terms of the GNU General Public License version 2.
   
   Alternatively, this software may be distributed under the terms of the
   BSD license. See README and COPYING for more details.
   
   Selected interface 'ath0'
   Interactive mode
   
>

Where the available commands are:

Full
command

Short command

Description

status

stat

displays the current connection status

disconnect

disc

prevents wpa_supplicant from connecting to any access point

quit

q

exits wpa_cli

terminate

term

kills wpa_supplicant

reconfigure

recon

reloads wpa_supplicant with the configuration file supplied
(-c parameter)

scan

scan

scans for available access points (only scans it, doesn’t display anything)

scan_results

scan_r

displays the results of the last scan

list_networks

list_n

displays a list of configured networks and their status (active or not, enabled or disabled)

select_network

select_n

select a network among those defined to initiate a connection
(ie select_network 0)

enable_network

enable_n

makes a configured network available for selection
(ie enable_network 0)

disable_network

disable_n

makes a configured network unavailable for selection
(ie disable_network 0)

remove_network

remove_n

removes a network and its configuration from the list
(ie remove_network 0)

add_network

add_n

adds a new network to the list. Its id will be created automatically

set_network

set_n

shows a very short list of available options to configure a network when supplied with no parameters.

get_network

get_n

displays the required parameter for the specified network. See next section for a list of parameters

save_config

save_c

saves the configuration


NOTE1: This set-up requires a Jeoss install + the included optional collections "Madwifi-ng" and "Router A"

NOTE2: This set-up was extensively tested with Wistron CM9, Ubiquiti XR2, and Engenius EMP-8603 Atheros based radios. Radio power (txpower) has to be wisely adjusted for maximum throughput. Please consider unnecessary high TX power settings can negatively impact throughput when the AP and Station antennas are very close to each other.

NOTE3: The second radio could be replaced by an Ethernet interface and the same set-up would work perfectly with wired instead of wireless capabilities downstream.

NOTE4: Remember when fine tuning WIFI set-ups that radios are small computers; when something goes wrong with them simply by "soft" rebooting the host (#sudo reboot) might not put them back to work properly. A power-off/power-on cycle sometimes is mandatory when dealing with them, specially on SBC (Single Board Computers) and the like.