pfSense English Support > Captive Portal

[HOWTO] Captive portal + FreeRADIUS + local MySQL user friendly single step

(1/30) > >>

03 May 2017:
- New version 0.48 has php-mysqli requirements
29 Nov 2016:
- Added watchdog install
26 May 2016:
- Added new pkg procedure for 2.3 final and post 2.3 releases


I've written a captive portal wrapper that creates the FreeeRADIUS user account and logs in in one step, all with bootstrap responsive code and validation, with configurable language that suits for hotels and public wifi providers.
Here's the full howto:

1 Introduction

pfSense-cp-auth-onestep is a project that aims to provide a captive portal interface for pfSense 2.x (currently tested on 2.2.x and 2.3-beta) that doesn't require the creation of a user account.

In fact, when a user registers, it creates the RADIUS user account and then logs in with that account.

A demo can be found at the following address:
The latest doc can be found here:

Initial work based on the excellent work of khan:

2 Preparation of pfSense

In order to work, pfSense needs the following packages: FreeRADIUS, Cron.

Also, some upstream packages are required in order to work.

First we need to fetch some upstream packages:

Additional steps for pfSense 2.3

The repository management has changed in pfSense 2.3, and by default the FreeBSD repository is disabled.

You must edit the file /usr/local/etc/pkg/repos/pfSense.conf and set the following value:

--- Code: ---FreeBSD: { enabled: yes }
--- End code ---

Additional steps after 2.3 final release

You must also edit file /usr/local/etc/pkg/repos/FreeBSD.conf and set the following value:

--- Code: ---FreeBSD: { enabled: yes }
--- End code ---

ATTENTION: Once the packages are installed with pkg command, please set this value to 'no' again so updates won't interfere with pfSense normal functionality.

Installation of packages:

--- Code: ---pkg
pkg update
pkg install nano git
--- End code ---

If your pkg doesn't find the packages, you may need to reinit the pkg database with

--- Code: ---rm -f /var/db/pkg/*.sqlite
--- End code ---

After this, pkg update should reinitialize the pkg database.

2.1 Installation of MySQL

Although MySQL should be installed on a separate machine, it's convenient to have a single pfSense box doing the whole authentication.

Installation of MySQL isn't supported by pfSense, so you'll have to redo the following steps after every update.

2.1.1 pfSense 2.2 steps

MySQL installation

--- Code: ---pkg install mysql56-server
pkg install compat8x-amd64
--- End code ---

PHP support

--- Code: ---touch /etc/php_dynamodules/mysql
--- End code ---

The following command should output mysql and mysqlnd.

--- Code: ---php -m | grep mysql
--- End code ---

2.1.2 pfSense 2.3 steps

MySQL installation

--- Code: ---pkg install mysql56-server
pkg install compat9x-amd64
pkg install php56-mysql
--- End code ---

Since v0.48 of the captive portal version, mySQL queries are done via prepared statements using mysqli.
If using pfSense-cp-onestep-auth v0.48 or higher, please replace php56-mysql package with php56-mysqli.

PHP support

The following command should output mysql and mysqlnd.

--- Code: ---php -m | grep mysql
--- End code ---

2.1.3 Common steps

We need to allow the MySQL service to start.

--- Code: ---echo 'mysql_enable="YES"' > /etc/rc.conf
--- End code ---

Also, pfSense won't start services unless their name finishes by “.sh”

--- Code: ---mv /usr/local/etc/rc.d/mysql-server /usr/local/etc/rc.d/
--- End code ---

2.1.4 MySQL startup fix

For whatever, pfSense won't start MySQL sometimes. If you have a tip, please tell.

In order to fix this, create the following file /usr/local/bin/

--- Code: ---#!/usr/bin/env sh 

service / status > /dev/null
if [ $? != 0 ]; then
        service start
--- End code ---

Render the file executable

--- Code: ---chmod +x /usr/local/bin/
--- End code ---

Install the cron package and add the following entry:

--- Code: ---*/1 * * * * root /usr/local/bin/
--- End code ---

After this, we may launch the mysql service

--- Code: ---service start
--- End code ---

Also, as FreeRADIUS may start before mysql and fail, install watchdog service and set it up to restart FreeRADIUS.

Secure your installation by running the following command and change your root password

--- Code: ---/usr/local/bin/mysql_secure_installation
--- End code ---

Optionnaly, you may create the following password file /root/.my.cnf

--- Code: ---[client]
--- End code ---

2.2 FreeRADIUS setup

2.2.1 FreeRADIUS installation

Install the FreeRADIUS2 package via System > Packages > Available

In Services > FreeRADIUS > Users

Add a user called: testu

Set it's password: testp

in Services > FreeRADIUS > NAS / Clients

Add a NAS user:


Client Shortname: tester

Shared Secret: SuperTest (replace this with a good password)

In Services > FreeRADIUS > Interface

Add the interface the RADIUS server should listen on:

You can now check in Status > System Logs that the server is active

--- Quote ---Sep 29 14:54:50   radiusd[10330]: Loaded virtual server <default>
Sep 29 14:54:50   radiusd[13493]: Ready to process requests.
--- End quote ---

Connect to pfSense via ssh or console and check if FreeRADIUS authenticates (replace SuperTest with your Shared Secret):

--- Code: ---radtest testu testp 0 SuperTest
--- End code ---

The answer should look like:

--- Quote ---Sending Access-Request of id 108 to port 1812
        User-Name = "testu"
        User-Password = "testp"
        NAS-IP-Address =
        NAS-Port = 0
        Message-Authenticator = 0x00000000000000000000000000000000
