CoovaChilli With EasyHotspot And Radius

CoovaChilli With EasyHotspot And Radius

Hello and welcome! Thank you for visiting my blog. Today, I’m going to write about  CoovaChilli, formerly known as ChilliSpot. It is an opensource Wi-Fi hotspot solution. I’m setting up CoovaChilli with EasyHotspot, also an open-source web portal. And FreeRadius server is being used for authentication. If you want to do it Ubuntu, please read this article.

CoovaChilli Wi-Fi Hotspot

Before I jump into the setup, I would like to shed some lights on the problem I’m trying to solve here. This project has been done to meet the hotspot requirements of a commercial bank for its guests or customers. In this case, this bank needed to provide free internet access to its guests inside its premises. For that purpose, it required the guest users to authenticate themselves in the hotspot system with their username and PIN. Now, I hope you can see the challenge here. A commercial bank usually has above hundred thousands of clients and we need to have their login credentials in this hotspot system.

I’m setting up my test environment in CentOS system running in Vmware vSphere and the steps I took during these setups are illustrated in the following posts:

Now that my host CentOS server is ready for use, I can get into the installation of CoovaChilli, Radius Server, and EasyHotspot. Before we do that, let’s summarize my host setup. I’ve got two network interfaces: eth0 connecting my external network and eth1 connecting my wireless network. Since I’m using VMware Vsphere platform and have two networks, I’ve passed two VLANs to VMware server using trunk mode in my switch. I’m leaving configuration for eth1 as it is.

Setting up Apache Web Server and Mysql DB

Since EasyHotspot is based on PHP and MySQL, and our preferred web server is Apache, let’s install these software first in our CentOS server. For that purpose, I’m installing EPEL repository so that I can have wide range of software packages to install.

[root@coovachilli ~]# yum -y install wget
[root@coovachilli ~]# wget
[root@coovachilli ~]# rpm -ivh epel-release-6-8.noarch.rpm
[root@coovachilli ~]# yum -y install httpd php php-mysql mysql-server php-xml php-gd php-pear php-db patch mod_ssl openssl dnsmasq git

After these packages are successfully installed, open up the php.ini file inside /etc directory and ensure that  the lines “short_open_tag = On” and “date.timezone = Asia/Kathmandu” are set. Set your timezone accordingly. Note that there are two lines containing “short_open_tag”. For this purpose, leave the one beginning with “;” as it is and set the other one as “On”. Misconfiguration in this section can lead to an error in EasyHotspot web page. So, you better be careful here.

Now, let’s tell the system to start these services during startup so that we don’t need to start them manually.

[root@coovachilli ~]# chkconfig --level 235 httpd on
[root@coovachilli ~]# chkconfig --level 235 mysqld on
[root@coovachilli ~]# chkconfig --level 235 dnsmasq on

Let’s also manually start these daemons for now:

[root@coovachilli ~]# service httpd start
[root@coovachilli ~]# service mysqld start
Setting Up EasyHotspot Web Portal

Now that our web server and database server are ready for use, let’s go ahead and install the EasyHotspot web portal. This project is available for collaboration and use in Github. So, I’m just going to clone this repository to my local system and perform the setup.

[root@coovachilli ~]# cd /opt
[root@coovachilli opt]# git clone
[root@coovachilli opt]# ln -s /opt/EasyHotspot/htdocs /var/www/html/easyhotspot

Doing above steps, downloads the source code of EasyHotspot from its respective Github repository to our local /opt directory and then soft links its web pages to the document root of Apache server i.e. /var/www/html. Now, if we access this system’s URL followed by /easyhotspot directory from a web browser, it should launch EasyHotspot’s login page.

In the database side, EasyHotspot is configured to use a mysql database called “easyhotspot_opensource“. Also, the pre-configured database user is “easyhotspot” with password “easyhotspot“. So, we need to manually create these database, user and password in our Mysql server. This task can be done as follows:

[root@coovachilli opt]# mysql

Use “mysql -u -p” if you’ve already setup user login credentials for mysql server.

mysql>  SHOW databases;
mysql> CREATE database easyhotspot_opensource;
mysql> CREATE USER 'easyhotspot'@'localhost';
mysql> SET PASSWORD FOR 'easyhotspot'@'localhost' = PASSWORD('easyhotspot');
mysql> GRANT ALL ON easyhotspot_opensource.* to 'easyhotspot'@'localhost';
mysql> quit

Doing this will create the required database and user credential in our MySQL server. Next task that we need to perform is import the same database content provided by EasyHotspot itself to get it started.

