Thursday, September 3, 2015

How to install a wireless hotspot with captive page on Linux using CoovaChilli

The purpose of this article is to demonstrate how you can turn a Linux based computer or laptop into a wireless hotspot where users can be authenticated via a captive portal page. For this task, the primary controller software will be CoovaChilli. This software is an ideal hotspot management solution for hotels, restaurants, supermarkets, parks, and any place offering WiFi Internet.


  • A Linux distribution. In this article, I will be using Fedora 20. Later versions 21/22 should work fine.
  • Development libraries for needed for source package compilations.
  • A working MySQL server installation.
  • A wired network device that connects to the Internet.
  • Ability to run sudo commands.
  • A wireless network device that supports Access Point mode. To see if your wireless device supports AP mode run:
    sudo iw phy |grep -A 5 -i 'Supported interface modes' | grep '*'

Install CoovaChilli dependencies

yum install libnl3-devel libtalloc-devel iptables

Install hostapd

Hostapd allows your computer to function as an Access Point (AP) WPA/WPA2 Authenticator. Other functionalities include Radius authentication services, although we'll not use that here.
Most Linux distributions (including Fedora) have pre-packaged versions of hostapd and can be installed using te package management software. For example in Fedora, CentOS and other Red-Hat based Linux distros, a simple command will install this package:
yum install hostapd
However, to install the latest version of hostpad, we will need to download and compile the sources. This can be done easily as follows:
cd /usr/src
sudo git clone git://
This will download both hostapd the server daemon, and wpa_supplicant sources. We are interested in the former, so will change to the hostapd sources:
cd hostap/hostapd
Hostapd does not have a 'configure' command, so before we compile hostapd, we need to change the install prefix. A a quick and simple way to change the default install directory is by using sed:
sed -i “s:export BINDIR ?= /usr/local/bin/:export BINDIR ?= /usr/sbin:g” Makefile
Next, copy default config file:
cp -v defconfig .config
we'll need to change some defaults in the configuration file:
vim .config
Uncomment the following options:

CONFIG_LIBNL32=y # Use libnl 3.2 libraries
CONFIG_IEEE80211N=y # Enables IEEE 802.11n support
CONFIG_WNM=y # Enables Network Management support
CONFIG_IEEE80211AC=y # Enables IEEE 802.11ac support
CONFIG_DEBUG_FILE=y # Support for writing debug log to file
Run make and install:
sudo make install
To check if hostapd is properly installed, run:
hostapd -v
The above command will show you the version and credits

Configure hostapd

Create hostapd config file using sample file:
sudo mkdir /etc/hostapd
sudo cp -v /usr/src/hostap/hostapd/hostapd.conf /etc/hostapd/
sudo vim /etc/hostapd/hostapd.conf
Change the following parameters in hostapd.conf file:

interface=wlan0 # Change this to your wireless device
ssid=KAMPALA-3 # Change this to your SSID
channel=6 # Enter your desired channel
ieee80211n=1 # Enable IEEE 802.11n
wpa_pairwise=TKIP CCMP
Create directory for hostapd sockets:
sudo mkdir /var/run/hostapd
Set status of WiFi interface to 'UP' and unblock Wifi if soft switch is on:
sudo rfkill unblock wifi
sudo ip link set dev wlan0 up
Test and start hostapd:
sudo hostapd -d /etc/hostapd/hostapd.conf
If all goes well, the hostapd daemon should start and not quit.
Next, create a systemd service file. By now, most Linux distributions use systemd to control services:
sudo vim /etc/systemd/system/hostapd.service
Description=Hostapd IEEE 802.11 AP, IEEE 802.1X/WPA/WPA2/EAP/RADIUS Authenticator

ExecStartPre=/bin/mkdir -p /var/run/hostapd
ExecStart=/usr/sbin/hostapd /etc/hostapd/hostapd.conf -P /var/run/ -B

Enable the service to start automatically at boot:
sudo systemctl enable hostapd.service


Since we will require clients to authenticate before accessing the Internet, installation of a radius server is needed. FreeRadius is an open source based radius server. It can also be installed using your favorite Linux package manager such as yum or apt. But since we want to install the latest version, we'll compile from source.

