This section deals with special configurations and usage of OpenWrt.
OpenWrt Kamikaze 7.06 includes the version 1.1 of ChilliSpot. This allows you to use the dynamic firewall scripts among other features on your Access Point. If you do not intend to use this feature, you can always opt for the more user friendly DD-WRT.
You have deployed a pilot Hotcakes and ChilliSpot set up. You followed the standard HOWTO and installed it on a dual homed Ubuntu machine.
Everyone is very impressed with this, in fact, other departments also want their Access Point's to join your Hotcakes management solution.
They asked for the following requirements:
A central server which manage access to all Access Points on the organization's network.
Indication who is logged onto which Access Point at any given time.
Each Access Point must implement a transparent proxy which will use the existing organization's proxy servers as an upstream source.
Limit a user dynamically (depending on their profile) when logged in to the network and clear this limitation as soon as the user leaves the network.
Be able to terminate the connection of misbehaving users on any of the Access Points.
Indicate where each Access Point is located, and specify detail on its vendor, model etc.
Install Hotcakes and Free Radius on a server. (This you've already done during the initial pilot with the dual homed Ubuntu machine.)
Explain to the departments who want to join your management solution that they have to replace those Access Points which can not be flashed with OpenWrt.
Flash existing Access Points with the OpenWrt Kamikaze 7.06 software, and acquire replacements for those Access Points which can not be flashed with OpenWrt.
Install ChilliSpot on each Access Point running OpenWrt to act as a gatekeeper.
Install TinyProxy on each Access Point running OpenWrt to act as a transparent proxy.
Implement a dynamic firewall on each Access Point running OpenWrt by using the 'Dynamic firewall with ChilliSpot and IP Tables' recipe in this cookbook.
We will discuss this implementation by giving a diagram of an imaginary network. See the included schematic on how everything fits in together.
The implementation will be about setting up the OpenWrt Access Points so they fit into this environment.
We will now go through the steps to deploy OpenWrt devices in an enterprise environment.
You will require a working Hotcakes set up. There is a separate HOWTO to get Hotcakes up and running.
Please bear the following in mind with regards to NAS devices on Free Radius
You have to adjust the Free Radius set up to get information on the NAS devices from the MySQL database instead of the 'clients.conf' file.
To do this, ensure
# # Set to 'yes' to read radius clients from the database ('nas' table) readclients = yesis uncommented in the '/usr/local/etc/raddb/sql.conf' file.
NAS devices specified inside the nas sql table will override any NAS devices specified inside the '/usr/local/etc/raddb/clients.conf' file.
The default install of Hotcakes will add a NAS client to Free Radius for '127.0.0.1'. This should not be removed, since the command to kick users off the Access Point makes use of this information.
Also: Keep the original '/usr/local/etc/raddb/clients.conf' file as is. If you remove the '127.0.0.1' client in that file, you are in for startup failure. |
If you want to show the NAS devices on Google Maps you have to gather their latitude and longitude to indicate their location on earth.
Now you can go to the 'Nas Devices->Devices' page on the Hotcakes management interface and add them.
When you are finished, the 'Devices' page should look similar to this screen shot.
NOTE: You have to restart/reload Free Radius every time you add NAS devices. |
I'm not going to repeat available documentation on how to to this.
You can download Kamikaze 7.06 here
The install procedure can be found here
Ensure the following packages are installed.
Table 1. Packages to install on the OpenWrt Access Points
Package | Comment |
---|---|
chillispot | Used as a Captive Portal on the WiFi network interface of the Access Point. |
kmod-tun | Kernel support for the TUN/TAP tunnelling device. (Dependicy of ChilliSpot) |
bash | Needed by the Dynamic Firewall scripts. |
libncurses | Needed by bash to function correct when executing the Dynamic Firewall scripts. |
tinyproxy | Required to implement the transparent proxy feature on each Access Point. |
iptables-mod-nat | Required to implement the transparent proxy feature on each Access Point. (module libipt_REDIRECT) |
Documentation on ipkg can be found here
Configure the WAN interface to have a fixed IP
Edit the file '/etc/config/network' so that it contains the following:
#### WAN configuration config interface wan option ifname "eth0.1" option proto static option ipaddr 10.0.20.100 option netmask 255.255.255.0 option gateway 10.0.20.1 option dns "10.0.10.100 10.0.10.101"
You need to adjust the above to suit the network set up on your network |
Activate the WiFi interface. Edit the '/etc/config/wireless' file. Change
option disabled 1to
option disabled 0
Break up the WiFi and LAN bridge. Edit the '/etc/config/wireless' file. Delete the
option network lanline in order to have the WiFi interface on its own.
Specify the SSID of the Access Point.
option ssid AP_RECEPTION
To learn more about network configuration in OpenWrt Kamikaze 7.06 you can go here
Be very careful when adjusting a firewall rule. It is very easy to lock the Access Point so down that you can not get access to the device. If this happens you are likely to get your soldering iron handy to add the serial port communication channel to the device. Various reports have been made that fail-safe mode does not work in OpenWrt Kamikaze 7.06. You have been warned! |
For this exercise we have the Access Points inside a protected corporate environment so we will fling the firewall wide open. Later you can close it down again.
You need to add the following lines at the bottom of the '/etc/firewall.user' file. I'm including the complete file for extra clarity. See the included comments.
#!/bin/sh # Copyright (C) 2006 OpenWrt.org iptables -F input_rule iptables -F output_rule iptables -F forwarding_rule iptables -t nat -F prerouting_rule iptables -t nat -F postrouting_rule # The following chains are for traffic directed at the IP of the # WAN interface iptables -F input_wan iptables -F forwarding_wan iptables -t nat -F prerouting_wan ### Open port to WAN ## -- This allows port 22 to be answered by (dropbear on) the router # iptables -t nat -A prerouting_wan -p tcp --dport 22 -j ACCEPT # iptables -A input_wan -p tcp --dport 22 -j ACCEPT ### Port forwarding ## -- This forwards port 8080 on the WAN to port 80 on 192.168.1.2 # iptables -t nat -A prerouting_wan -p tcp --dport 8080 -j DNAT --to 192.168.1.2:80 # iptables -A forwarding_wan -p tcp --dport 80 -d 192.168.1.2 -j ACCEPT ### DMZ ## -- Connections to ports not handled above will be forwarded to 192.168.1.2 # iptables -t nat -A prerouting_wan -j DNAT --to 192.168.1.2 # iptables -A forwarding_wan -d 192.168.1.2 -j ACCEPT #Hotcakes hack #Open it up iptables -P INPUT ACCEPT iptables -P OUTPUT ACCEPT iptables -P FORWARD ACCEPT #Flush it clean iptables -F INPUT iptables -F OUTPUT iptables -F FORWARD #Redirection from port 80 to 8888 for tiny proxy #ONLY inside the tunnel created by chillispot iptables -t nat -A prerouting_rule -i tun0 -p tcp --dport 80 -j REDIRECT --to-port 8888 #End hotcakes hack
You can learn more about the IP Tables firewall in OpenWrt here
In the above alteration to the IP Tables firewall, we are redirecting all traffic to port 80 to port 8888. This is the port where TinyProxy is listening on.
Edit the '/etc/tinyproxy/tinyproxy.conf' file, and ensure you change the following to suit your network set up.
Table 2. Values to verify or change
Value | Comment |
---|---|
Port 8888 | You can keep the default. If you change the port here be sure to change it in the firewall rule as well. |
Listen 192.168.182.1 | If you change the IP setup in ChilliSpot be sure to change it here as well. |
no upstream "10.0.0.0/16" | Filter out the local domain not to go via the organizational proxies. |
no upstream ".hotcakes.com" | Filter out the local domain not to go via the organizational proxies. |
upstream 10.0.10.11:3128 | Add your organizational proxy as an upstream source. |
Allow 192.168.182.0/24 | If you change the IP setup in ChilliSpot be sure to change it here as well. |
In my installation of TinyProxy the startup script's permissions was not right, and it was not activated. You can correct this by the following commands:
chmod 755 /etc/init.d/tinyproxy /etc/init.d/tinyproxy enable
This part will mention all the important options which you need to verify/specify in the 'etc/chilli.conf' file.
Table 3. Options to verify or change
Option | Comment |
---|---|
radiuslisten 10.0.20.100 | This is the IP on which ChilliSpot will listen for client disconnect requests. This option also determines the value for the NAS-IP-Address radius attribute, very important for the disconnect function to work correct. |
radiusnasip 10.0.20.100 | IP address to report in NAS-IP-Address attribute. Defaults to the IP address specified by the radiuslisten option. (Can be left out.) |
radiusserver1 10.0.10.10 | The server on which Hotcakes and Free Radius is running. |
radiusserver2 10.0.10.10 | The server on which Hotcakes and Free Radius is running. |
dhcpif wl0 | Make sure about this one! You don't want to setup rogue DHCP servers on the network. |
uamserver https://10.0.10.10/cgi-bin/hotspotlogin.cgi | It seems to me this script is the only 'just works' login script. I'll try to find the source of problems with the GoLogin script. The one on my setup did not work as intended. :( |
uamsecret ht2eb8ej6s4et3rg1ulp | Be sure this is the same as the secret specified in the login script. |
uamallowed 10.0.10.10,192.168.1.0/24 | The IP of the Hotcakes and Free Radius server. The subnet of the LAN part of the Access Point running the DNS server. |
coaport 3799 | Very important for the disconnect function to work correct. Add this to the '/etc/chilli.conf' file. There is no commented out entry in the '/etc/chilli.conf' file, you have to add it yourself. |
Activate ChilliSpot to start during boot up.
/etc/init.d/chilli enable
We've made a lot of changes up to now. Before we do the last part (the Dynamic Firewall) we are first going to test to see if everything is working as intended. Reboot the device ( command 'reboot') and try to get in via the WiFi interface to the network. You should be greeted with a login screen. |
Finally we are going to implement the Dynamic Firewall on each Access Point.
Refer to Section 2.1 for detailed background. |
Connection between the OpenWrt Access Points and the Hotcakes/Free Radius server happens via ssh. You have to generate a public/private key pair on each OpenWrt Access Point. The public key has to be added to the '/root/.ssh/authorized_keys' file on the Hotcakes/Free Radius server.
The ssh server and client running on OpenWrt is dropbear and dbclient respectively.
To get the key authentication working, do the following:
Create '/etc/dynamic_firewall' directory.
mkdir /etc/dynamic_firewall
Create a new RSA key to store in '/etc/dynamic_firewall/'.
dropbearkey -t rsa -f /etc/dynamic_firewall/id_rsa.db
The public key part of the new key will be printed to the screen. You can put it into the '/root/.ssh/authorized_keys' file on the Hotcakes/Free Radius server.
Should you lose the public key, you can always get it back by using the private key and the -y switch to dropbearkey dropbearkey -y -f /etc/dynamic_firewall/id_rsa.db |
Because of paths which differ from those on Ubuntu, we will modify the 'fetch_rules.sh' and 'clear_rules.sh' scripts after we copied them from the Hotcakes/Free Radius server onto the OpenWrt Access Point.
Copy the two sripts responsible for adding and clearing a user's firewall rules to the '/etc/dynamic_firewall' directory on each OpenWrt Access Point.
cd /etc/dynamic_firewall scp -i id_rsa.db root@10.0.10.10:/var/www/cake/hotcakes/webroot/files/fetch_rules.sh ./ scp -i id_rsa.db root@10.0.10.10:/var/www/cake/hotcakes/webroot/files/clear_rules.sh ./
Change the /etc/dynamic_firewall/fetch_rules.sh to look like this:
#! /bin/bash #Copyright (c) <2007> <dirkvanderwalt> (<dirkvanderwalt at gmail dot com>). # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #--------------------------------------- #---Values to Specify------------------- HOTCAKES_IP='10.0.10.10' REMOTE_SCRIPT='/usr/local/bin/rules_for_user.pl' REMOTE_USER='root' #OpenWrt MOD KEY_FILE='/etc/dynamic_firewall/id_rsa.db' IPTABLES='/usr/sbin/iptables' #END OpenWrt MOD #----END Values to Specify-------------- #-------------- #--Dummy Tests- #FRAMED_IP_ADDRESS="192.168.182.4" #USER_NAME="alee" #--END Dummy--- #Initial value, we only ban all if the rules says 'ALLOW' DROP_FLAG=0 #WE NEED TO SEE IF THIS SCRIPT WAS CALLED BY CHILLI, IF IT WAS, THE FOLLOWING #ENVIRONMENTAL VARIABLES WILL HAVE A VALUE if [ -z $FRAMED_IP_ADDRESS ] then echo "----------------------------------------------------------------------" echo "The value of 'FRAMED_IP_ADDRESS' is not set, this script is suppose to be" echo "run by the Chilli program! Aborting!" echo "----------------------------------------------------------------------" exit 0; fi if [ -z $USER_NAME ] then echo "----------------------------------------------------------------------" echo "The value of 'USER_NAME' is not set, this script is suppose to be" echo "run by the Chilli program! Aborting!" echo "----------------------------------------------------------------------" exit 0; fi #If it passed these two tests, we can ask the FreeRADIUS server for the rules for specified user #FEEDBACK=(`ssh $REMOTE_USER\@$HOTCAKES_IP perl $REMOTE_SCRIPT $USER_NAME`) FEEDBACK=(`ssh -y -i $KEY_FILE $REMOTE_USER\@$HOTCAKES_IP perl $REMOTE_SCRIPT $USER_NAME`) element_count=${#FEEDBACK[*]} current_element=0; value="DROP" while [ "$current_element" -lt "$element_count" ] do action=${FEEDBACK[$current_element]} destination=${FEEDBACK[(( $current_element +1 ))]} if [ "$action" == "DROP" ] then echo "DROP $destination" $IPTABLES -I FORWARD -s $FRAMED_IP_ADDRESS -d $destination -j $action #$IPTABLES -i FORWARD -s -d $destination fi if [ "$action" == "ACCEPT" ] then #IF THERE ARE ACCEPT RULES WE first HAVE TO BLOCK EVERYTHING AND only ALLOW #FOR THE ACCEPT DESTINATIONS #WE ONLY DO THIS BLOCK ONCE AND SET A FLAG SO WE DON'T BLOCK ALL WITH EVERY ACCEPT if [ $DROP_FLAG != 1 ] then #Drop everything from this host then allow hosts to be visited (destinations) #FIXME WRITE IPTABLE COMMAND TO BANN ALL echo "DO INTITAL REJECT OF ALL" $IPTABLES -I FORWARD -s $FRAMED_IP_ADDRESS -d 0.0.0.0/0 -j DROP DROP_FLAG=1; fi echo "ACCEPT $destination" $IPTABLES -I FORWARD -s $FRAMED_IP_ADDRESS -d $destination -j $action fi (( current_element ++ )) done exit 0
The main changes made to this file is the location of the iptables command, the location of the remote server and how to get to it via the ssh command (public private key). |
Change the /etc/dynamic_firewall/clear_rules.sh to look like this:
#! /bin/bash #Copyright (c) <2007> <dirkvanderwalt> (<dirkvanderwalt at gmail dot com>). # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #-------------- #--Dummy Tests- #FRAMED_IP_ADDRESS="192.168.182.4" #USER_NAME="alee" #--END Dummy--- #You can also use this script to clear all the rules for a certain ip #Just specify the IP as argument if [ $1 ] then FRAMED_IP_ADDRESS=$1 fi #WE NEED TO SEE IF THIS SCRIPT WAS CALLED BY CHILLI, IF IT WAS, THE FOLLOWING #ENVIRONMENTAL VARIABLES WILL HAVE A VALUE if [ -z $FRAMED_IP_ADDRESS ] then echo "----------------------------------------------------------------------" echo "The value of 'FRAMED_IP_ADDRESS' is not set, this script is suppose to be" echo "run by the Chilli program! Aborting!" echo "----------------------------------------------------------------------" exit 0; fi #Check for rules for $FRAMED_IP_ADDRESS in the forward chain, and clear each of them RULES_PRESENT=(`/usr/sbin/iptables -L FORWARD -n | /bin/grep $FRAMED_IP_ADDRESS`) current_element=0; element_count=${#RULES_PRESENT[*]} while [ "$current_element" -lt "$element_count" ] do #We get the value of the list element value=${RULES_PRESENT[$current_element]} #If the value is 'DROP' or 'ACCEPT' we clear it if [ $value == "DROP" ] then action=$value prot=${RULES_PRESENT[ (( $current_element +1 )) ]} opt=${RULES_PRESENT[ (( $current_element +2 )) ]} source=${RULES_PRESENT[ (( $current_element +3 )) ]} destination=${RULES_PRESENT[ (( $current_element +4 )) ]} /usr/sbin/iptables -D FORWARD -s $source -d $destination -j $action fi if [ $value == "ACCEPT" ] then action=$value prot=${RULES_PRESENT[ (( $current_element +1 )) ]} opt=${RULES_PRESENT[ (( $current_element +2 )) ]} source=${RULES_PRESENT[ (( $current_element +3 )) ]} destination=${RULES_PRESENT[ (( $current_element +4 )) ]} /usr/sbin/iptables -D FORWARD -s $source -d $destination -j $action fi (( current_element ++ )) done exit 0
The main change made to this file is the location of the iptables command. |
Now we have to configure ChilliSpot to make use of these scripts. Add the 'conup' and 'condown' options to the 'etc'chilli.conf' file.
# TAG: conup # Script executed after a user has been authenticated. # Executed with the following parameters: <devicename> <ip address> # <mask> <user ip address> <user mac address> <filter ID> # Normally you do not need to uncomment this tag. #conup /etc/chilli.conup conup /etc/dynamic_firewall/fetch_rules.sh # TAG: conup # Script executed after a user has disconnected. # Executed with the following parameters: <devicename> <ip address> # <mask> <user ip address> <user mac address> <filter ID> # Normally you do not need to uncomment this tag. #conup /etc/chilli.condown condown /etc/dynamic_firewall/clear_rules.sh
Restart ChilliSpot. Refer to Section 2.1.4.6 to manage rules.
This bit will deviate from the standard recipe format, and will discuss only the steps required to get WDS (Wireless Distribution System) working on OpenWrt Kamikaze 7.06.
I'd like to thank ajauberg for his excelent HOWTO to set up ChilliSpot and WDS on OpenWrt Whiterussian. For those still running OpenWrt Whiterussian, you can go here for documentation. |
For those who does not know much about WDS, here's a quick description.
A WDS is a system that enables the interconnection of access points wirelessly. As described in IEEE 802.11, it allows a wireless network to be expanded using multiple access points without the need for a wired backbone to link them, as is traditionally required.
In this setup the Access Point connected to the Internet will be called the Gateway Access Point. We will then create a 802.11 hotzone as opposed to a 802.11 hotspot by extending this Access Point's range with the use of WDS. The other Access Points which are part of this 802.11 hotzone will not be physically connected to the network. They will be used merely to extend the coverage area of the Gateway Access Point.
We assume all the Access Points are flashed with the OpenWrt Kamikaze 7.06 software.
We assume the Gateway Access Point is running ChilliSpot as stipulated in Section 3.1.
On the Gateway Access Point's WiFi interface, we need to add a WDS interface. This will specify the Access Points which are allowed to talk with this Access Point's WDS. Add the following to the '/etc/config/wireless' file. (I'm showing the whole file for extra clarity)
config wifi-device wl0 option type broadcom option channel 5 # disable radio to prevent an open ap after reflashing: option disabled 0 config wifi-iface option device wl0 option mode ap option ssid HOTCAKES-01 option hidden 0 option encryption none config wifi-iface option device wl0 option mode wds option ssid WDS option hidden 0 option encryption none option bssid '00:90:4C:5F:00:2B'
This needs to be added BELOW the part where you specify the detail of the Access Point. The 'option bssid' contains a list of MAC Addresses of those Access Point's WiFi interfaces which are part of the 802.11 hotzone.
I had to modify the nvram value for the other Access Points MAC Addresses, since they were the same on each device (00:90:4C:5F:00:2A) nvram set il0macaddr=00:90:4c:5f:00:2b nvram commit |
This will create an extra interface which will be present upon reboot. You can verify this by issuing the 'iwconfig' command.
wds0.1 no wireless extensions.
At this stage the WDS interface is not up. You have to define a bridge which will bridge the WiFi interface (wl0) and this WDS interface.
Edit the '/etc/config/network' file to define the bridge 'w'. Again I'm showing the complete file.
#### VLAN configuration config switch eth0 option vlan0 "0 1 2 3 5*" option vlan1 "4 5" #### Loopback configuration config interface loopback option ifname "lo" option proto static option ipaddr 127.0.0.1 option netmask 255.0.0.0 #### LAN configuration config interface lan option type bridge option ifname "eth0.0" option proto static option ipaddr 192.168.1.1 option netmask 255.255.255.0 #### WAN configuration config interface wan option ifname "eth0.1" option proto static option ipaddr 10.0.100.24 option netmask 255.255.255.0 option gateway 10.0.100.1 option dns "10.0.10.100 10.0.10.101" ####Bridge for the WIFI config interface w option type bridge option ifname "wl0 wds0.1"With this bridge defined, OpenWrt will now bring the WDS interface up together with the bridge upon startup.
Reboot and verify that the bridge and WDS interface is up by issuing the 'ifconfig' command.
br-w Link encap:Ethernet HWaddr 00:90:4C:5F:00:2A UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1 RX packets:2297582 errors:0 dropped:0 overruns:0 frame:0 TX packets:3053972 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:0 RX bytes:108113789 (103.1 MiB) TX bytes:237023442 (226.0 MiB)All bridge interfaces start with 'br-' and then the bridge name as defined in the '/etc/config/network' file.
The 'wds0.1' interface should also appear in the output of 'ifconfig'.
wds0.1 Link encap:Ethernet HWaddr 00:90:4C:5F:00:2A UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1 RX packets:0 errors:0 dropped:0 overruns:0 frame:0 TX packets:0 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:1000 RX bytes:0 (0.0 B) TX bytes:0 (0.0 B)As a final verification, you can use 'brctl' to see if the bridge was created.
root@OpenWrt:/etc/config# brctl show bridge name bridge id STP enabled interfaces br-lan 8000.0018f8d28b78 no eth0.0 br-w 8000.00904c5f002a no wl0 wds0.1
Change the interface on which ChilliSpot binds the DHCP server to that of the bridge 'br-w'.(/etc/chilli.conf)
# TAG: dhcpif # Ethernet interface to listen to. # This is the network interface which is connected to the access points. # In a typical configuration this tag should be set to eth1. #dhcpif wl0 dhcpif br-w
If you neglect to do this, ChilliSpot will not work as intended. |
You can now do the same on each Access Point which is part of the 802.11 hotzone. You do not need to do the ChilliSpot part, since we are using only one Access Point as a Gateway.
Remember that the MAC address which you specify on them has to be the MAC address of the Gateway Access Point. The 'ap' mode SSID does not need to be the same as the Gateway Access Point, but the 'wds' mode SSID's need to be the same.
Listed here is the '/etc/config/wireless' file from another Access Point in the 802.11 hotzone.
config wifi-device wl0 option type broadcom option channel 5 # disable radio to prevent an open ap after reflashing: option disabled 0 config wifi-iface option device wl0 option mode ap option ssid HOTCAKES-02 option hidden 0 option encryption none config wifi-iface option device wl0 option mode wds option ssid WDS option hidden 0 option encryption none option bssid '00:90:4C:5F:00:2A'
Remember all Access Points which are part of the 802.11 hotzone need to be on the same channel for WDS to work. |