Google
 

Howto for DD-WRT Chillispot and Freeradius

Linksys WRT54GS + OpenWRT + ChillSpot + FreeRadius (with Mysql authentication and accounting ) + PHP/Perl


Before you start

I would recommend you need to know/read

OpenWRT - www.openwrt.org
ChilliSpot - www.chillispot.org
FreeRadius - www.freeradius.org
Mysql - www.mysql.com
PHP - www.php.net
Perl - www.cpan.org


A very Brief introduction

OpenWrt is a Linux distribution for Linksys WRT54G. It provides minimal firmware with add-on packages. Its allows the customization with broad range of software packages available for it.
We will be using OpenWrt as a replacement to the original Linksys firmware that comes pre-installed with the router.

ChilliSpot is a wireless LAN access controller. It is used for authenticating users of wireless LAN. It supports web based login for hotspots.
The Chilli daemon plays a primary role in the entire hotspot setup. It runs on the router and provides users access to the wireless Hotspot.

FreeRadius is a server that manages remote user authentication and accounting.

Mysql is a premier opensource database server.
All user database, authentication and accounting is stored in a Mysql database.


 

Follow this howto at your own risk…!!!

I have followed steps similar to those demonstrated here. They have worked for me. They may work for you too..

 

You may require special customization according to your need. Let me know if it worked for you.


<yunusbookwala @ gmail.com>



Setting up the Linksys router

I used the Linksys WRT54GS routers for this setup. For other supported routers see

http://wiki.openwrt.org/OpenWrtDocs/Installing

Remove ads

We need to install OpenWrt on the router. This is done by flashing the pre-installed Linksys firmware with openwrt.

<!–[if !supportLists]–>You may find the procedure to do this is a bit complex depending on your skills.

You may need to downgrade the linksys firmware to enable boot_wait. To do this <!–[endif]–>

1. Download this firmware from here

wget ftp://ftp.linksys.com/pub/network/WRT54GS_3.37.2_US_code.zip on your computer.

2. The Ethernet cable should be connected to the PORT 1 of the router.

3. Point your browser to the Linksys Web administration panel, usually its http://192.168.1.1 and goto the Admin Page -> Upgrade firmware link

4. upload the above firmware.

5. Once you have successfully downgraded the firmware, navigate to Administration -> Diagnostics -> Ping test

6. Enter exactly each line listed below, one line at a time into the “IP Address” field, pressing the Ping button after each entry.

;cp${IFS}*/*/nvram${IFS}/tmp/n
;*/n${IFS}set${IFS}boot_wait=on
;*/n${IFS}commit
;*/n${IFS}show>tmp/ping.log

7. When you get to the last command the ping window should be filled with a long list of variables including boot_wait=on somewhere in that list.


8. Now you are ready to install the actual openwrt firmware. You need a TFTP client for this.

9. Download the openwrt firmware

wget http://downloads.openwrt.org/whiterussian/rc3/bin/openwrt-wrt54gs-jffs2.bin

The basic procedure of using a tftp client to upload a new firmware to your router<!–[endif]–>

1. unplug the power to your router

2. start your tftp client

give it the router’s address (usually 192.168.1.1)

set mode to octet

tell the client to resend the file, until it succeeds.

put the file

3. plug your router, while having the tftp client running and constantly probing for a connection.

4. the tftp client will receive an ack from the bootloader and starts sending the firmware

Please be patient, the reflashing occurs AFTER the firmware has been transferred. DO NOT unplug the router, it will automatically reboot into the new firmware. These steps have to be done in quick succession.

A typical tftp session look like this

tftp 192.168.1.1s

tftp> binary
tftp> trace
Packet tracing on.
tftp> put openwrt-wrt54gs-jffs2.bin

On windows you may try this to tftp

tftp -i 192.168.1.1 PUT openwrt-wrt54gs-jffs2.bin

from the command prompt.

On routers with a DMZ led, OpenWrt will light the DMZ led while booting, after bootup it will turn the DMZ led off. Sometimes automatic rebooting does not work, so you can safely reboot after 5 minutes.

If everything up to this point goes fine, we are ready to use the router with the new openwrt.


Using the openwrt router

You can now login to the router like a regular Linux box. But the first thing after the router has rebooted is to set a password for the `root’ account.

At this point you can telnet on to the router. Once you have set a password for `root’ on next reboot you will only be able to ssh in to the router.

The default IP address on the router is 192.168.1.1 hence bring your machine to the 192.168.1. network range.

# telnet 192.168.1.1