Download freeradius:
cd /tmp/
wget -c
Unpack sources and change to install location:
sudo tar jxvf freeradius-server-3.0.9.tar.bz2 -C /usr/src/
cd /usr/src/freeradius-server-3.0.9
Run configure script ensuring that you use the correct prefix and library path for your setup:
sudo ./configure --prefix=/usr --libdir=/usr/lib64 --sysconfdir=/etc --localstatedir=/var/ --enable-fast-install=no
Proceed to compile and install:
sudo make
sudo make install
If you run into the following error
mkdir: cannot create directory ‘/etc/raddb/’: File exists
make: *** [/etc/raddb/] Error 1
Run the following, to fix it:
rmdir /etc/raddb
make install && make install
Add radiusd group and user:
sudo groupadd -r radiusd
sudo useradd -r -M -c "Radius Server User" -g radiusd radiusd -s /sbin/nologin

Confgure freeradius MySQL tables

Start MySQL server if it is not running. As mentioned above, initialization process is via systemd, so:
sudo systemctl -q is-active mysqld.service || sudo systemctl start mysqld.service
Make sure service start even at boot:
sudo systemctl enable mysqld.service
Create radius database:
mysqladmin -u root -p[MYSQL_ROOT_PASSWORD] create radius
Generate database tables using MySQL schema:
sudo cat /etc/raddb/mods-config/sql/main/mysql/schema.sql | mysql -u root -p[MYSQL_ROOT_PASSWORD] radius
Create MySQL radius user and set privileges on radius database:
mysql -u root -p[MYSQL_ROOT_PASSWORD] radius

Configure the SQL radius module:
sudo vim /etc/raddb/mods-available/sql
Uncomment and or change the following parameters:

driver = "rlm_sql_mysql"
dialect = ”mysql”
server = "localhost"
port = 3306
read_clients = yes
Add chillispot SQL counters:
sudo vim /etc/raddb/mods-available/sqlcounter
Add this line at the end of the above file:

$INCLUDE ${modconfdir}/sql/counter/${modules.sql.dialect}/chillispot.conf
Next link sql, sqlcounter to modules available:
sudo ln -s /etc/raddb/mods-available/sql /etc/raddb/mods-enabled/sql
sudo ln -s /etc/raddb/mods-available/sqlcounter /etc/raddb/mods-enabled/sqlcounter
Configure radius clients
sudo vim /etc/raddb/clients.conf
Change the password to the password used above for FreeRadius MySQL database:

Configure radius server:
sudo vim /etc/raddb/radiusd.conf
Under security section, change the user and group to name created during install:
user = radiusd
group = radiusd 
allow_vulnerable_openssl = yes
IMPORTANT: Don't do this. You really should update to recent versions of OpenSSL
Under the instantiate section (Near line 728), add the following counter modules:
Configure the default virtual server under sites-available:
sudo vim /etc/raddb/sites-available/default
Under authorize section:

Comment the following:
Uncomment the following:

Change the following:
'-sql' to sql
Add the following at the end of authorize section:
Next under accounting section, Uncomment the following:
Changethe following:
'-sql' to sql
Next under session section, Uncomment the following:
Next under post-auth section, Uncomment the following:
Change the following:
'-sql' to sql
Configure the inner tunnel requests virtual server under sites-available:
sudo vim /etc/raddb/sites-available/inner-tunnel
Under authorize section, change the following:
'-sql' to sql
Add the following at the end of authorize section:
Next under the session section, Uncomment the following:
Next under post-auth section, Uncomment the following:
Change the following:
'-sql' to sql
Add the following MySQL counters for Chillispot:
sudo vim /etc/raddb/mods-config/sql/counter/mysql/chillispot.conf
sqlcounter chillispot_max_bytes {
counter_name = Max-Total-Octets
check_name = ChilliSpot-Max-Total-Octets
reply_name = ChilliSpot-Max-Total-Octets
reply_message = "You have reached your bandwidth limit"
sql_module_instance = sql
key = User-Name
reset = never
query = "SELECT IFNULL((SUM(AcctInputOctets + AcctOutputOctets)),0) FROM radacct WHERE username = '%{${key}}' AND UNIX_TIMESTAMP(AcctStartTime) + AcctSessionTime > '%%b'"
Change ownership of config and log directories:
sudo touch /var/log/radius/radutmp
sudo chown -R radiusd:radiusd /etc/raddb
sudo chown -R radiusd:radiusd /var/log/radius
Create Admin User in radius MySQL database:
echo "INSERT INTO radcheck (UserName, Attribute, Value, Op) VALUES ('[ADMIN_USER]', 'Cleartext-Password', '[ADMIN_PASSWORD]', ':=');" | mysql -u radius -p[FREERADIUS_DB_PASS] radius
Start radius for initialization and testing purposes
sudo /usr/sbin/radiusd -X
Open a new terminal window to test connections:
If you get a message like this one, then you are done with the minimal and required radius setup for the next steps:
Received Access-Accept Id 174 from to length 20
But before leaving radius aside, create a systemd service file for your radius server:
sudo vim /etc/systemd/system/radiusd.service
Description=FreeRADIUS high performance RADIUS server.
ExecStartPre=-/bin/mkdir /var/log/radius
ExecStartPre=-/bin/mkdir /var/run/radiusd
ExecStartPre=-/bin/chown -R radiusd.radiusd /var/log/radius
ExecStartPre=-/bin/chown -R radiusd.radiusd /var/run/radiusd
ExecStartPre=/usr/sbin/radiusd -C
ExecStart=/usr/sbin/radiusd -d /etc/raddb
ExecReload=/usr/sbin/radiusd -C
ExecReload=/bin/kill -HUP $MAINPID
Enable the service to start automatically at boot:
sudo systemctl enable radiusd.service

Install Haserl

Haserl is needed for the embedded miniportal included in CoovaChilli.
Download haserl:
cd /tmp
wget -c
Upack the tarball:
sudo tar zxvf haserl-0.9.35.tar.gz -C /usr/src/
cd /usr/src/haserl-0.9.35/
Compile and install:
./configure --prefix=/usr –libdir=/usr/lib64
(Make sure you change to correct library or desired prefix)
sudo make install

Install CoovaChilli

CoovaChilli is an open source based captive portal software. It started out from the deprecated chilli project. After installation and configuration of coovachilli is done, you will be able to redirect your WiFi hotspot clients to a login page, i.e. captive portal where they can log in and access the Internet.
Download the latest sources for coovachilli:
cd /usr/src
sudo git clone
Configure and Compile coova :
cd /usr/src/coova-chilli
sh bootstrap
./configure --prefix=/usr --libdir=/usr/lib64 --localstatedir=/var --sysconfdir=/etc --enable-miniportal --with-openssl --enable-libjson --enable-useragent --enable-sessionstate --enable-sessionid --enable-chilliredir --enable-binstatusfile --enable-statusfile --disable-static --enable-shared --enable-largelimits --enable-proxyvsa --enable-chilliproxy --enable-chilliradsec --with-poll
(Make sure you change to correct library or desired prefix)
sudo make install

Configure CoovaChilli

All configuration files are located under: /etc/chilli. You will need to create a config file with your sites modifications as follows:
sudo cp -v /etc/chilli/defaults /etc/chilli/config
sudo vim /etc/chilli/config
Change the following parameters to match your environment:

HS_WANIF=eth0 # WAN Interface toward the Internet
HS_LANIF=wlan0 # 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_RADSECRET=[FREERADIUS_DB_PASS] # Set to be your RADIUS shared secret
Add the chilli script. The purpose of these script is to prepare the system to act as a router.  You may also wish to add other commands e.g. Setting the gateway.
sudo vim /etc/chilli/
# Allow IP masquerading through this box
/usr/sbin/iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
IMPORTANT: Change the Internet device to the correct one.
Make script executable:
sudo chmod 755 /etc/chilli/
Enable coovachilli so it starts up at boot time:
sudo systemctl enable chilli
Start coovachilli:
sudo systemctl start chilli

Testing your captive portal

Before you begin testing, make sure you can first access the internet locally.

Then using a wireless client like smartphone or laptop, open your favourite web browser. Go to any URL/ website of your choice.

If your followed the above steps, then you will be redirected to the captive portal page as shown below:

User Management

To add users so they can access the Internet using your hotspot, run the following command for each user.  You can automate it using a script if you wish.
echo "INSERT INTO radcheck (UserName, Attribute, Value, Op) VALUES ('[LOGIN_NAME]', 'Cleartext-Password', '[LOGIN_PASSWORD]', ':=');" | mysql -u radius -p[FREERADIUS_DB_PASS] radius
That's it folks!
Follow me at: @jzikusooka

No comments:

Post a Comment