rad_recv: Access-Accept packet from host port 1812, id=108, length=20
--- End quote ---

Check authentication in Status > System Logs

--- Code: ---Sep 29 15:04:51 radiusd[22223]: Login OK: [testu] (from client pfSense port 0)
--- End code ---

#TIP: See for tuning and troubleshooting

2.2.2 MySQL FreeRADIUS integration

First we need to create the RADIUS database. Launch the “mysql” program. If you didn't create the /root/.my.cnf password file, launch “mysql -p” and execute the following statements:

--- Code: ---CREATE DATABASE  `radius`;
--- End code ---

We also have to get a copy of the sql files needed for the captive portal.

You can fetch them via wget at or directly via git:

--- Code: ---cd /root
git clone
cd /root/pfSense-cp-auth-onestep/sql
--- End code ---

We need to integrate every .sql file into the radius database. Please execute the admin.sql file at last because it contains definitions for the other files. Add “-p” to myql if you don't have created the password file.

Before running those commands, modify the admin.sql file in order to replace the default password 'radpass'. (Use vi or nano if installed).

--- Code: ---mysql radius < cui.sql
mysql radius < nas.sql
mysql radius < radippool.sql
mysql radius < schema.sql
mysql radius < wimax.sql
mysql radius < reg_users.sql
mysql radius < admin.sql
--- End code ---

Activate SQL support in Services > FreeRADIUS > SQL:

Enable SQL Support: Enable

Enable SQL Authorization: Enable

Enable SQL Accounting: Enable

Enable SQL Session: Enable

Enable SQL Post-Auth: Enable

Server IP Address -->

Server Port --> 3306

Server Database -> radius

Server User -> radius

Server Password -> radpass (replace with your database password).

MySQL authentication test

Execute the following command (replace SuperTest with your Shared Secret):

--- Code: ---radtest testu testp 0 SuperTest
--- End code ---

The radpostauth table should contain the authentication info:

--- Code: ---mysql -p -e "SELECT * FROM radpostauth;" radius
--- End code ---

--- Quote ---+----+----------+-------+---------------+---------------------+
| id | username | pass  | reply         | authdate            |
|  1 | testu    | testp | Access-Accept | 2015-09-29 15:13:24 |
--- End quote ---

2.3 Enable captive portal

2.3.1 Setup

Grab a copy of the pfSense-pfcp-auth-onestep files via github or via the following link

Uncompress the file and edit captiveportal-config.php to meet your settings, especially the database password.

Create a new zone in Services > Captive Portal . Example “PUBLICWIFI”

In Services > Captive Portal > File Manager, upload all the files from pfSense-pfcp-auth-onestep beginning with “captiveportal-*”

The following files need to be uploaded:

--- Quote ---captiveportal-bootstrap.min.css
--- End quote ---

#TIP: I had trouble with uploading the files in pfSense 2.2.6. After every 3 files, I had to restart WebConfigurator via ssh.

We Can now enable the captive portal on the LAN interface or whatever interface you need.

We also need to activate RADIUS authentication:


Port: 1812

Shared Secret: SuperTest (or your Shared Secret)

Radius Protocol: PAP

Account Check:

Send RADIUS accounting packets: Enable

Port: 1813

Accounting updates: stop/start accounting (FreeRADIUS if available)

RADIUS NAS IP attribue: LAN IP (or whatever interface you selected)

Portal page contesnts: Upload file ozy-captive.php

Redirection URL: Whatever you'd like, example:

2.3.2 Testing

Once enabled, you can open a browser and enter any domain. You should end on the captive portal page.

You may access directly to the captive portal via http://[pfSenseIP]:8002

#TIP: Your computer should use DHCP and use the pfSense IP as DNS server or the redirection won't work.

If the redirection still doesn't work, check that the DNS Resolver service is running without the forwarding mode.

Also, if your computer already has the domain in DNS cache, you may have to flush dns cache.

On Linux:

--- Code: ---service nscd restart
--- End code ---

On Windows:

--- Code: ---ipconfig /flushdns
--- End code ---

At least, close and reopen your browser so it would make a new DNS query.

Fell free to help improve this howto.


Thanks deajan for the post with detailed information to implement self signed captive portal. My CP was working fine in 2.2 now I can´t install needed packages.
pkg version (pkg -v) is 1.6.2, pkg install mysql56-server creates a loop with these messages

--- Code: ---Updating FreeBSD repository catalogue...
FreeBSD repository is up-to-date.
Updating pfSense-core repository catalogue...
pfSense-core repository is up-to-date.
Updating pfSense repository catalogue...
pfSense repository is up-to-date.
All repositories are up-to-date.
New version of pkg detected; it needs to be installed first.
Checking integrity... done (0 conflicting)
The most recent version of packages are already installed

--- End code ---
I´ve tried pkg install pkg-1.7.2 with the same result


This is more a pfSense than a captive portal problem.
Are you still running V2.2 ?

Check the contents of /usr/local/etc/pkg/pfSense.conf and see if FreeBSD is enabled (disable it after installing mysql).

Thanks so much Deajan for this code! I just wanted to give a heads up that I ran into an issue with the firmware 2.3-RELEASE. When data was submitted I was getting a Fatal error: Call to undefined function mysql_connect(). I was pushing this data to a remote Mysql server.

After looking around I found out from a post that php56-mysql needs to be installed manually on 2.3 with
--- Code: ---pkg install php56-mysql
--- End code ---
See this post

I think I wrote about this in section 2.1.2.
Anyway, thanks for the feedback.


[0] Message Index

[#] Next page

Go to full version