1 (edited by ajauberg 2009-01-20 22:39:48)

Topic: [HOWTO] Setting up OpenWRT as a captive portal on WRT54GL

[HOWTO] Setting up OpenWRT as a captive portal on WRT54GL

This howto explains using a WRT54GL with OpenWRT as a captive portal for controlling user access to the Internet.
The configuration of a remote wireless router for repeating the signal is also shown.

In addition to OpenWRT the Freeradius and Chillispot packages are used.

At present this configuration only covers NVRAM settings on Whiterussian.
Do also note that the NVRAM settings can be applied on other routers than the WRT54GL,
but the interfaces for WIFI etc. may be different.


Default settings

The default bridging is set up as follows:

  (192.168.1.0/24) 
 |   |    |  |  \|/
 +--vlan0-+--+  eth1
     |           |
     +----br0----+ 
           | 
      <userspace>

- vlan0 is used for bridging all the LAN ports
- eth1 is used for the WIFI interface
- br0 is bridging the WIFI and LAN interface

* On a WRT54GL the NVRAM settings for this can be found as follows:

lan_ifname=br0
lan_ifnames=vlan0 eth1



Creating the captive portal interface

The most important thing when creating a captive portal is to create a separate interface where users
can authenticate themselves. This is done by creating a separate bridge that contains the interfaces that
we need. In the example we also want to include WDS to extend the range of our wireless network.
The 'br0' bridge is used for wireless, and we create a separate bridge 'br1' for the LAN interface:


(192.168.1.0/24)  (192.168.182.0/24) 
|   |    |  |         \|/     \|/
+--vlan0-+--+         eth1    wds
    |                  |       |
   br1                 +--br0--+
    |                      |
    |                 <Chillispot>    
    |                      | 
    |                     tun0
    +-------+    +---------+ 
            |    | 
         <userspace>

- vlan0 is used for bridging all the LAN ports
- eth1 is used for the WIFI interface
- wds is used for extending the WIFI range using WDS
- br0 is the bridge that the captive portal (Chillispot) uses
- br1 is a new bridge for the LAN interface


* The LAN interface is then configured using the new bridge:

lan_ifname=br1
lan_ifnames=vlan0


* The existing bridge is then used for the wireless interface. For every WDS client that we want to
add, we add a new wds0.xxxxx interface, starting at wds0.49153:

wifi_ifname=br0
wifi_ifnames=eth1 wds0.49153 wds0.49154 wds0.49155


* In addition, the Spanning Tree Protocol is set to avoid circular bridges when using WDS:

wifi_stp=1


* We use manual WDS and disables Lazy WDS, and adds the MAC address for all wireless routers
that we want to communicate with:

wl0_lazywds=0
wl0_wds=xx:xx:xx:xx:xx:xx yy:yy:yy:yy:yy:yy zz:zz:zz:zz:zz:zz



Installing the necessary packages

* First we need to update the ipkg directory to get a list of all our packages:

ipkg update


* Chillispot is used as our captive portal, so install it:

ipkg install chillispot


* Freeradius receives RADIUS authentication requests from Chillispot, and we use plain password authentication:

ipkg install freeradius-mod-pap


* Freeradius stores all users and attributes in a MySQL database:

ipkg install freeradius-mod-sql-mysql


* To be able to keep track of the correct time we use NTP:

ipkg install openntpd
ipkg install ntpclient


* Monit keeps track of process status, and can restart the processes if they stop

ipkg install monit


Note that all packages have dependencies, and dependant packages will be installed as well



Chillispot config

* Change the following parameters in /etc/chilli.conf:

interval 3600
pidfile /var/run/chilli.pid

radiuslisten 127.0.0.1
radiusserver1 127.0.0.1
radiusserver2 127.0.0.1
radiussecret testing123

dhcpif br0

uamserver https://www.mydomain.com/hotspotlogin.cgi
uamsecret ht2eb8ej6s4et3rg1ulp
uamallowed www.mydomain.com,www.paypal.com,paypal.com,www.paypalobjects.com,paypalobjects.com,64.4.240.0/20,216.113.160.0/19
uamanydns


* Replace the /etc/init.d/S35firewall file with the following file:

#!/bin/sh
#
# Firewall script for ChilliSpot on OpenWRT
#
# Uses $WANIF (vlan1) as the external interface (Internet or intranet) and
# $WLANIF (eth1) as the internal interface (access point).
# $LANIF is used as a trusted management interface.
#
# SUMMARY
# * All connections originating from ChilliSpot are allowed.
# * Nothing is allowed in on WAN interface.
# * Nothing is allowed in on WLAN interface.
# * Everything is allowed in on LAN interface.
# * Forwarding is allowed to and from WAN interface, but disallowed
#   to and from the WLAN interface.
# * NAT is enabled on the WAN interface.

. /etc/functions.sh

WANIF=$(nvram get wan_ifname)
WLANIF=$(nvram get wifi_ifname)
LANIF=$(nvram get lan_ifname)

IPTABLES="/usr/sbin/iptables"

for T in filter nat mangle ; do
  $IPTABLES -t $T -F
  $IPTABLES -t $T -X
done

$IPTABLES -P INPUT DROP
$IPTABLES -P FORWARD ACCEPT
$IPTABLES -P OUTPUT ACCEPT

#Allow related and established on all interfaces (input)
$IPTABLES -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT

#Allow SSH, related and established $WANIF. Reject everything else.
$IPTABLES -A INPUT -i $WANIF -p tcp -m tcp --dport   22 -j ACCEPT
$IPTABLES -A INPUT -i $WANIF -j REJECT

#Allow satellite WDSs, related and established $WLANIF. Drop everything else.
$IPTABLES -A INPUT -i $WLANIF -j DROP

#Allow 3990 on other interfaces (input).
$IPTABLES -A INPUT -p tcp -m tcp --dport 3990 --syn -j ACCEPT

#Allow everything on loopback interface.
$IPTABLES -A INPUT -i lo -j ACCEPT

#Allow everything on $LANIF
$IPTABLES -A INPUT -i $LANIF -j ACCEPT

#Drop everything to and from $WLANIF (forward)
$IPTABLES -A FORWARD -i $WLANIF -j DROP
$IPTABLES -A FORWARD -o $WLANIF -j DROP

#Enable NAT on output device.
$IPTABLES -t nat -A POSTROUTING -o $WANIF -j MASQUERADE

* Place the following login script 'hotspotlogin.cgi' on your SSL and Perl-enabled web server with domain name www.mydomain.com:

#!/usr/bin/perl

# chilli - ChilliSpot.org. A Wireless LAN Access Point Controller
# Copyright (C) 2003, 2004 Mondru AB.
#
# The contents of this file may be used under the terms of the GNU
# General Public License Version 2, provided that the above copyright
# notice and this permission notice is included in all copies or
# substantial portions of the software.