Check whether boot_wait is ON. boot_wait must be on for upgrades or recovering from bad installations.

# nvram get boot_wait
boot_wait=on

Set a password for `root’

# passwd

If you get any error setting password, run the following command

# firstboot

Or the router may require a reboot.

# reboot

Now you can ssh in to the router and start configuring it.

# ssh root@192.168.1.1

We will be using the router as a ‘Access Point’. Run the following commands on the router.
These command set the networking parameters for the router to access the Internet(WAN).

# nvram set wan_ifname=vlan1
# nvram set wan_proto=static
# nvram set wan_ipaddr=xxx.xxx.xxx.xxx
# nvram set wan_netmask=255.255.255.0
# nvram set wan_gateway=192.168.1.1
# nvram set wan_dns=192.168.1.1
# nvram commit

If your router need to get IP address through DHCP you only need to run these

# nvram set wan_ifname=vlan1
# nvram set wan_proto=dhcp
# nvram commit

For PPPoE Internet connection

# nvram set wan_ifname=ppp0
# nvram set wan_proto=pppoe
# nvram set ppp_mtu=1492
# nvram set pppoe_ifname=vlan1
# nvram set ppp_username=your_isp_login
# nvram set ppp_passwd=your_isp_password
# nvram commit

 

You may need to reboot the router now.


Installing ChilliSpot

Download following packages on your machine

A module to create tunnel on the router

# wget http://downloads.openwrt.org/experimental-20050525/bin/packages/kmod-tun_2.4.30-1_mipsel.ipk

The chilli daemon

# wget http://chillispot.org/download/chillispot_1.0-1_mipsel.ipk
# wget http://chillispot.org/download/chillispot-1.0.tar.gz

Copy the files on to the router

# scp kmod-tun_2.4.30-1_mipsel.ipk root@192.168.1.1:/tmp
# scp chillispot_1.0-1_mipsel.ipk
root@192.168.1.1:/tmp

login to the router

# ssh root@192.168.1.1

On the router

# cd /tmp
# ipkg install kmod-tun_2.4.30-1_mipsel.ipk

Edit /etc/modules and append `tun` to it.

This will load the tun module whenever the router is restarted.

You can use vi on the router

OpenWRT comes with the following network interfaces:

  • eth0: LAN Switch. Is used as the connection point for the VLANs. Do never use this port directly.
  • eth1: Wireless Interface
  • vlan1: Virtual LAN: Internet
  • vlan0: Virutal LAN: Port 1 to 4
  • br0: Bridge between vlan0 and eth1.

We will have the LAN not accessible through wireless and vice-versa, we will remove eth1 from the brigde

Run these commands

# nvram set lan_ifnames=”vlan0 eth3″
# nvram commit

# /etc/init.d/S40network restart

Install chillispot

# cd /tmp
# ipkg install chillispot_1.0-1_mipsel.ipk

Now have the firewall in place. Copy the firewall script from the chillispot sources to the router.

Untar the chillispot source on your machine

# tar zxvf chillispot-1.0.tar.gz
# cd chillispot-1.0/doc
# scp firewall.openwrt
root@192.168.1.1:/tmp

On the router

# rm /etc/init.d/S45firewall
# cp /tmp/firewall.openwrt /etc/init.d/S45firewall
# chmod 755 /etc/init.d/S45firewall

I had to edit the S45firewall script and change

WANIF=$(nvram_get wan_ifname)
to
WANIF=$(nvram get wan_ifname)

Chilli takes care of assigning IP to the wireless clients, hence we can safely delete dnsmasq the openwrt dns and dhcp service.

# rm /etc/init.d/S#dnsmasq

Substitue the # in S#dnsmasq with the appropriate number.

Configure chilli to start on booting the router

edit /etc/init.d/S50services and append this line at the bottom

sleep 5
/usr/sbin/chilli

The configuration file for chilli daemon can be found at /etc/chilli.conf on the router. Now before any further chilli configuration we will be installing and configuring the UAM server and FreeRadius server.

We will be using the Universal Access Method(UAM) for authentication and login to the wireless HotSpot. With UAM the wireless client is redirected to a login web page to be authenticated on first Internet or Extranet request.

I suppose you have installed and configured Apache httpd server to serve CGI pages. The UAM method uses the hotspotlogin.cgi script which can be found at doc/hotspotlogin.cgi in the chillispot source directory.

Place this CGI script in the apache cgi-script directory usually /var/www/cgi-bin/ of your server.

Edit the hotspotlogin.cgi file. Uncomment following line

$uamsecret = “ht2eb8ej6s4et3rg1ulp”; Change this to your liking.
$userpassword=1;

The hotspotlogin.cgi script requires https(SSL) to access it. You may need to configure SSL certificates accordingly.


FreeRadius

We will have the FreeRadius server configured with MySql backend for user authentication and accounting.

If compiling from source

# wget ftp://ftp.freeradius.org/pub/radius/freeradius-1.0.5.tar.gz
# tar zxvf freeradius-1.0.5.tar.gz
# cd freeradius-1.0.5
# ./configure –with-mysql
# make && make install

Configure FreeRadius

We prepare the database for using with freeradius.

# mysql -u root -p
> create database radius;
> quit

# mysql -u root -p radius < /usr/share/doc/freeradius-x.x.x/db_mysql.sql

# mysql -u root -p
> GRANT select,insert,update,delete,create,drop ON radius.*

TO ‘radiususer’@’localhost’ IDENTIFIED BY ‘radiuspasswd‘;
> quit

edit /etc/raddb/radius.conf or /usr/local/etc/raddb/radius.conf

The end of your radiusd.conf should then look something like this:

authorize {
preprocess
chap
mschap
# auth_log
# attr_filter
# digest
suffix
sql
# file
# eap
# etc_smbpasswd
# ldap
}
authenticate {
Auth-Type PAP {
pap
}
Auth-Type CHAP {
chap
}
Auth-Type MS-CHAP{
mschap
}
# pam
# unix
# Auth-Type LDAP {
# ldap
# }
# eap
}
preacct {
pre process
acct_unique
suffix
# files
}
accounting {
acct_unique
detail
# counter
unix
sql
radutmp
# sradutmp
}
session {
radutmp
}

The radius.conf file is pretty good commented you can customize it as per your needs.

Edit the /etc/raddb/sql.conf and enter the server, name and password details to connect to your MySQL server and the RADIUS database.

Dialupadmin

Dialupadmin is a web based administration tool to manage Radius users and their accounting and authorization information.

Copy the dialup_admin directory from the freeradius source directory to /usr/local/dialup_admin

# cp -r freeradius-x.x.x/dialup_admin /usr/local/

Create as symlink from your web server root directory to dialup_admin/htdocs

# ln -s /usr/local/dialup_admin/htdocs /var/www/html/dialupadmin

edit the dialup_admin/conf/admin.conf. Attributes to lookout for are

general_radiusd_base_dir: /usr/local/radiusd
general_domain: company.com
general_lib_type: sql
general_radius_server: localhost
general_radius_server_port: 1812
general_encryption_method: clear
sql_type: mysql
sql_server: localhost
sql_port: 3306
sql_username: radiususer
sql_password: radius69passwd
sql_database: radius

You can now access dailup_admin with following kind of URL, http://yourwebsever/dialupadmin

Now we can move ahead configuring chilli on the router. The chilli configuration file can be found at /etc/chilli.conf on the router. The configuration derectives that needs to be taken care of are

#dns server that will be specified to the clients machines
dns1 172.16.0.5
dns2 172.16.0.6

#domain name that will be suggested to the clients
domain your.hotspot.com

#radius server IP
radiusserver1 192.168.0.100
radiusserver2 192.168.0.101

#secret shared between the router and the radius servers
#on the radius server it in the file clients.conf
radiussecret somesecret123

#Location ID of the router that will be sent to the radius for #accounting purpose
radiuslocationid isocc=in,cc=91,ac=400078,network=HOME_Nework

#Location name
radiuslocationname HOME,magnet

dhcpif eth1

#DHCP lease period in seconds
lease 900

#UAM paramter. URL of web server handling authentication.
Uamserver
https://youruamserver/cgi-bin/hotspotlogin.cgi

#secret shared between chilli and authentication web server.
#Specify same as mentioned in the hotspotlogin.cgi
uamsecret ht2eb8ej6s4et3rg1ulp

#Domains that users can browse with out authentication
uamallowed
www.chillispot.org,www.openwrt.org

There are other parameter that can be changed according to your preferences.


Testing the entire setup
All the basic configuration has been done, and ready to be tested.

Point your browser to the dialup_admin web interface. Create a test user account.
Just a username and password will do. You can leave the other fields blank.

Start the chilli server on the router in debug mode.

# /usr/sbin/chilli -f -d

Also start the radius on the server if not running. Use -X to see debugging output.

# /usr/sbin/radiusd -X

Now with your wireless client machine try to browse the Internet.

Freeradius Disconnected User when Time Limit Exceed

I learned this while integrating phpmyprepaid into my radius server.
The purpose of this configuration is to limit a user by the time he use our network.

Let say as example I want to limit a user only 1 hour per prepaid card.
So what I did is define a counter using sqlcounter module in the radius.conf file;

— snipped —
sqlcounter timelimit {

counter-name = Max-All-Session-Time
check-name = Max-All-Session
sqlmod-inst = sql
key = User-Name
reset = never
query = “SELECT SUM(AcctSessionTime) FROM radacct where UserName=’%{%k}’”

}
— snipped —

In the configuration I set the check-name as Max-All-Session, this will apply to the the radcheck table. You can choose other name, the same name should be use in the radcheck table. in the query part is the sql query we use to get the data for accounting. From the above query radius server will get the sum of session time of the user from radacct table. It will compare with Max-All-Session check item and terminate the session when the time is reached.

but the server does not do accounting yet, to enable accounting we must specify the module we define in authorize section in the radius.conf.

— snipped —
authorize {

 

preprocess
chap
mschap
suffix
eap
files
sql
pap
timelimit

}
— snipped —

Then we need to restart/reload the server to make the new configuration take effect.

To force the setting to the user we must insert the regarding attribute into the radcheck table:
as example:

+–+———–+—————–+—+———-+
| id | UserName| Attribute | op | Value |
+–+———–+—————–+—+———-+
| 1 | user | User-Password | := | p45sw0rd |
| 2 | user | Max-All-Session | := | 3600 |
+–+———–+—————–+—+———-+

Freeradius Limit User Access by Period Started from Activation Time

 

This module is sligthly different than last module; The significant difference is in the query attribute where the sql query will calculate the time used by a user from the first access time of a user.
It will compare to Access-Period we define, and terminate a user session when the times expire.

Using this, we can limit a user access period for 1 day or 1 week from his first time he login using the a prepaid card.
The counter module we create is as below,

— snipped —
sqlcounter accessperiod {

counter-name = Max-Access-Period-Time
check-name = Access-Period
sqlmod-inst = sql
key = User-Name
reset = never
query = “SELECT UNIX_TIMESTAMP() - UNIX_TIMESTAMP(AcctStartTime) FROM radacct WHERE UserName = ‘%{%k}’ ORDER BY AcctStartTime LIMIT 1?

— snipped —

In the authorize section, we should include the module:

— snipped —
authorize {

 

preprocess
chap
mschap
suffix
eap
files
sql
pap
accessperiod

}
— snipped —

And as usual, we need to restart/reload the server to make the new configuration take effect.

Then for the radcheck table, we insert the appropriate attribute:

+—-+—–———–+———————+—-+————-+
| id   | UserName  | Attribute           | op | Value     |
+—-+——–——–+———————+—-+————-+
| 3    | user             | Access-Period   | := | 3600     |
+—-+——–——–+———–———-+—-+————-+

Freeradius Terminate a User Session using Radclient

Sometimes a user session must be terminated. A lot of reason to do it and I leave it to you to choose what the reason is but I know someday you want to kill his session not for nothing. If you use icradius there is tools name as  radkill to do it. You also can use snmp protocol to kill him but there is an easier way for Freeradius user through radclient command.

root@salji:# radclient -h
Usage: radclient [options] server[:port] <command> [<secret>]
<command> One of auth, acct, status, coa, or disconnect.
-c count Send each packet ‘count’ times.
-d raddb Set dictionary directory.
-f file Read packets from file, not stdin.
-i id Set request id to ‘id’. Values may be 0..255
-n num Send N requests/s
-p num Send ‘num’ packets from a file in parallel.
-q Do not print anything out.
-r retries If timeout, retry sending the packet ‘retries’ times.
-s Print out summary information of auth results.
-S file read secret from file, not command line.
-t timeout Wait ‘timeout’ seconds before retrying (may be a floating point number).
-v Show program version information.
-x Debugging mode.

If the chillispot server is on the same machine as freeradius, we can run this command:

# echo “User-Name = raihan” | radclient -x 127.0.0.1:3779 status theradiussecret

If the command is accepted by server, you can get this output.

# echo “User-Name = raihan” | radclient -x 127.0.0.1:3779 status theradiussecret
Sending Disconnect-Request of id 63 to 127.0.0.1 port 3779
User-Name = “raihan”
rad_recv: Disconnect-ACK packet from host 127.0.0.1:3779, id=63, length=20

But firstly, You must starts chillispot server with this option, –coaport=3779 (or any port you desire) to make chillispot server accept your command.

# chilli –fg –coaport 3779

If the chillispot is separated from freeradius, the NAS wont have radclient command to do the job. But we can allow the chillispot to accept kill request from other nodes using –coanoipcheck option. Meaning, you can run the command from any machine, but with some security issue emerge. Well, some iptables rules  can fix it.

chilli –fg –coaport 3779 –coanoipcheck

Freeradius Bandwidth Limit for Network Users

Bandwidth limit can be set up using WISPr Attributes. Two attribute can be used for this purpose, which is

  1. WISPr-Bandwidth-Max-Down
  2. WISPr-Bandwidth-Max-Up

These attribute must be define in radreply table or radgroupreply table. Operator := is commonly used, but I figure out that == operator can be use also.
Lets say we want to limit a user bandwidth to 256kbps for download and 32kbps for upload. So we define in the radreply table:

WISPr-Bandwidth-Max-Down := 256000
WISPr-Bandwidth-Max-Up := 32000

However, bandwidth limitation is not successful yet by just applying these attributes, this is because our network users session is being routed in two way to go to Internet, using NAS internal ip (in my case br0) and NAS tunnel (tun0). Seems the br0 interface have more priority than tun0, and it packets will always being routed using this interfaces. This is not good as the attribute we set is only applied to tun0 tunnel which is created by Chillispot.

To overcome the situation we must force all packets to be routed using tun0. We can apply some firewall rules to help us achieve this. Below is the rules I used.

# iptables -P FORWARD DROP
# iptables -F FORWARD
# iptables -A FORWARD -o tun0-j ACCEPT
# iptables -A FORWARD -i tun0 -j ACCEPT

So when I list back the policy for Forward Chain in the Iptables, I’ll get this:

# iptables -nvL FORWARD
Chain FORWARD (policy DROP 17 packets, 1088 bytes)
pkts bytes target prot opt in out source destination
0 0 ACCEPT all — * tun0 0.0.0.0/0 0.0.0.0/0
0 0 ACCEPT all — tun0 * 0.0.0.0/0 0.0.0.0/0

By this rule, the bandwidth will be shape according to what we set in radreply/radgroupeply table. We can test this using iperf command.

So for the upload testing this is what i got:

$ iperf.exe -c 10.20.20.1 -i 10 -t 60
——————————

——————————
Client connecting to 10.20.20.1, TCP port 5001
TCP window size: 8.00 KByte (default)
————————————————————
[1912] local 10.0.1.4 port 3834 connected with 10.20.20.1 port 5001
[ ID] Interval Transfer Bandwidth
[1912] 0.0-10.0 sec 64.0 KBytes 52.4 Kbits/sec
[1912] 10.0-20.0 sec 40.0 KBytes 32.8 Kbits/sec
[1912] 20.0-30.0 sec 40.0 KBytes 32.8 Kbits/sec
[1912] 30.0-40.0 sec 40.0 KBytes 32.8 Kbits/sec
[1912] 40.0-50.0 sec 40.0 KBytes 32.8 Kbits/sec

[1912] 50.0-60.0 sec 32.0 KBytes 26.2 Kbits/sec
[1912] 0.0-65.4 sec 264 KBytes 33.1 Kbits/sec

And this is for download test:

$ iperf -c 10.0.1.4 -i 10 -t 60
——————————

——————————
Client connecting to 10.0.1.4, TCP port 5001
TCP window size: 16.0 KByte (default)
————————————————————
[ 3] local 10.20.20.1 port 60918 connected with 10.0.1.4 port 5001
[ 3] 0.0-10.0 sec 568 KBytes 465 Kbits/sec
[ 3] 10.0-20.0 sec 312 KBytes 256 Kbits/sec
[ 3] 20.0-30.0 sec 296 KBytes 242 Kbits/sec
[ 3] 30.0-40.0 sec 312 KBytes 256 Kbits/sec
[ 3] 40.0-50.0 sec 288 KBytes 236 Kbits/sec
[ 3] 50.0-60.0 sec 264 KBytes 216 Kbits/sec
[ 3] 0.0-60.3 sec 2.00 MBytes 278 Kbits/sec

Finally, we managed to set up bandwidth limit for our network users. However, there is a problem in the way, traffic burst happens when everytime an object is retrieved from the Internet. Imagine a web page that contains 20 objects, there will be 20 traffic burst to happen. The traffic will make the traffic looks inaccurate when being test using bandwidth tester. Except, if we could excluded the beginning of the data transfer from the test, the bandwidth test will looks more accurate.