[root@coovachilli opt]# mysql -u root easyhotspot_opensource < /opt/EasyHotspot/install/database_with_sample.sql

This completes the setup procedure for EasyHotspot. Last step necessary to start accessing its web page is to allow port 80 through our CentOS’s iptables firewall. This can be done by opening the /etc/sysconfig/iptables file in vi editor and move the cursor to the line which is permitting the port 22. Hit  “yy” to copy this permit statement and hit “p” to paste it in the line below. In this new line, replace the value 22 with 80. Then save and close this file by using Esc followed by :wq. Finally, restart the iptables daemon to implement this change.

We should now be able to access the web page of EasyHotspot by accessing the URL “http://<server’s IP>/easyhotspot”. The default username is “admin” and the password is “admin123“.

EasyHotspot Login Page
EasyHotspot Login Page
Installing FreeRadius

FreeRadius is an open-source radius server for external authentication purpose. Since it is available in the CentOS’s repository, we can install it using yum like this:

[root@coovachilli ~]# yum install freeradius freeradius-mysql freeradius-utils
[root@coovachilli ~]# chkconfig --level 235 radiusd on

Then, open the clients.conf file and make necessary changes:

[root@coovachilli ~]# vi /etc/raddb/clients.conf

Within this file, find the “client localhost” section using “/client localhost” command in vi editor and make sure that lines shown below are present.

ipaddr =
secret = easyhotspot
nastype = other

Similarly, open the radiusd.conf file, find the “module” section, and then un-comment following lines:

[root@coovachilli ~]# vi /etc/raddb/radiusd.conf
$INCLUDE sql.conf
$INCLUDE sql/mysql/counter.conf

In this same file, find “instantiate” section and then add these two lines:


Next, open a config file for enabled sites (/etc/raddb/sites-enabled/default), find the section “authorize“, and then uncomment the line containing “sql” only. In this same section, add these two new lines:


Within the same config file, find the sections “accounting“, “session“, and “post auth“, and then uncomment the line “sql” in each of them.

Similarly, open up another config file (/etc/raddb/sql/mysql/counter.conf) and append the following lines to it.