# Redirects from ChilliSpot daemon:
#
# Redirection when not yet or already authenticated
#   notyet:  ChilliSpot daemon redirects to login page.
#   already: ChilliSpot daemon redirects to success status page.
#
# Response to login:
#   already: Attempt to login when already logged in.
#   failed:  Login failed
#   success: Login succeded
#
# logoff:  Response to a logout


# Shared secret used to encrypt challenge with. Prevents dictionary attacks.
# You should change this to your own shared secret.
#$uamsecret = "ht2eb8ej6s4et3rg1ulp";

# Uncomment the following line if you want to use ordinary user-password
# for radius authentication. Must be used together with $uamsecret.
#$userpassword=1;

# Our own path
$loginpath = $ENV{'SCRIPT_URL'};

use Digest::MD5  qw(md5 md5_hex md5_base64);

# Make sure that the form parameters are clean
$OK_CHARS='-a-zA-Z0-9_.@&=%!';
$| = 1;
if ($ENV{'CONTENT_LENGTH'}) {
    read (STDIN, $_, $ENV{'CONTENT_LENGTH'});
}
s/[^$OK_CHARS]/_/go;
$input = $_;


# Make sure that the get query parameters are clean
$OK_CHARS='-a-zA-Z0-9_.@&=%!';
$_ = $query=$ENV{QUERY_STRING};
s/[^$OK_CHARS]/_/go;
$query = $_;


# If she did not use https tell her that it was wrong.
if (!($ENV{HTTPS} =~ /^on$/)) {
    print "Content-type: text/html\n\n
<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">
<html>
<head>
  <title>ChilliSpot Login Failed</title>
  <meta http-equiv=\"Cache-control\" content=\"no-cache\">
  <meta http-equiv=\"Pragma\" content=\"no-cache\">
</head>
<body bgColor = '#c0d8f4'>
  <h1 style=\"text-align: center;\">ChilliSpot Login Failed</h1>
  <center>
    Login must use encrypted connection.
  </center>
</body>
<!--
<?xml version=\"1.0\" encoding=\"UTF-8\"?>
<WISPAccessGatewayParam 
  xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"
  xsi:noNamespaceSchemaLocation=\"http://www.acmewisp.com/WISPAccessGatewayParam.xsd\">
<AuthenticationReply>
<MessageType>120</MessageType>
<ResponseCode>102</ResponseCode>
<ReplyMessage>Login must use encrypted connection</ReplyMessage>
</AuthenticationReply> 
</WISPAccessGatewayParam>
-->
</html>
";
    exit(0);
}


#Read form parameters which we care about
@array = split('&',$input);
foreach $var ( @array )
{
    @array2 = split('=',$var);
    if ($array2[0] =~ /^UserName$/) { $username = $array2[1]; }
    if ($array2[0] =~ /^Password$/) { $password = $array2[1]; }
    if ($array2[0] =~ /^challenge$/) { $challenge = $array2[1]; }
    if ($array2[0] =~ /^button$/) { $button = $array2[1]; }
    if ($array2[0] =~ /^logout$/) { $logout = $array2[1]; }
    if ($array2[0] =~ /^prelogin$/) { $prelogin = $array2[1]; }
    if ($array2[0] =~ /^res$/) { $res = $array2[1]; }
    if ($array2[0] =~ /^uamip$/) { $uamip = $array2[1]; }
    if ($array2[0] =~ /^uamport$/) { $uamport = $array2[1]; }
    if ($array2[0] =~ /^userurl$/)   { $userurl = $array2[1]; }
    if ($array2[0] =~ /^timeleft$/)  { $timeleft = $array2[1]; }
    if ($array2[0] =~ /^redirurl$/)  { $redirurl = $array2[1]; }
}

#Read query parameters which we care about
@array = split('&',$query);
foreach $var ( @array )
{
    @array2 = split('=',$var);
    if ($array2[0] =~ /^res$/)       { $res = $array2[1]; }
    if ($array2[0] =~ /^challenge$/) { $challenge = $array2[1]; }
    if ($array2[0] =~ /^uamip$/)     { $uamip = $array2[1]; }
    if ($array2[0] =~ /^uamport$/)   { $uamport = $array2[1]; }
    if ($array2[0] =~ /^reply$/)     { $reply = $array2[1]; }
    if ($array2[0] =~ /^userurl$/)   { $userurl = $array2[1]; }
    if ($array2[0] =~ /^timeleft$/)  { $timeleft = $array2[1]; }
    if ($array2[0] =~ /^redirurl$/)  { $redirurl = $array2[1]; }
}


$reply =~ s/\+/ /g;
$reply =~s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/seg;

$userurldecode = $userurl;
$userurldecode =~ s/\+/ /g;
$userurldecode =~s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/seg;

$redirurldecode = $redirurl;
$redirurldecode =~ s/\+/ /g;
$redirurldecode =~s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/seg;

$password =~ s/\+/ /g;
$password =~s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/seg;

# If attempt to login
if ($button =~ /^Login$/) {
    $hexchal  = pack "H32", $challenge;
    if (defined $uamsecret) {
    $newchal  = md5($hexchal, $uamsecret);
    }
    else {
    $newchal  = $hexchal;
    }
    $response = md5_hex("\0", $password, $newchal);
    $pappassword = unpack "H32", ($password ^ $newchal);
#sleep 5;
print "Content-type: text/html\n\n";
print "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">
<html>
<head>
  <title>ChilliSpot Login</title>
  <meta http-equiv=\"Cache-control\" content=\"no-cache\">
  <meta http-equiv=\"Pragma\" content=\"no-cache\">";
    if ((defined $uamsecret) && defined($userpassword)) {
    print "  <meta http-equiv=\"refresh\" content=\"0;url=http://$uamip:$uamport/logon?username=$username&password=$pappassword&userurl=$userurl\">";
    } else {
    print "  <meta http-equiv=\"refresh\" content=\"0;url=http://$uamip:$uamport/logon?username=$username&response=$response&userurl=$userurl\">";
    }
print "</head>
<body bgColor = '#c0d8f4'>";
  print "<h1 style=\"text-align: center;\">Logging in to ChilliSpot</h1>";
  print "
  <center>
    Please wait......
  </center>
</body>
<!--
<?xml version=\"1.0\" encoding=\"UTF-8\"?>
<WISPAccessGatewayParam 
  xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"
  xsi:noNamespaceSchemaLocation=\"http://www.acmewisp.com/WISPAccessGatewayParam.xsd\">
<AuthenticationReply>
<MessageType>120</MessageType>
<ResponseCode>201</ResponseCode>
";
    if ((defined $uamsecret) && defined($userpassword)) {
    print "<LoginResultsURL>http://$uamip:$uamport/logon?username=$username&password=$pappassword</LoginResultsURL>";
    } else {
    print "<LoginResultsURL>http://$uamip:$uamport/logon?username=$username&response=$response&userurl=$userurl</LoginResultsURL>";
    }
print "</AuthenticationReply> 
</WISPAccessGatewayParam>
-->
</html>
";
    exit(0);
}


