Transform Raspberry Pi in hot spot Wifi with captive portal (2/2)

For an automatic install of the hotspot, read this post.

In a previous article, We had installed our own Wifi access point. Now it comes to add a captive portal to control who will use it. Hotspot_WiFiTo a captive portal you have several options :

  1. The simple method is passing through a PHP page. You can display a message in an HTML page, wait for an and then allow access to Internet.
  2. The more complex method where you go through a specialized tool as for example YFi Hotspot Manager.

Each method has much on its advantages and disadvantages but initially I chose simplicity and only control basic way Internet access. It will be through a PHP page.

A captive portal in PHP

  1. Install Nginx with PHP support. The simplest is to follow the instructions of this article. Here is my server configuration :
    server {
    	root /var/www;
    	index index.php;
    	server_name localhost;
    	location / {
    		try_files $uri $uri / index.php;
    	location ~ .php$ {
    		fastcgi_split_path_info ^(.+\.php)(/.+)$;
    		fastcgi_pass unix:/var/run/PHP5-fpm.sock;
    		fastcgi_index index.php;
    		include fastcgi_params;
  2. Install additional packages :
    apt-get install conntrack
  3. Allow the user www - data to perform the commands required to manage access :
    Launch visudo then add the following lines at the end of the file :
  4. www-data ALL=NOPASSWD: /usr/sbin/arp
    www-data ALL=NOPASSWD: /sbin/iptables
    www-data ALL=NOPASSWD: /usr/bin/rmtrack [0-9]*.[0-9]*.[0-9]*.[0-9]*
  5. Create the home page index.php

    $ip = $_SERVER[‘REMOTE_ADDR’];
    $mac = shell_exec("sudo /usr/sbin/arp -an " . $ip);
    preg_match(‘/..:..:..:..:..:../’,$Mac , $matches);
    $mac = @$matches[0];
    if( $mac === NULL) { echo "Access Denied."; exit; }

    <form action="process.php" method="post">
    <input name="mac" type="input" value="<?php echo $mac; ?>" />
    <input name="ip" type="input" value="<?php echo $ip; ?>" />
    <input style="padding: 10px 20px;" type="submit" value="OK" />


  6. Create the page that will generate the rules to allow access to the Internet process.php. When the user has validated the form on the previous page, It is she who will be called to give full access.
  7. Create the set of routing rules
    iptables -t mangle -N internet
    iptables -t mangle -A PREROUTING -i wlan0 -p tcp -m tcp --dport 80 -j internet
    iptables -t mangle -A internet -j MARK --set-mark 99
    iptables -t nat -A PREROUTING -i wlan0 -p tcp -m mark --mark 99 -m tcp --dport 80 -j DNAT --to-destination
  8. Save the rules for the next few reboots
    service iptables-persistent


Here you are ! An access point with a captive portal. You can edit PHP pages to change the look and features. A database could, for example, memorize the MAC addresses to not ask the connection, manage a connection time, a volume, etc.

Sources :

You may also like...