sqlcounter noresetcounter {
counter-name = Session-Timeout
check-name = Session-Timeout
reply-name = Session-Timeout
sqlmod-inst = sql
key = User-Name
reset = never
query = "SELECT SUM(Acctsessiontime) FROM radacct WHERE UserName='%{%k}'"
sqlcounter max_all_mb {
counter-name = Max-All-MB
check-name = Max-All-MB
reply-name = ChilliSpot-Max-Total-Octets
sqlmod-inst = sql
key = User-Name
reset = never
query = "SELECT SUM(AcctInputOctets)/(1024*1024) + SUM(AcctOutputOctets)/(1024*1024) FROM radacct WHERE UserName='%{%k}'"

Let’s do the last necessary modification for config file /etc/raddb/sql.conf.  Find a section called “sql“, which should be modified to look like this:

database = "mysql"
driver = "rlm_sql_${database}"
server = "localhost"
#port = 3306
login = "easyhotspot"
password = "easyhotspot"
radius_db = "easyhotspot_opensource"

Finally, we can run freeradius. An error free output confirms that all of our configurations are correct and working. Otherwise, we should get back to correcting our configurations until we get it running correctly.

[root@coovachilli ~]# radiusd -X
Setting Up CoovaChilli

First of all, we need to download the source code of CoovaChilli to our system. We can do this by downloading a tarball from Coova’s download page or by cloning Coova’s repository from Github.  If we choose to install it from tarball package, we need to perform following tasks:

[root@coovachilli ~]# wget
[root@coovachilli ~]# tar -xzvf coova-chilli-1.3.0.tar.gz
[root@coovachilli ~]# cd coova-chilli-1.3.0
[root@coovachilli coova-chilli-1.3.0]# ./configure

While configuring this source package, it is highly necessary to have GCC installed. GCC is a compiler for C and C++ based programs. To install GCC in CentOS or RHEL, enter this command:

[root@coovachilli coova-chilli-1.3.0]# yum -y install gcc

Then, try again to configure the source code, and if it succeeds, we can make it for installation.

[root@coovachilli coova-chilli-1.3.0]# ./configure
[root@coovachilli coova-chilli-1.3.0]# make

When trying to make this compilation, I ran into an error saying “cc1: warnings being treated as errors/treat warring as error“. After some research, I learned that removing an argument “–Werror” from the files and inside src directory can resolve this issue. We can manually open these two files using editor like vi, find the required argument and delete it. Or, we can use “sed” utility for this purpose.

[root@coovachilli coova-chilli-1.3.0]# sed -i 's/--Werror//g' src/
[root@coovachilli coova-chilli-1.3.0]# sed -i 's/--Werror//g' src/

After this small fix, we can run the make and make install tasks to complete the installation.

[root@coovachilli coova-chilli-1.3.0]# make; make install

Next, we need to create necessary soft links for various files and directories belonging to CoovaChilli inside the standard CentOS system directories. Doing this will allow the system to access CoovaChilli’s components easily and effectively.

[root@coovachilli coova-chilli-1.3.0]# ln -s /usr/local/etc/chilli /etc/
[root@coovachilli coova-chilli-1.3.0]# ln -s /usr/local/etc/chilli.conf /etc/
[root@coovachilli coova-chilli-1.3.0]# ln -s /var /usr/local/
[root@coovachilli coova-chilli-1.3.0]# ln -s /usr/local/sbin/chilli /sbin/
[root@coovachilli coova-chilli-1.3.0]# ln -s /usr/local/etc/init.d/chilli /etc/init.d/
[root@coovachilli coova-chilli-1.3.0]# ln -s /usr/local/sbin/chilli_response /sbin/
[root@coovachilli coova-chilli-1.3.0]# ln -s /usr/local/sbin/chilli_query /sbin/
[root@coovachilli coova-chilli-1.3.0]# ln -s /usr/local/sbin/chilli_opt /sbin/
[root@coovachilli coova-chilli-1.3.0]# ln -s /usr/local/sbin/chilli_radconfig /sbin/

Now that our CoovaChilli is successfully installed, we need to modify few configuration files according to our needs and environment. First, let’s configure CoovaChilli’s defaults configuration file. Values set in this file enables CoovaChilli to adapt to our host environment and to fulfill our objectives. My configuration looks like this:

[root@coovachilli ~]# vi /etc/chilli/defaults
HS_WANIF=eth0 # WAN Interface toward the Internet
HS_LANIF=eth1 # Subscriber Interface for client devices
HS_NETWORK= # HotSpot Network (must include HS_UAMLISTEN)
HS_NETMASK= # HotSpot Network Netmask
HS_UAMLISTEN= # HotSpot IP Address (on subscriber network)
HS_UAMPORT=3990 # HotSpot UAM Port (on subscriber network)
HS_UAMUIPORT=4990 # HotSpot UAM "UI" Port (on subscriber network, for embedded portal)
# HotSpot settings for simple Captive Portal
HS_RADSECRET=easyhotspot # Set to be your RADIUS shared secret
HS_UAMSECRET=easyhotspot # Set to be your UAM secret
# The server to be used in combination with HS_UAMFORMAT to
# create the final chilli 'uamserver' url configuration.
# Firewall Ports to be allowed
HS_TCP_PORTS="80 443"
# Standard Configurations
# Directory containing internal web pages
# For 'haseurl'
HS_LOC_NAME="My HotSpot" # WISPr Location Name and used in portal

I understand that this is pretty long and complex configuration. If you don’t fully get it, but still want to setup CoovaChilli, you can simply copy and paste my configuration file with simple changes like interface names, hotspot network information, and so on.

Once our defaults file is ready, we can tell CoovaChilli to use this configuration by simply copying this file in the same directory with the name of config.

[root@coovachilli ~]# cp /etc/chilli/defaults /etc/chilli/config

Then, let’s modify the startup or init file for CoovaChilli. To do so, we can open the init file (/etc/init.d/chilli) in vi editor and navigate to the line number 78, which we should modify to look like this:

/usr/local/sbin/chilli -c $CONFIG --pidfile=$pidfile --coaport 3799 &

Now, let’s permit port 80 from our iptables firewall so that wireless clients can access web captive portal in this server.

[root@coovachilli ~]# vi /etc/sysconfig/iptables

Inside this file, add the following line above any reject statement.

-A INPUT -m state --state NEW -m tcp -p tcp --dport 80 -j ACCEPT

Similarly, we need to add an iptables entry to another config file for Chilli as below:

[root@coovachilli ~]# echo "iptables -I POSTROUTING -t nat -o $HS_WANIF -j MASQUERADE" >> /etc/chilli/

Doing this will allow the system to Masquerade or serve many-to-one NAT for wireless clients via our external network facing (eth0) interface. This means that all of the hotspot users will be represented by the IP address we set in eth0 interface throughout the external network. This is not an ideal option if we want full network visibility across all hotspot users. So, I’m taking another way to handle this issue. In this case, I don’t  enable Masquerade across my eth0 interface, instead I set this interface’s IP as the default gateway for hotspot network (which is done by default). In the other hand, I set a static route in my router or gateway device to reach my hotspot network with the next hop address of the same interface’s IP. Doing this will enable both the hotspot and external network users to reach each other.

To complete the installation, let’s enable CoovaChilli to start at system boot.

[root@coovachilli ~]# chkconfig --level 235 chilli on

This completes our installation. We can now reboot our system to implement the changes. After reboot, all components of our newly prepared hotspot system should be up and running. We can verify this by looking at the interfaces available in our system. The presence of “tun0” interface confirms that our coovachilli setup is working properly.

[root@coovachilli ~]# ifconfig tun0
tun0 Link encap:UNSPEC HWaddr 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00
    inet addr: P-t-P: Mask:
    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:100
    RX bytes:0 (0.0 b) TX bytes:0 (0.0 b)

We can then get into the admin or cashier panel of EasyHotspot to manage accounts for our guest users. The below screenshots show the homepage and Accounts list. I’ve done some minor modifications to EasyHotspot’s CSS, so it looks a little different.

EasyHotspot - Home Page
EasyHotspot – Home Page

Listing existing postpaid user accounts from Cashier menu.

EasyHotspot Cashier - Account List
EasyHotspot Cashier – Account List

From the above screenshot, it is evident that we can add new postpaid account manually by entering user’s fullname, username, password, bill by type, and valid until. If you remember the overview of this project, I had mentioned that our client needed to have hundred of thousands of guest users in their hotspot system. So, adding every user manually isn’t a viable option here.

To address this need, I’ve prepared a PHP script which will add postpaid account users for all of these guest users. For this purpose, I required a list containing fullname and account number (or its last four digits) of all guest users. Currently, my script requires a CSV file containing the full name and account number only, which was exported from our client’s database. My objective was to create a username with first name and the first two letters of surname. Similarly, I needed to create a hotspot password for a user by taking out last four digits of the account number.

Here’s my script written in PHP.

vi generate-postpaid-acts.php
# Author: Sajjan Bhattarai
# Date: 8 Feb 2016

# Defining username and password for mysql
$db_user = "root";
$db_pass = "[your-mysql-password]";
$conn = mysql_connect("", $db_user, $db_pass);
if (! $conn) {
    die ("Could not connect!");

# Reading CSV File
$row = 1;
if (($handle = fopen("users.csv", "r")) !== FALSE) {
    while (($data = fgetcsv($handle, 1000, ",")) !== FALSE) {
        $num = count($data);
        $name = explode(" ", $data[0]);
        $firstname = $name[0];
        $lastname = $name[1];
        $userid = strtolower($firstname) . strtolower(substr($lastname,0, 2 ));
        $password = substr($data[1], -4);
        # echo $userid . " : " . substr($data[1], -4) . "\n";
        $sql = "INSERT INTO postpaid_account (realname, username, password, bill_by, created_by, IdleTimeout, valid_until) VALUES ( '$data[0]', '$userid', '$password', 'time', 'admin', 0, 'March 8 2016 24:00:00')";
        $sql2 = "INSERT INTO radcheck (username, attribute, op, value) VALUES ('$userid', 'Expiration', ':=', 'March 8 2016 24:00:00')";
        $sql3 = "INSERT INTO radcheck (username, attribute, op, value) VALUES ('$userid', 'Simultaneous-Use', ':=', '1')";
        $sql4 = "INSERT INTO radcheck (username, attribute, op, value) VALUES ('$userid', 'Cleartext-Password', ':=', '$password')";

        $results = mysql_query($sql, $conn);
        $results2 = mysql_query($sql2, $conn);
        $results3 = mysql_query($sql3, $conn);
        $results4 = mysql_query($sql4, $conn);

        if(! $results || !$results2 || !$results3 || !$results4) {
            die('Could not insert data: ' . mysql_error() . "\n");


echo "\nInserted data successfully! \n";

Note that this script takes “users.csv” file to read guest users’ fullnames and account numbers. You can modify this script according to your needs. To execute this script, enter following commands:

[root@coovachilli ~]# chmod u+x generate-postpaid-acts.php
[root@coovachilli ~]# ./generate-postpaid-acts.php

Running this script will take all users’ information from “users.csv”, convert them into required login credentials, and then insert the final information into the easyhotspot’s database. We can see in the script above that I’m inserting information into two different database tables (postpaid_account and radcheck). While inserting into radcheck table, I’m entering three different parameters (Expiration, Simultanious Use and Cleartext-Password) for each user entry.

I hope you found this article informative. Please let me know in the comment section if you have any query or suggestion. Looking forward to hearing from you.