# Default: It was not a form request
$result = 0;

# If login successful
if ($res =~ /^success$/) { 
    $result = 1;
}

# If login failed 
if ($res =~ /^failed$/) { 
    $result = 2;
}

# If logout successful
if ($res =~ /^logoff$/) { 
    $result = 3;
}

# If tried to login while already logged in
if ($res =~ /^already$/) { 
    $result = 4;
}

# If not logged in yet
if ($res =~ /^notyet$/) { 
    $result = 5;
}

# If login from smart client
if ($res =~ /^smartclient$/) { 
    $result = 6;
}

# If requested a logging in pop up window
if ($res =~ /^popup1$/) { 
    $result = 11;
}

# If requested a success pop up window
if ($res =~ /^popup2$/) { 
    $result = 12;
}

# If requested a logout pop up window
if ($res =~ /^popup3$/) { 
    $result = 13;
}


# Otherwise it was not a form request
# Send out an error message
if ($result == 0) {
    print "Content-type: text/html\n\n
<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">
<html>
<head>
  <title>ChilliSpot Login Failed</title>
  <meta http-equiv=\"Cache-control\" content=\"no-cache\">
  <meta http-equiv=\"Pragma\" content=\"no-cache\">
</head>
<body bgColor = '#c0d8f4'>
  <h1 style=\"text-align: center;\">ChilliSpot Login Failed</h1>
  <center>
    Login must be performed through ChilliSpot daemon.
  </center>
</body>
</html>
";
    exit(0);
}

