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 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
  3. Set a dynamic route between Jeoss Station (ath0) and AP (ath1) sides

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
 
# 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 roam among the upstream APs connecting to them and getting its IP parameters by DHCP. Now it is time to set the route between both Jeoss interfaces. Downstream the Jeoss AP side will have a static IP but the Station side will have a changing IP, then the route has to be updated every time the Jeoss Station side is assigned a new address.
This is easily achieved creating a DHCP client "hook"; this hook is really a shell script that it is automatically referenced by the DHCP client engine every time the client gets a new IP.

let' s create the file "repeater" (not execution permission required)
/etc/dhcp3/dhclient-exit-hooks.d/repeater

INTERNET_IF=ath0              # Jeoss Station interface (upstream)
LOCAL_NET=192.168.30.0        # Jeoss AP Network        (downstream)
LOCAL_MASK=255.255.255.0      # Jeoss AP Mask


nat_setup() {
# activate ip forwarding
/bin/echo "1" > /proc/sys/net/ipv4/ip_forward

# Flush any rules
iptables --table filter --flush FORWARD
iptables --table filter --flush INPUT
iptables --table filter --flush OUTPUT
      
# Drop default policies
iptables --table filter --policy INPUT ACCEPT
iptables --table filter --policy OUTPUT ACCEPT
iptables --table filter --policy FORWARD ACCEPT
      
# Free loopback connections
iptables --table filter --append INPUT --in-interface lo --jump ACCEPT
iptables --table filter --append OUTPUT --out-interface lo --jump ACCEPT 

      # -------------------------#
      #         ROUTING
      # -------------------------#

iptables --table nat \
         --append POSTROUTING \
         --out-interface "$INTERNET_IF" \
         --source "$LOCAL_NET"/"$LOCAL_MASK" \
         --jump SNAT \
         --to-source "$new_ip_address"

#logger "RepeaterNatSetup: New rule set; If: $interface Reason: $reason"

}

repeater_nat_setup() {
#logger "RepeaterNatSetup: Hook; If: $interface Reason: $reason"

if [ $interface = $INTERNET_IF ]; then 

	case $reason in
      BOUND | RENEW | REBIND | REBOOT )
      nat_setup
      ;;
  esac
fi
}

repeater_nat_setup 

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

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

# madwifi AP settings
up madwifiAP.sh ath1
   
# 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 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

finally the /etc/networks/interface file considering there is an additional Ethernet interface it will 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
 
# 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

# madwifi AP settings
up madwifiAP.sh ath1
   
# remove the ath1 device when bringing the interface down
post-down wlanconfig ath1 destroy
#*************************************************************************

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

 

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 radios.

NOTE3: The second radio can be replaced by an Ethernet interface and the same set-up works perfect 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.