#Generate the output
print "Content-type: text/html\n\n
<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">
<html>
<head>
  <title>ChilliSpot Login</title>
  <meta http-equiv=\"Cache-control\" content=\"no-cache\">
  <meta http-equiv=\"Pragma\" content=\"no-cache\">
  <SCRIPT LANGUAGE=\"JavaScript\">
    var blur = 0;
    var starttime = new Date();
    var startclock = starttime.getTime();
    var mytimeleft = 0;

    function doTime() {
      window.setTimeout( \"doTime()\", 1000 );
      t = new Date();
      time = Math.round((t.getTime() - starttime.getTime())/1000);
      if (mytimeleft) {
        time = mytimeleft - time;
        if (time <= 0) {
          window.location = \"$loginpath?res=popup3&uamip=$uamip&uamport=$uamport\";
        }
      }
      if (time < 0) time = 0;
      hours = (time - (time % 3600)) / 3600;
      time = time - (hours * 3600);
      mins = (time - (time % 60)) / 60;
      secs = time - (mins * 60);
      if (hours < 10) hours = \"0\" + hours;
      if (mins < 10) mins = \"0\" + mins;
      if (secs < 10) secs = \"0\" + secs;
      title = \"Online time: \" + hours + \":\" + mins + \":\" + secs;
      if (mytimeleft) {
        title = \"Remaining time: \" + hours + \":\" + mins + \":\" + secs;
      }
      if(document.all || document.getElementById){
         document.title = title;
      }
      else {   
        self.status = title;
      }
    }

    function popUp(URL) {
      if (self.name != \"chillispot_popup\") {
        chillispot_popup = window.open(URL, 'chillispot_popup', 'toolbar=0,scrollbars=0,location=0,statusbar=0,menubar=0,resizable=0,width=500,height=375');
      }
    }

    function doOnLoad(result, URL, userurl, redirurl, timeleft) {
      if (timeleft) {
        mytimeleft = timeleft;
      }
      if ((result == 1) && (self.name == \"chillispot_popup\")) {
        doTime();
      }
      if ((result == 1) && (self.name != \"chillispot_popup\")) {
        chillispot_popup = window.open(URL, 'chillispot_popup', 'toolbar=0,scrollbars=0,location=0,statusbar=0,menubar=0,resizable=0,width=500,height=375');
      }
      if ((result == 2) || result == 5) {
        document.form1.UserName.focus()
      }
      if ((result == 2) && (self.name != \"chillispot_popup\")) {
        chillispot_popup = window.open('', 'chillispot_popup', 'toolbar=0,scrollbars=0,location=0,statusbar=0,menubar=0,resizable=0,width=400,height=200');
        chillispot_popup.close();
      }
      if ((result == 12) && (self.name == \"chillispot_popup\")) {
        doTime();
        if (redirurl) {
          opener.location = redirurl;
        }
        else if (userurl) {
          opener.location = userurl;
        }
        else if (opener.home) {
          opener.home();
        }
        else {
          opener.location = \"about:home\";
        }
        self.focus();
        blur = 0;
      }
      if ((result == 13) && (self.name == \"chillispot_popup\")) {
        self.focus();
        blur = 1;
      }
    }

    function doOnBlur(result) {
      if ((result == 12) && (self.name == \"chillispot_popup\")) {
        if (blur == 0) {
          blur = 1;
          self.focus();
        }
      }
    }
  </script>
</head>
<body onLoad=\"javascript:doOnLoad($result, '$loginpath?res=popup2&uamip=$uamip&uamport=$uamport&userurl=$userurl&redirurl=$redirurl&timeleft=$timeleft','$userurldecode', '$redirurldecode', '$timeleft')\" onBlur = \"javascript:doOnBlur($result)\" bgColor = '#c0d8f4'>";


#      if (!window.opener) {
#        document.bgColor = '#c0d8f4';
#      }

#print "THE INPUT: $input";
#foreach $key (sort (keys %ENV)) {
#    print $key, ' = ', $ENV{$key}, "<br>\n";
#}

if ($result == 2) {
    print "
  <h1 style=\"text-align: center;\">ChilliSpot Login Failed</h1>";
    if ($reply) {
    print "<center> $reply </BR></BR></center>";
    }
}

if ($result == 5) {
    print "
  <h1 style=\"text-align: center;\">ChilliSpot Login</h1>";
}

if ($result == 2 || $result == 5) {
  print "
  <form name=\"form1\" method=\"post\" action=\"$loginpath\">
  <INPUT TYPE=\"hidden\" NAME=\"challenge\" VALUE=\"$challenge\">
  <INPUT TYPE=\"hidden\" NAME=\"uamip\" VALUE=\"$uamip\">
  <INPUT TYPE=\"hidden\" NAME=\"uamport\" VALUE=\"$uamport\">
  <INPUT TYPE=\"hidden\" NAME=\"userurl\" VALUE=\"$userurldecode\">
  <center>
  <table border=\"0\" cellpadding=\"5\" cellspacing=\"0\" style=\"width: 217px;\">
    <tbody>
      <tr>
        <td align=\"right\">Username:</td>
        <td><input STYLE=\"font-family: Arial\" type=\"text\" name=\"UserName\" size=\"20\" maxlength=\"128\"></td>
      </tr>
      <tr>
        <td align=\"right\">Password:</td>
        <td><input STYLE=\"font-family: Arial\" type=\"password\" name=\"Password\" size=\"20\" maxlength=\"128\"></td>
      </tr>
      <tr>
        <td align=\"center\" colspan=\"2\" height=\"23\"><input type=\"submit\" name=\"button\" value=\"Login\" onClick=\"javascript:popUp('$loginpath?res=popup1&uamip=$uamip&uamport=$uamport')\"></td> 
      </tr>
    </tbody>
  </table>
  </center>
  </form>
</body>
</html>";
}

if ($result == 1) {
  print "
  <h1 style=\"text-align: center;\">Logged in to ChilliSpot</h1>";

  if ($reply) { 
      print "<center> $reply </BR></BR></center>";
  }

  print "
  <center>
    <a href=\"http://$uamip:$uamport/logoff\">Logout</a>
  </center>
</body>
</html>";
}

if (($result == 4) || ($result == 12)) {
  print "
  <h1 style=\"text-align: center;\">Logged in to ChilliSpot</h1>
  <center>
    <a href=\"http://$uamip:$uamport/logoff\">Logout</a>
  </center>
</body>
</html>";
}


if ($result == 11) {
  print "<h1 style=\"text-align: center;\">Logging in to ChilliSpot</h1>";
  print "
  <center>
    Please wait......
  </center>
</body>
</html>";
}


if (($result == 3) || ($result == 13)) {
    print "
  <h1 style=\"text-align: center;\">Logged out from ChilliSpot</h1>
  <center>
    <a href=\"http://$uamip:$uamport/prelogin\">Login</a>
  </center>
</body>
</html>";
}


exit(0);

* - or place the following login script 'hotspotlogin.php' on your SSL and PHP-enabled web server with domain name www.mydomain.com:

<?php
#
# chilli - ChilliSpot.org. A Wireless LAN Access Point Controller
# Copyright (C) 2003, 2004 Mondru AB.
#
# The contents of this file may be used under the terms of the GNU
# General Public License Version 2, provided that the above copyright
# notice and this permission notice is included in all copies or
# substantial portions of the software.

# Redirects from ChilliSpot daemon:
#
# Redirection when not yet or already authenticated
#   notyet:  ChilliSpot daemon redirects to login page.
#  already: ChilliSpot daemon redirects to success status page.
#
# Response to login:
#   already: Attempt to login when already logged in.
#   failed:  Login failed
#   success: Login succeded
#
# logoff:  Response to a logout


# Shared secret used to encrypt challenge with. Prevents dictionary attacks.
# You should change this to your own shared secret.
$uamsecret = "ht2eb8ej6s4et3rg1ulp";

# Uncomment the following line if you want to use ordinary user-password
# for radius authentication. Must be used together with $uamsecret.
$userpassword=1;

# Our own path
$loginpath = $_SERVER['PHP_SELF'];

$ChilliSpot="ChilliSpot";
$title="$ChilliSpot Login";
$centerUsername="Username";
$centerPassword="Password";
$centerLogin="Login";
$centerPleasewait="Please wait.......";
$centerLogout="Logout";
$h1Login="$ChilliSpot Login";
$h1Failed="$ChilliSpot Login Failed";
$h1Loggedin="Logged in to $ChilliSpot";
$h1Loggingin="Logging in to $ChilliSpot";
$h1Loggedout="Logged out from $ChilliSpot";
$centerdaemon="Login must be performed through $ChilliSpot daemon";
$centerencrypted="Login must use encrypted connection";


# Make sure that the form parameters are clean
#$OK_CHARS='-a-zA-Z0-9_.@&=%!';
#$_ = $input = <STDIN>;
#s/[^$OK_CHARS]/_/go;
#$input = $_;

# Make sure that the get query parameters are clean
#$OK_CHARS='-a-zA-Z0-9_.@&=%!';
#$_ = $query=$ENV{QUERY_STRING};
#s/[^$OK_CHARS]/_/go;
#$query = $_;


# If she did not use https tell her that it was wrong.
if (!($_ENV['HTTPS'] == 'on')) {
#    echo "Content-type: text/html\n\n";
echo "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">
<html>
<head>
  <title>$title</title>
  <meta http-equiv=\"Cache-control\" content=\"no-cache\">
  <meta http-equiv=\"Pragma\" content=\"no-cache\">
</head>
<body bgColor = '#c0d8f4'>
  <h1 style=\"text-align: center;\">$h1Failed</h1>
  <center>
    $centerencrypted
  </center>
</body>
<!--
<?xml version=\"1.0\" encoding=\"UTF-8\"?>
<WISPAccessGatewayParam 
  xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"
  xsi:noNamespaceSchemaLocation=\"http://www.acmewisp.com/WISPAccessGatewayParam.xsd\">
<AuthenticationReply>
<MessageType>120</MessageType>
<ResponseCode>102</ResponseCode>
<ReplyMessage>Login must use encrypted connection</ReplyMessage>
</AuthenticationReply>
</WISPAccessGatewayParam>
-->
</html>
";
    exit(0);
}


# Read form parameters which we care about
if (isset($_POST['UserName']))    $username    = $_POST['UserName'];
if (isset($_POST['Password']))    $password    = $_POST['Password'];
if (isset($_POST['challenge']))    $challenge    = $_POST['challenge'];
if (isset($_POST['button']))    $button        = $_POST['button'];
if (isset($_POST['logout']))    $logout        = $_POST['logout'];
if (isset($_POST['prelogin']))    $prelogin    = $_POST['prelogin'];
if (isset($_POST['res']))    $res        = $_POST['res'];
if (isset($_POST['uamip']))    $uamip        = $_POST['uamip'];
if (isset($_POST['uamport']))    $uamport    = $_POST['uamport'];
if (isset($_POST['userurl']))    $userurl    = $_POST['userurl'];
if (isset($_POST['timeleft']))    $timeleft    = $_POST['timeleft'];
if (isset($_POST['redirurl']))    $redirurl    = $_POST['redirurl'];

# Read query parameters which we care about
if (isset($_GET['res']))    $res        = $_GET['res'];
if (isset($_GET['challenge']))    $challenge    = $_GET['challenge'];
if (isset($_GET['uamip']))    $uamip        = $_GET['uamip'];
if (isset($_GET['uamport']))    $uamport    = $_GET['uamport'];
if (isset($_GET['reply']))    $reply        = $_GET['reply'];
if (isset($_GET['userurl']))    $userurl    = $_GET['userurl'];
if (isset($_GET['timeleft']))    $timeleft    = $_GET['timeleft'];
if (isset($_GET['redirurl']))    $redirurl    = $_GET['redirurl'];


#$reply =~ s/\+/ /g;
#$reply =~s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/seg;

$userurldecode = $userurl;
#$userurldecode =~ s/\+/ /g;
#$userurldecode =~s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/seg;

$redirurldecode = $redirurl;
#$redirurldecode =~ s/\+/ /g;
#$redirurldecode =~s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/seg;

#$password =~ s/\+/ /g;
#$password =~s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/seg;

# If attempt to login
if ($button == 'Login') {
  $hexchal = pack ("H32", $challenge);
  if ($uamsecret) {
    $newchal = pack ("H*", md5($hexchal . $uamsecret));
  } else {
    $newchal = $hexchal;
  }
  $response = md5("\0" . $password . $newchal);
  $newpwd = pack("a32", $password);
  $pappassword = implode ("", unpack("H32", ($newpwd ^ $newchal)));
# sleep 5;
# echo 'Content-type: text/html\n\n';
  echo "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">
<html>
<head>
  <title>$title</title>
  <meta http-equiv=\"Cache-control\" content=\"no-cache\">
  <meta http-equiv=\"Pragma\" content=\"no-cache\">";
  if (isset($uamsecret) && isset($userpassword)) {
    echo "  <meta http-equiv=\"refresh\" content=\"0;url=http://$uamip:$uamport/logon?username=$username&password=$pappassword\">";
  } else {
    echo "  <meta http-equiv=\"refresh\" content=\"0;url=http://$uamip:$uamport/logon?username=$username&response=$response&userurl=$userurl\">";
  }
  echo "</head>
<body bgColor = '#c0d8f4'>
<h1 style=\"text-align: center;\">$h1Loggingin</h1>
  <center>
    $centerPleasewait
  </center>
</body>
<!--
<?xml version=\"1.0\" encoding=\"UTF-8\"?>
<WISPAccessGatewayParam 
  xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"
  xsi:noNamespaceSchemaLocation=\"http://www.acmewisp.com/WISPAccessGatewayParam.xsd\">
<AuthenticationReply>
<MessageType>120</MessageType>
<ResponseCode>201</ResponseCode>
";
  if (isset($uamsecret) && isset($userpassword)) {
    echo "<LoginResultsURL>http://$uamip:$uamport/logon?username=$username&password=$pappassword</LoginResultsURL>";
  } else {
    echo "<LoginResultsURL>http://$uamip:$uamport/logon?username=$username&response=$response&userurl=$userurl</LoginResultsURL>";
  }
  echo "</AuthenticationReply> 
</WISPAccessGatewayParam>
-->
</html>
";
    exit(0);
}

switch($res) {
  case 'success':     $result =  1; break; // If login successful
  case 'failed':      $result =  2; break; // If login failed
  case 'logoff':      $result =  3; break; // If logout successful
  case 'already':     $result =  4; break; // If tried to login while already logged in
  case 'notyet':      $result =  5; break; // If not logged in yet
  case 'smartclient': $result =  6; break; // If login from smart client
  case 'popup1':      $result = 11; break; // If requested a logging in pop up window
  case 'popup2':      $result = 12; break; // If requested a success pop up window
  case 'popup3':      $result = 13; break; // If requested a logout pop up window
  default: $result = 0; // Default: It was not a form request
}

# Otherwise it was not a form request
# Send out an error message
if ($result == 0) {
#    echo "Content-type: text/html\n\n";
    echo "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">
<html>
<head>
  <title>$title</title>
  <meta http-equiv=\"Cache-control\" content=\"no-cache\">
  <meta http-equiv=\"Pragma\" content=\"no-cache\">
</head>
<body bgColor = '#c0d8f4'>
  <h1 style=\"text-align: center;\">$h1Failed</h1>
  <center>
    $centerdaemon
  </center>
</body>
</html>
";
    exit(0);
}

# Generate the output
#echo "Content-type: text/html\n\n";
echo "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">
<html>
<head>
  <title>$title</title>
  <meta http-equiv=\"Cache-control\" content=\"no-cache\">
  <meta http-equiv=\"Pragma\" content=\"no-cache\">
  <SCRIPT LANGUAGE=\"JavaScript\">
    var blur = 0;
    var starttime = new Date();
    var startclock = starttime.getTime();
    var mytimeleft = 0;

    function doTime() {
      window.setTimeout( \"doTime()\", 1000 );
      t = new Date();
      time = Math.round((t.getTime() - starttime.getTime())/1000);
      if (mytimeleft) {
        time = mytimeleft - time;
        if (time <= 0) {
          window.location = \"$loginpath?res=popup3&uamip=$uamip&uamport=$uamport\";
        }
      }
      if (time < 0) time = 0;
      hours = (time - (time % 3600)) / 3600;
      time = time - (hours * 3600);
      mins = (time - (time % 60)) / 60;
      secs = time - (mins * 60);
      if (hours < 10) hours = \"0\" + hours;
      if (mins < 10) mins = \"0\" + mins;
      if (secs < 10) secs = \"0\" + secs;
      title = \"Online time: \" + hours + \":\" + mins + \":\" + secs;
      if (mytimeleft) {
        title = \"Remaining time: \" + hours + \":\" + mins + \":\" + secs;
      }
      if(document.all || document.getElementById){
         document.title = title;
      }
      else {   
        self.status = title;
      }
    }

    function popUp(URL) {
      if (self.name != \"chillispot_popup\") {
        chillispot_popup = window.open(URL, 'chillispot_popup', 'toolbar=0,scrollbars=0,location=0,statusbar=0,menubar=0,resizable=0,width=500,height=375');
      }
    }

    function doOnLoad(result, URL, userurl, redirurl, timeleft) {
      if (timeleft) {
        mytimeleft = timeleft;
      }
      if ((result == 1) && (self.name == \"chillispot_popup\")) {
        doTime();
      }
      if ((result == 1) && (self.name != \"chillispot_popup\")) {
        chillispot_popup = window.open(URL, 'chillispot_popup', 'toolbar=0,scrollbars=0,location=0,statusbar=0,menubar=0,resizable=0,width=500,height=375');
      }
      if ((result == 2) || result == 5) {
        document.form1.UserName.focus()
      }
      if ((result == 2) && (self.name != \"chillispot_popup\")) {
        chillispot_popup = window.open('', 'chillispot_popup', 'toolbar=0,scrollbars=0,location=0,statusbar=0,menubar=0,resizable=0,width=400,height=200');
        chillispot_popup.close();
      }
      if ((result == 12) && (self.name == \"chillispot_popup\")) {
        doTime();
        if (redirurl) {
          opener.location = redirurl;
        }
        else if (opener.home) {
          opener.home();
        }
        else {
          opener.location = \"about:home\";
        }
        self.focus();
        blur = 0;
      }
      if ((result == 13) && (self.name == \"chillispot_popup\")) {
        self.focus();
        blur = 1;
      }
    }

    function doOnBlur(result) {
      if ((result == 12) && (self.name == \"chillispot_popup\")) {
        if (blur == 0) {
          blur = 1;
          self.focus();
        }
      }
    }
  </script>
</head>
<body onLoad=\"javascript:doOnLoad($result, '$loginpath?res=popup2&uamip=$uamip&uamport=$uamport&userurl=$userurl&redirurl=$redirurl&timeleft=$timeleft','$userurldecode', '$redirurldecode', '$timeleft')\" onBlur = 'javascript:doOnBlur($result)' bgColor = '#c0d8f4'>";

/*# begin debugging
  print "<center>THE INPUT (for debugging):<br>";
  foreach ($_GET as $key => $value) {
    print $key . "=" . $value . "<br>";
  }
  print "<br></center>";
# end debugging
*/
if ($result == 2) {
    echo "
  <h1 style=\"text-align: center;\">$h1Failed</h1>";
    if ($reply) {
    echo "<center> $reply </BR></BR></center>";
    }
}

if ($result == 5) {
    echo "
  <h1 style=\"text-align: center;\">$h1Login</h1>";
}

if ($result == 2 || $result == 5) {
  echo "
  <form name=\"form1\" method=\"post\" action=\"$loginpath\">
  <input type=\"hidden\" name=\"challenge\" value=\"$challenge\">
  <input type=\"hidden\" name=\"uamip\" value=\"$uamip\">
  <input type=\"hidden\" name=\"uamport\" value=\"$uamport\">
  <input type=\"hidden\" name=\"userurl\" value=\"$userurl\">
  <center>
  <table border=\"0\" cellpadding=\"5\" cellspacing=\"0\" style=\"width: 217px;\">
    <tbody>
      <tr>
        <td align=\"right\">$centerUsername:</td>
        <td><input style=\"font-family: Arial\" type=\"text\" name=\"UserName\" size=\"20\" maxlength=\"128\"></td>
      </tr>
      <tr>
        <td align=\"right\">$centerPassword:</td>
        <td><input style=\"font-family: Arial\" type=\"password\" name=\"Password\" size=\"20\" maxlength=\"128\"></td>
      </tr>
      <tr>
        <td align=\"center\" colspan=\"2\" height=\"23\"><input type=\"submit\" name=\"button\" value=\"Login\" onClick=\"javascript:popUp('$loginpath?res=popup1&uamip=$uamip&uamport=$uamport')\"></td> 
      </tr>
    </tbody>
  </table>
  </center>
  </form>
</body>
</html>";
}

if ($result == 1) {
  echo "
  <h1 style=\"text-align: center;\">$h1Loggedin</h1>";

  if ($reply) { 
      echo "<center> $reply </br></br></center>";
  }

  echo "
  <center>
    <a href=\"http://$uamip:$uamport/logoff\">Logout</a>
  </center>
</body>
</html>";
}

if (($result == 4) || ($result == 12)) {
  echo "
  <h1 style=\"text-align: center;\">$h1Loggedin</h1>
  <center>
    <a href=\"http://$uamip:$uamport/logoff\">$centerLogout</a>
  </center>
</body>
</html>";
}


if ($result == 11) {
  echo "
  <h1 style=\"text-align: center;\">$h1Loggingin</h1>
  <center>
    $centerPleasewait
  </center>
</body>
</html>";
}


if (($result == 3) || ($result == 13)) {
  echo "
  <h1 style=\"text-align: center;\">$h1Loggedout</h1>
  <center>
    <a href=\"http://$uamip:$uamport/prelogin\">$centerLogin</a>
  </center>
</body>
</html>";
}

exit(0);
?>

Freeradius config

* Change the following attributes in /etc/freeradius/radiusd.conf to use Freeradius with a MySQL backend:

authorize {
    sql

}

authenticate {
    Auth-Type PAP {
        pap
    }
}

accounting {
    sql
}

session {
    sql
}


* Change the following attributes in /etc/freeradius/sql.conf

sql {
    driver = "rlm_sql_mysql"

    server = "mysql.mydomain.com"
    login = "my_login"
    password = "my_password"
    radius_db = "my_db"

    # Uncomment simul_count_query to enable simultaneous use checking
    simul_count_query = "SELECT COUNT(*) FROM ${acct_table1} WHERE UserName='%{SQL-User-Name}' AND AcctStopTime = 0"

    readclients = yes
}


* Install the Freeradius tables in the MySQL database on the domain mysql.mydomain.com, and configure a test user:

raduserinfo

UserName = 'testuser'

radcheck for 'testuser'

User-Password := 'password'
Auth-Type := 'PAP'
Simultaneous-Use := 1

radreply for 'testuser'

Idle-Timeout := 1800



NTP config

* Change the attributes in /etc/TZ to match your time zone, for instance:

CET-1CEST-2,M3.5.0/02:00:00,M10.5.0/03:00:00


Monit config

* Change the following attributes in /etc/monitrc:

set mailserver smtp.mymailserver.com
set mail-format { from: monit@mydomain.com }
set alert monit@mydomain.com
set httpd port 2812 and
     allow admin:monit     # user 'admin' with password 'monit'

check process chilli with pidfile /var/run/chilli.pid
   start program = "/etc/init.d/chilli start"
   stop program = "/etc/init.d/chilli stop"

check process radiusd with pidfile /var/run/radiusd.pid
   start program = "/etc/init.d/radiusd start"
   stop program = "/etc/init.d/radiusd stop"

check host www.mydomain.com with address www.mydomain.com
   if failed port 80 protocol http
      and request "/hotspotlogin.cgi" then alert

check host mysql.mydomain.com with address mysql.mydomain.com
   if failed port 3306 protocol mysql then alert



Configuring the remote routers

Since we only want to use the remote routers to repeat our signal, we bridge the WDS, WIFI and LAN:

       (192.168.1.0/24) 
|   |    |  |         \|/     \|/
+--vlan0-+--+         eth1    wds
    |                  |       |
    +----------br0-----+-------+
                | 
          <userspace>

- vlan0 is used for bridging all the LAN ports
- eth1 is used for the WIFI interface
- wds is used for extending the WIFI range using WDS
- br0 is the bridge that connects all the interfaces


* The existing bridge is then used for the wireless interface.
For every WDS client that we want to add, we add a new wds0.xxxxx interface, starting at wds0.49153:

lan_ifname=br0
lan_ifnames=vlan0 eth1 wds0.49153 wds0.49154 wds0.49155


* In addition, the Spanning Tree Protocol is set to avoid circular bridges when using WDS:

lan_stp=1


* We use manual WDS and disables Lazy WDS, and adds the MAC address for all wireless routers
that we want to communicate with, including the MAC address of the captive portal:

wl0_lazywds=0
wl0_wds=aa:aa:aa:aa:aa:aa bb:bb:bb:bb:bb:bb cc:cc:cc:cc:cc:cc


* Last, disable all services you do not need, such as DHCP. This is an important step because we do not want the remote routers to hand out IP addresses that confuses Chillispot.



Testing the setup

* Start your WEB browser, and write 'testuser'/'password' in the WEB page that appears. If you have configured everything correctly, you should be authenticated.

* If anything fails, connect your PC to one of the LAN ports on the router and start two SSH sessions, one with Chillispot and the other with Freeradius, both in foreground debug mode:

chilli -fd

radiusd -X


Establish a wireless connection to your WLAN and watch the outputs carefully to debug your setup.



Have fun!

Re: [HOWTO] Setting up OpenWRT as a captive portal on WRT54GL

Hi,
thanks for that HowTo. Very helpful indeed.
Before I get stuck into it, I would like to ask for some clarification, as the HowTo appears to make some assumptions:
- Where are all chillispot and freeradius packages installed in your setup? All on the router? Or all on a gateway PC? Or chillispot on the router and freeradius on a PC? Or does it matter at all?
I assume freeradius could be installed anywhere - even remotely on a hosted server, as long as it can be reached via an IP address.
Waht about chillispot, does it have to be on the router? Could chillispot be hosted remotely like freeradius?
And where does the hotspotlogin.cgi have to be placed. Router? Server? remote server?

And would all these variations make a difference for your set up?

Please advise

Best wishes

*************
Auckland, New Zealand

3 (edited by ajauberg 2007-11-14 22:41:21)

Re: [HOWTO] Setting up OpenWRT as a captive portal on WRT54GL

My setup has Chillispot and Freeradius on the router, and the rest (MySQL and SSL WEB server) externally.

You are right in that Freeradius also could be located externally without doing any changes to the setup. It would also work to place Chillispot outside the router if you configure bridging, not routing, between the router and the external Chillispot. This is because Chillispot uses MAC authentication, and it needs to see the MAC addresses of all clients it shall authenticate. Any router or firewall in between blocking the client MAC addresses will therefore cause the authentication to fail.

R

Arne-J.

Re: [HOWTO] Setting up OpenWRT as a captive portal on WRT54GL

Hey ajauberg,

I was wondering how would you approach a setup where the interfaces are configured
in such way that vlan0 (LAN) is separated from eth1 (WLAN) interface?
Would you simply delete the br0 bridge between in them, such as "brctl delbr br0 eth1" and
thats it.

To continue with that, would the firewall rules actually have to be changed? it doesn't
seem as if they pose a problem. It would be enough to simply add to /etc/firewall.user
"iptables -A forwarding_rule -i tun0 -j ACCEPT"
(and possibly a rule to drop everything coming from the eth1 interface as chillispot
manually assigns new iptable rules for clients when they authenticate).



What do you think?

5 (edited by ajauberg 2007-11-27 20:52:00)

Re: [HOWTO] Setting up OpenWRT as a captive portal on WRT54GL

Hi,

I guess your suggestion using brctl could work, but as I am using OpenWRT they have their own nvram settings to hold the configuration. I think that brctl is used in the background to set up the required config based on the nvram settings.

When it comes to the firewall issue you may also be right, I guess that the standard Chillispot package has a focus on portability and therefore does not care so much about what functionality already exists on the current platform. As long as you have a firewall that can resist attacks from malicious users who wants to break into your system you should be OK.

Please share your settings if you continue on this track, they could be of value to the community!

Re: [HOWTO] Setting up OpenWRT as a captive portal on WRT54GL

Yeah I'm gonna set this up pretty soon and will keep you updated.
Since you mentioned nvram it's necessary to ask which version of openwrt
are you working with :-)
WR or Kamikaze?

About the setup - in terms of interfaces, its not a must to use the brctl utility
indeed and nvram settings are probably easier to manage although a reboot
is required to apply them while brctl commands work on-the-fly.

So basically the configuration should be simple, if currently (default) I have
the nvram setting: lan_ifnames=vlan0 eth1 eth2 eth3
I should simply take eth1 out of it, and manually with brctl also break the
bridge between vlan0 and eth1 just to check for these settings without
rebooting.

About the firewall I am still unsure how to set up the rules so that I keep
the original openwrt's firewall script while adding support for chillispot.


What do you say about the firewall?
I believe chillispot is to be set so that it drops all packets going outside
but I can't remember

Re: [HOWTO] Setting up OpenWRT as a captive portal on WRT54GL

So far I have only used WhiteRussian, Kamikaze does not use nvram settings but configuration files in /etc/config/. I have had partial success in setting it up on Kamikaze, and has configured both Chillispot and Freeradius (not 7.09), but have had problems with WDS and the firewall tables.

I am no firewall guru, but maybe we could discuss the settings together:


$IPTABLES -P INPUT DROP
$IPTABLES -P FORWARD ACCEPT
$IPTABLES -P OUTPUT ACCEPT

- This sets the policies, these are general rules unless otherwise specified (?)



#Allow related and established on all interfaces (input)
$IPTABLES -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT

- Already related and established connections are accepted, what does this mean exactly?



#Allow SSH, related and established $WANIF. Reject everything else.
$IPTABLES -A INPUT -i $WANIF -p tcp -m tcp --dport   22 -j ACCEPT
$IPTABLES -A INPUT -i $WANIF -j REJECT

- This is my personal choice, as it lets me contact the router from the Internet


#Allow related and established $WLANIF. Drop everything else.
$IPTABLES -A INPUT -i $WLANIF -j DROP

- This is important as no routing shall go in through the WLAN, only through the Chillispot app.


#Allow 3990 on other interfaces (input).
$IPTABLES -A INPUT -p tcp -m tcp --dport 3990 --syn -j ACCEPT

- This is the control port used for communication between the Chillispot daemon and the UAM portal. What interface is referenced here, as WAN and WLAN are rejected and dropped already?


#Allow everything on loopback interface.
$IPTABLES -A INPUT -i lo -j ACCEPT

- This is the internal interface


#Allow everything on $LANIF
$IPTABLES -A INPUT -i $LANIF -j ACCEPT

- This is the trusted management interface were everything is allowed


#Drop everything to and from $WLANIF (forward)
$IPTABLES -A FORWARD -i $WLANIF -j DROP
$IPTABLES -A FORWARD -o $WLANIF -j DROP

- This is also important to ensure that only Chillispot controls the WLAN interface


#Enable NAT on output device.
$IPTABLES -t nat -A POSTROUTING -o $WANIF -j MASQUERADE

- This is straightforward NAT on the WAN


Any more comments?

Re: [HOWTO] Setting up OpenWRT as a captive portal on WRT54GL

Sorry for the long time.

It didn't require any changes to the firewall rule, just add to /etc/firewall.user:
iptables -A forwarding_rule -i tun0 -j ACCEPT

To break the bridge bonding between vlan0 and eth1 simply do:
brctl delif br0 eth1
This will separate the eth1 (WLAN) interface from the br0 bridge.

Then just start chilli on eth1 and everything should work fine.


Let me know if you have any problems.

Regards,
Liran Tal.

Re: [HOWTO] Setting up OpenWRT as a captive portal on WRT54GL

Hi ajauberg,

I recently configured a WRT54G running DD-WRT v23sp2 with a Chillispot config.
On the web-server side I'm running Apache w/ SSL.

The issue I'm having is that the .php file you posted above is not re-directing to the default login page with username / password fields.  Rather, I'm seeing the 'Chillispot Login Failed' page with the message 'Login must use encrypted connection'.  The CGI counterpart (hotspotlogin.cgi) works as desired, however.

The main issue here is that I'm looking for a hotspotlogin.php page that has the WISPr XML Smart Client Tags embedded, similar to the .cgi page.  After Googling for days at a time, the closest I could find is your solution above, as other efforts did not include the required code blocks.  If however, yourself or some other talented soul has a template and is willing to share, it would be most helpful and appreciated.


Thanks in advance!

Re: [HOWTO] Setting up OpenWRT as a captive portal on WRT54GL

Hey pbflores,

If you can provide me with some documentation of the WISPr XML Smart Client tags
then I'm willing to work on it.


Regards,
Liran Tal.

Re: [HOWTO] Setting up OpenWRT as a captive portal on WRT54GL

Hi Liri,

Please, call me Phil!

The WISPr XML Specification outlines the communication between both smart client and Access Gateway.  The spec is older, but used by Hotspot Aggregators such as Boingo and iPass. 

You can find the document at this link:
http://www.ebusinessforum.gr/engine/index.php?op=modload&modname=Downloads&action=downloadsviewfile&ctn=500&language=en

For your testing, the coova-chilli distro has links to a java-based smart client for download:
http://coova.org/wiki/index.php/CoovaFX

Please let me know how I can assist in any way.


Thanks again!

Re: [HOWTO] Setting up OpenWRT as a captive portal on WRT54GL

Hey Phil,


I've just checked the hotspotlogin.php that comes with the daloRADIUS package
and it seems to have all the WISPr XML tags, I suggest you download and check it as well.

So it seems that the hotspotlogin.php that was posted here and the one at daloRAIDUS
both have the WISPr XML tags and that your problem is something else, correct me if I'm wrong.

If you require more help getting this thing going you can also
contact me at liran dot tal at gmail dot com

Regards,
Liran Tal.

Re: [HOWTO] Setting up OpenWRT as a captive portal on WRT54GL

Hi Liran,

I checked the page from the daloRADIUS package as you mentioned, and it worked as desired.
Thanks for your quick and helpful response!

Best,
--Phil

Re: [HOWTO] Setting up OpenWRT as a captive portal on WRT54GL

Glad it was helpful.
Are you using daloRADIUS?

Re: [HOWTO] Setting up OpenWRT as a captive portal on WRT54GL

Not for this environment.  I'm using FreeRadius w/ MySQL and Apache installed via lampp.
Perhaps I'll try the dalo instance on another machine.

Cheers!

Re: [HOWTO] Setting up OpenWRT as a captive portal on WRT54GL

Alrighty.
Keep in touch!

Re: [HOWTO] Setting up OpenWRT as a captive portal on WRT54GL

Good job guys! This HowTo was extremely helpful to me.

What is the best approach for me if I want to implement Chillispot to authenticate users from 3 physically-distant places? Will Chillispot still be the DHCP server? Or will each location have its own DHCP server(the AP for instance)?
How to go about this scenario?

Thanks everybody!

Re: [HOWTO] Setting up OpenWRT as a captive portal on WRT54GL

Will Chillispot still be the DHCP server?

- Yes, Chillispot will be the DHCP server in all scenarioes.

Or will each location have its own DHCP server(the AP for instance)?

- My HowTo uses only one Chillispot server, and WDS between the APs. If they are too far away to hear each other, you must have several Chillispot servers, and also a backbone of some kind.

Re: [HOWTO] Setting up OpenWRT as a captive portal on WRT54GL

Hi ajauberg & others

This is a great post, thanks. I am trying to replicate what you have done, and am a bit confused about one step in the process. When you are setting up the interfaces in OpenWRT you mention these commands:

wifi_ifname=br0
wifi_ifnames=eth1 wds0.49153 wds0.49154 wds0.49155

When I do the second command I get an error that the wds0.49153 .... interfaces do not exist. Was there a step in there that was not mentioned about creating those interfaces? (sorry, OpenWRT is all a bit new to me)

Thanks in advance, I know you did this post a few years ago now.

Heath

Re: [HOWTO] Setting up OpenWRT as a captive portal on WRT54GL

Hi,

Yes, this was indeed a few years ago!

As I have not worked too much with White Russian lately, I think that the WDS interfaces came up when I added the MAC addresses for the other clients that should use WDS. This is not necessary to get Chillispot working, only to extend the range of the WiFi coverage.

BR

Arne-J.

21 (edited by el.capitan 2011-03-07 15:53:56)

Re: [HOWTO] Setting up OpenWRT as a captive portal on WRT54GL

Thanks for the info. It was very Helpful.


________________
MLB Extra Innings article

Re: [HOWTO] Setting up OpenWRT as a captive portal on WRT54GL

I'm using Daloradius 0.9-9 and the hotspotlogin.php of portal2 (daloradius/contrib/chilli/portal2/hotspotlogin/hotspotlogin.php). The login works, however on iOS after successfull logging in, the login window does not disappear and I can only press on "Cancel" but not "Finish".
What's the missing link here for satisfy the last step of the iOS Wifi configuration?

Hint: after pressing the Home button in fact I'm logged in, but the configuration dialog is somewhat confusing.