Installation du portail captif Chillispot

Précédent / Suivant

Principe de sécurisation

Les ordinateurs ne supportant pas le 802.1x, comme ceux inconnus dans la base de VMPS, doivent pouvoir se connecter à Internet après authentification. Pour cela, il est mis en place un portail captif. Celui-ci, nommé Chillispot, est intéressant car il établit un tunnel HTTPS (HyperText Transfert Protocol Secured). Il faut installer un serveur HTTPS (nous utilisons Apache2), le configurer pour qu'il soit à l'écoute du port 443/tcp. Il doit aussi supporter les CGI (Common Gateway Interface). En effet, dès que le client va vouloir se connecter à Internet, Chillispot enverra une redirection HTTP vers le programme CGI d'authentification sur le serveur sécurisé. Ce programme récupère le compte/mot de passe de l'utilisateur et demande au serveur Radius central l'autorisation d'accès. Si celle-ci est fournie, Chillispot laisse passer la connexion vers le site Internet demandé.

Chillispot a une lacune : une fois l'utilisateur authentifié, s'il ferme la fenêtre Chillispot qui apparaît en pop-up, il n'y a aucun moyen pour lui de se déconnecter. Il a été nécessaire de modifier le code source. Cette modification est faite en Javascript, qui doit être activé sur le navigateur. De cette manière, dès que l'utilisateur ferme son navigateur, la connexion est coupée.

Protocoles autorisés

Une fois authentifié, Chillispot laisse passer tous les paquets réseau. Il est nécessaire de configurer le pare-feu du portail captif pour qu'il ne laisse passer que ce que l'on veut. Au CNRS, il a été décidé de laisser passer : en sortie : ICMP, FTP, HTTP, IMAPS, POP3S (des utilisateurs vers Internet), SMTP, DNS, LDAP (des utilisateurs vers les serveurs centraux) ; en entrée (d'Internet vers les utilisateurs) : ICMP et les connexions pré-établies. Tout ceci est possible grâce à Netfilter, le composant du noyau Linux supportant les pare-feux. Très puissant et assez facile à configurer, il permet de créer un pare-feu performant avec état, dit aussi à suivi de connexion.

Routage

Chillispot fonctionne entre deux réseaux : le réseau privé (où les ordinateurs se retrouvent avant l'authentification) et le réseau public qui donne sur Internet. Le programme s'appuie sur les fonctionnalités de routage de Linux pour faire transiter les paquets. Il s'agit d'un routage avec une traduction d'adresse ou NAT (Network Address Translation) puisque la classe interne n'est pas routable.

Le principe de la translation NAT est que chaque paquet est corrigé à la volée en fonction de son adresse IP source : la translation NAT remplace l'adresse source à l'envoi du paquet par une adresse externe. Lorsque le retour de paquet arrive, la translation NAT corrige l'adresse destination avant de renvoyer le paquet vers sa finalité.

Un exemple de NAT statique est fourni en figure 22.

Il existe deux types de translation NAT : la translation NAT statique et la translation NAT dynamique. La translation NAT statique associe toujours la même adresse externe à la même adresse interne. La translation NAT dynamique associe aléatoirement les adresses externes en fonction des demandes. Dans notre contexte, la nécessité d'une translation NAT statique est évidente. De cette façon, en cas de remontée d'alerte, il sera possible d'aller consulter l'accounting pour connaître l'adresse interne donnée à l'utilisateur. La translation NAT dynamique (également disponible sur Linux) ne permettrait pas de retrouver une adresse source derrière le portail captif qui aurait effectué un accès illégal à une heure donnée.

Pour que le routeur sache communiquer avec les multiples adresses du portail captif sur son interface externe, il faut signaler à Linux que ces adresses doivent être gérées. Ceci est fait par la commande ip address add qui permet de créer toutes les adresses externes. Une fois ces adresses créées, Linux sait les utiliser pour le routage et il répond aussi aux requêtes ARP (Address Resolution Protocol) du routeur.

Les serveurs VPN du Campus de St Martin d'Hères sont situés dans une classe de réseaux non routables en 10.0.0.0/8. Il est nécessaire de router les paquets vers ces serveurs de VPN sans faire d'authentification Chillispot. Pour cela, il faut ajouter une règle dans la translation NAT pour que la translation NAT ne corrige pas les adresses à destination des réseaux du Campus. Pour être plus précis, la translation NAT ré-écrit l'adresse avec la même adresse, ce qui fait qu'il n'y a pas de changement.

Configuration

Pour que le Chillispot fonctionne, il est nécessaire de configurer le réseau pour que l'ordinateur soit à l'écoute de toutes les adresses IP externes du NAT, ainsi que les règles de filtrage nécessaires. De plus, le programme Chillispot doit aussi être configuré et modifié pour supporter la fermeture de fenêtre. Voici les fichiers nécessaires :
chilli.conf Voir / Cacher / Télécharger
##############################################################################
#
# Sample ChilliSpot configuration file
#
##############################################################################

# TAG: fg
# Include this flag if process is to run in the foreground
#fg

# TAG: debug
# Include this flag to include debug information.
debug

# TAG: interval
# Re-read configuration file at this interval. Will also cause new domain
# name lookups to be performed. Value is given in seconds.
#interval 3600

# TAG: pidfile
# File to store information about the process id of the program.
# The program must have write access to this file/directory.
#pidfile /var/run/chilli.pid

# TAG: statedir
# Directory to use for nonvolatile storage.
# The program must have write access to this directory.
# This tag is currently ignored
#statedir ./


# TUN parameters

# TAG: net
# IP network address of external packet data network
# Used to allocate dynamic IP addresses and set up routing.
# Normally you do not need to uncomment this tag.
#net 192.168.182.0/24
net 10.8.246.0/24

# TAG: dynip
# Dynamic IP address pool
# Used to allocate dynamic IP addresses to clients.
# If not set it defaults to the net tag.
# Do not uncomment this tag unless you are an experienced user!
#dynip 192.168.182.0/24

# TAG: statip
# Static IP address pool
# Used to allocate static IP addresses to clients.
# Do not uncomment this tag unless you are an experienced user!
#statip 192.168.182.0/24


# TAG: dns1
# Primary DNS server.
# Will be suggested to the client. 
# If omitted the system default will be used.
# Normally you do not need to uncomment this tag.
#dns1 172.16.0.5
dns1 147.173.1.26

# TAG: dns2
# Secondary DNS server.
# Will be suggested to the client.
# If omitted the system default will be used.
# Normally you do not need to uncomment this tag.
#dns2 172.16.0.6
dns2 147.173.1.27

# TAG: domain
# Domain name
# Will be suggested to the client.
# Normally you do not need to uncomment this tag.
#domain key.chillispot.org

# TAG: ipup
# Script executed after network interface has been brought up.
# Executed with the following parameters: <devicename> <ip address>
# <mask>
# Normally you do not need to uncomment this tag.
#ipup /etc/chilli.ipup

# TAG: ipdown
# Script executed after network interface has been taken down.
# Executed with the following parameters: <devicename> <ip address>
# <mask>
# Normally you do not need to uncomment this tag.
#ipdown /etc/chilli.ipdown


# Radius parameters

# TAG: radiuslisten
# IP address to listen to
# Normally you do not need to uncomment this tag.
#radiuslisten 127.0.0.1
radiuslisten 147.173.246.1

# TAG: radiusserver1
# IP address of radius server 1
# For most installations you need to modify this tag.
radiusserver1 147.173.1.27

# TAG: radiusserver2
# IP address of radius server 2
# If you have only one radius server you should set radiusserver2 to the
# same value as radiusserver1.
# For most installations you need to modify this tag.
radiusserver2 147.173.1.27

# TAG: radiusauthport
# Radius authentication port
# The UDP port number to use for radius authentication requests.
# The same port number is used for both radiusserver1 and radiusserver2.
# Normally you do not need to uncomment this tag.
#radiusauthport 1812

# TAG: radiusacctport
# Radius accounting port
# The UDP port number to use for radius accounting requests.
# The same port number is used for both radiusserver1 and radiusserver2.
# Normally you do not need to uncomment this tag.
#radiusacctport 1813

# TAG: radiussecret
# Radius shared secret for both servers
# For all installations you should modify this tag.
radiussecret PASSsecretRadius

# TAG: radiusnasid
# Radius NAS-Identifier
# Normally you do not need to uncomment this tag.
radiusnasid Chillispot

# TAG: radiuslocationid
# WISPr Location ID. Should be in the format: isocc=<ISO_Country_Code>,
# cc=<E.164_Country_Code>,ac=<E.164_Area_Code>,network=<ssid/ZONE>
# Normally you do not need to uncomment this tag.
#radiuslocationid isocc=us,cc=1,ac=408,network=ACMEWISP_NewarkAirport

# TAG: radiuslocationname
# WISPr Location Name. Should be in the format: 
# <HOTSPOT_OPERATOR_NAME>,<LOCATION>
# Normally you do not need to uncomment this tag.
#radiuslocationname ACMEWISP,Gate_14_Terminal_C_of_Newark_Airport


# Radius proxy parameters

# TAG: proxylisten
# IP address to listen to
# Normally you do not need to uncomment this tag.
#proxylisten 10.0.0.1

# TAG: proxyport
# UDP port to listen to. 
# If not specified a port will be selected by the system
# Normally you do not need to uncomment this tag.
#proxyport 1645

# TAG: proxyclient
# Client(s) from which we accept radius requests
# Normally you do not need to uncomment this tag.
#proxyclient 10.0.0.1/24

# TAG: proxysecret
# Radius proxy shared secret for all clients
# If not specified defaults to radiussecret
# Normally you do not need to uncomment this tag.
#proxysecret testing123


# DHCP Parameters

# TAG: dhcpif
# Ethernet interface to listen to.
# This is the network interface which is connected to the access points.
# In a typical configuration this tag should be set to eth1.
dhcpif vlan846

# TAG: dhcpmac
# Use specified MAC address.
# An address in the range  00:00:5E:00:02:00 - 00:00:5E:FF:FF:FF falls
# within the IANA range of addresses and is not allocated for other
# purposes.
# Normally you do not need to uncomment this tag.
#dhcpmac 00:00:5E:00:02:00

# TAG: lease
# Time before DHCP lease expires
# Normally you do not need to uncomment this tag.
#lease 600


# Universal access method (UAM) parameters

# TAG: uamserver
# URL of web server handling authentication.
uamserver https://10.8.246.1/cgi-bin/hotspotlogin.cgi

# TAG: uamhomepage
# URL of welcome homepage.
# Unauthenticated users will be redirected to this URL. If not specified
# users will be redirected to the uamserver instead.
# Normally you do not need to uncomment this tag.
#uamhomepage https://10.8.246.1/cgi-bin/hotspotlogin.cgi

# TAG: uamsecret
# Shared between chilli and authentication web server
uamsecret xxxx

# TAG: uamlisten
# IP address to listen to for authentication requests
# Do not uncomment this tag unless you are an experienced user!
#uamlisten 192.168.182.1

# TAG: uamport
# TCP port to listen to for authentication requests
# Do not uncomment this tag unless you are an experienced user!
#uamport 3990

# TAG: uamallowed
# Comma separated list of domain names, IP addresses or network segments
# the client can access without first authenticating.
# It is possible to specify this tag multiple times.
# Normally you do not need to uncomment this tag.
#uamallowed www.chillispot.org,10.11.12.0/24
uamallowed 10.0.0.0/8

# TAG: uamanydns
# If this flag is given unauthenticated users are allowed to use
# any DNS server.
# Normally you do not need to uncomment this tag.
#uamanydns


# MAC authentication

# TAG: macauth
# If this flag is given users will be authenticated only on their MAC
# address.
# Normally you do not need to uncomment this tag.
#macauth

# TAG: macallowed
# List of MAC addresses.
# The MAC addresses specified in this list will be authenticated only on
# their MAC address.
# This tag is ignored if the macauth tag is given.
# It is possible to specify this tag multiple times.
# Normally you do not need to uncomment this tag.
#macallowed 00-0A-5E-AC-BE-51,00-30-1B-3C-32-E9

# TAG: macpasswd
# Password to use for MAC authentication.
# Normally you do not need to uncomment this tag.
#macpasswd password

# TAG: macsuffix
# Suffix to add to MAC address in order to form the username.
# Normally you do not need to uncomment this tag.
#macsuffix suffix



chillispot.patch Voir / Cacher / Télécharger
--- hotspotlogin.cgi.ori	2007-09-25 12:59:40.000000000 +0200
+++ hotspotlogin.cgi	2007-09-25 14:03:58.000000000 +0200
@@ -352,9 +352,15 @@
         }
       }
     }
+    function doOnUnLoad(result) {
+      if ((result==12) && (self.name=='chillispot_popup')) {
+        window.close();
+        document.location.href=('http://$uamip:$uamport/logoff');
+      }
+    }
   </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'>";
+<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)\" onUnLoad=\"doOnUnLoad($result)\" bgColor = '#c0d8f4'>";
 
 
 #      if (!window.opener) {
@@ -418,7 +424,9 @@
 
   print "
   <center>
-    <a href=\"http://$uamip:$uamport/logoff\">Logout</a>
+    <a href=\"http://$uamip:$uamport/logoff\">Logout</a><br><br>
+    Vous devez cliquer sur le Logout pour vous d&eacute;connecter<br>
+    You must click on Logout link to unconnect you
   </center>
 </body>
 </html>";
@@ -428,7 +436,10 @@
   print "
   <h1 style=\"text-align: center;\">Logged in to ChilliSpot</h1>
   <center>
-    <a href=\"http://$uamip:$uamport/logoff\">Logout</a>
+    <a href=\"javascript:doOnUnLoad(12);\">Logout</a><br><br>
+    La fermeture de cette fen&ecirc;tre cl&ocirc;t la connexion avec votre 
+    compte<br>
+    Closing this window end connection with your account
   </center>
 </body>
 </html>";

hotspotlogin.cgi Voir / Cacher / Télécharger
#!/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 = "xxxx";

# 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 = "/cgi-bin/hotspotlogin.cgi";

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

# 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$/)) {
    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\">";
    } 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 (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();
        }
      }
    }
    function doOnUnLoad(result) {
      if ((result==12) && (self.name=='chillispot_popup')) {
        window.close();
        document.location.href=('http://$uamip:$uamport/logoff');
      }
    }
  </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)\" onUnLoad=\"doOnUnLoad($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=\"$userurl\">
  <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><br><br>
    Vous devez cliquer sur le Logout pour vous d&eacute;connecter<br>
    You must click on Logout link to unconnect you
  </center>
</body>
</html>";
}

if (($result == 4) || ($result == 12)) {
  print "
  <h1 style=\"text-align: center;\">Logged in to ChilliSpot</h1>
  <center>
    <a href=\"javascript:doOnUnLoad(12);\">Logout</a><br><br>
    La fermeture de cette fen&ecirc;tre cl&ocirc;t la connexion avec votre 
    compte<br>
    Closing this window end connection with your account
  </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);


ipt Voir / Cacher / Télécharger
#!/bin/sh

# Script de Gestion du Pare-Feu IPTABLES
##################################################################
IPTABLES="/sbin/iptables"

# Reseaux VPN et Chilli
INTIF="vlan846"
INTNW="10.8.246.0/24"
INTIP="10.8.246.1"

# Reseaux divers
NW_CRIC="147.173.3.0/24"
NET="0.0.0.0/0"

# Interfaces Chillispot
PCEXTIF="vlan246"
PCEXTIP="147.173.246.1"
PCTUNIF="tun0"   # On ne peut pas forcer ce tun0, donc on force tun3

# Adresses des serveurs et protocoles que les utilisateurs ou le portail captif
# ont le droit de contacter
# adresse de LABS = {DNS,SMTP}, LABS2 = DNS2
SMTP="147.173.1.26"
RADIUS="147.173.1.26/31"
IMAPs="0.0.0.0/0"
POP3s="0.0.0.0/0"
DNS="147.173.1.26/31"
LDAP="147.173.1.26/31"
NTP="147.173.1.254"

#_______________________________________________________________________________
# Chargement des modules
modprobe ip_tables ipt_LOG ipt_state iptable_nat ip_conntrack iptable_filter
modprobe ip_conntrack_ftp
# Initialisation
$IPTABLES -F INPUT
$IPTABLES -F OUTPUT
$IPTABLES -F FORWARD
$IPTABLES -F -t nat

if [ "$1" == "stop" ]; then
  $IPTABLES -P INPUT   ACCEPT
  $IPTABLES -P FORWARD ACCEPT
  $IPTABLES -P OUTPUT  ACCEPT
  echo "Flush des regles : ACCEPT Partout"
  exit
fi

##################################################################
# Politique Principale
##################################################################
$IPTABLES -P INPUT   DROP               # N'autorise pas ce qui entre
$IPTABLES -P FORWARD DROP               # N'autorise pas le forwarding
$IPTABLES -P OUTPUT  DROP               # N'autorise pas ce qui sort

#Tout est autorise sur l'interface de loopback.
$IPTABLES -A INPUT   -i lo -j ACCEPT
$IPTABLES -A OUTPUT  -o lo -j ACCEPT

#    .----   /   /  /////  /      /      /////
#   /       /   /    /    /      /        /
#  /       /////    /    /      /        /
# /       /   /    /    /      /        /
# \____  /   /  /////  /////  /////  /////

######   ######  PETIT COMMENTAIRE SUR LES INTERFACES INTERNES   ######   ######
# Pour que tout fonctionne correctement au niveau du routage, il est necessaire#
# de ne PAS mettre d'adresse IP pour la partie VLAN846. Dans ce cas, tous les  #
# paquets transiteront par l'interface tunnel. Sinon les paquets arrivent sur  #
# les deux interfaces et repartent par vlan846.
######   ######    ######   ######   ######   ######   ######    ######   ######

# COTE UTILISATEURS
##################################################################
#EN ENTREE, UTILISTEURS -- vers --> CHILLI
##################################################################
# HTTP sur le port 80, HTTPS sur le port 443, CHILLI sur le port 3990, DHCP sur les ports 68/67
$IPTABLES -A INPUT   -i $PCTUNIF -p icmp -s $INTNW -d $NET -j ACCEPT
$IPTABLES -A INPUT   -i $PCTUNIF -p udp --sport 68 --dport 67 -j ACCEPT
$IPTABLES -A INPUT   -i $PCTUNIF -p tcp -s $INTNW --sport 1024:65535 -d $INTIP --dport 80 -j ACCEPT
$IPTABLES -A INPUT   -i $PCTUNIF -p tcp -s $INTNW --sport 1024:65535 -d $INTIP --dport 443 -j ACCEPT
$IPTABLES -A INPUT   -i $PCTUNIF -p tcp -s $INTNW --sport 1024:65535 -d $INTIP --dport 3990 -j ACCEPT
##################################################################
#EN SORTIE, CHILLI -- vers --> UTILISATEURS
##################################################################
$IPTABLES -A OUTPUT  -o $PCTUNIF -p icmp -s $INTIP -d $INTNW -j ACCEPT
$IPTABLES -A OUTPUT  -o $PCTUNIF -p icmp -j ACCEPT
$IPTABLES -A OUTPUT  -o $PCTUNIF -m state --state ESTABLISHED -j ACCEPT
$IPTABLES -A OUTPUT  -o $PCTUNIF -p udp -s $INTIP --sport 67 -d $INTNW --dport 68 -j ACCEPT

##################################################################
# COTE INTERNET
##################################################################
#EN ENTREE, INTERNET -- vers --> CHILLI
#       - SSH depuis le CRIC
##################################################################
$IPTABLES -A INPUT   -i $PCEXTIF -p icmp -j ACCEPT
$IPTABLES -A INPUT   -i $PCEXTIF -m state --state ESTABLISHED -j ACCEPT
$IPTABLES -A INPUT   -i $PCEXTIF -p tcp -s $NW_CRIC --sport 1024:65535 -d $PCEXTIP --dport 22 -j ACCEPT
##################################################################
#EN SORTIE, CHILLI -- vers --> INTERNET
##################################################################
# HTTP, SMTP vers LABS, NTP vers RT-CNRS, RADIUS vers LABS
$IPTABLES -A OUTPUT  -o $PCEXTIF -p icmp -j ACCEPT
$IPTABLES -A OUTPUT  -o $PCEXTIF -m state --state ESTABLISHED -j ACCEPT
$IPTABLES -A OUTPUT  -o $PCEXTIF -p tcp -s $PCEXTIP --sport 1024:65535 -d $NW_CRIC --dport 22 -j ACCEPT
$IPTABLES -A OUTPUT  -o $PCEXTIF -p tcp -s $PCEXTIP --sport 1024:65535 -d $SMTP --dport 25 -j ACCEPT
$IPTABLES -A OUTPUT  -o $PCEXTIF -p udp -s $PCEXTIP --sport 1024:65535 -d $DNS --dport 53 -j ACCEPT
$IPTABLES -A OUTPUT  -o $PCEXTIF -p tcp -s $PCEXTIP --sport 1024:65535 -d $NET --dport 80 -j ACCEPT
$IPTABLES -A OUTPUT  -o $PCEXTIF -p udp -s $PCEXTIP --sport 123        -d $NTP --dport 123 -j ACCEPT
$IPTABLES -A OUTPUT  -o $PCEXTIF -p udp -s $PCEXTIP --sport 1024:65535 -d $RADIUS --dport 1812:1813 -j ACCEPT

##################################################################
# FORWARD (les ports qu'on autorise a sortir une fois loggue)
##################################################################
#EN SORTIE,  DES UTILISATEURS -- vers --> l'INTERNET
##################################################################
# SMTP vers LABS, DNS vers LABS, smtp, HTTP, IMAPs, ICMP, FTP, POP3s, LDAP
$IPTABLES -A FORWARD -i $PCTUNIF -p icmp -s $INTNW -d $NET -j ACCEPT
$IPTABLES -A FORWARD -i $PCTUNIF -m state --state RELATED,ESTABLISHED -j ACCEPT
$IPTABLES -A FORWARD -i $PCTUNIF -p tcp -s $INTNW --sport 1024:65535 -d $SMTP --dport 25 -j ACCEPT
$IPTABLES -A FORWARD -i $PCTUNIF -p tcp -s $INTNW --sport 1024:65535 -d $NET --dport 21 -j ACCEPT
$IPTABLES -A FORWARD -i $PCTUNIF -p udp -s $INTNW --sport 1024:65535 -d $DNS --dport 53 -j ACCEPT
$IPTABLES -A FORWARD -i $PCTUNIF -p tcp -s $INTNW --sport 1024:65535 -d $NET --dport 80 -j ACCEPT
$IPTABLES -A FORWARD -i $PCTUNIF -p tcp -s $INTNW --sport 1024:65535 -d $LDAP --dport 389 -j ACCEPT
$IPTABLES -A FORWARD -i $PCTUNIF -p tcp -s $INTNW --sport 1024:65535 -d $NET --dport 443 -j ACCEPT
$IPTABLES -A FORWARD -i $PCTUNIF -p tcp -s $INTNW --sport 1024:65535 -d $IMAPs --dport 993 -j ACCEPT
$IPTABLES -A FORWARD -i $PCTUNIF -p tcp -s $INTNW --sport 1024:65535 -d $POP3s --dport 995 -j ACCEPT

##################################################################
#EN ENTREE, D'INTERNET vers les UTILISATEURS
##################################################################
$IPTABLES -A FORWARD -i $PCEXTIF -p icmp -s $NET -d $INTNW -j ACCEPT
$IPTABLES -A FORWARD -i $PCEXTIF -m state --state RELATED,ESTABLISHED -j ACCEPT

#    /      .---.   .---.        .---.  .---.
#   /      /    /  /            /   /  /
#  /      /    /  /  ..        /---'  /
# /      /    /  /    /       /      /
# \____  \___/   \___/       /      \___,  

##################################################################
# LOG (en /var/log/syslog)
##################################################################
# Log de l'interface interne Portail Captif (en entre/sortie)
#$IPTABLES -A INPUT   -i $INTIF -j LOG --log-level debug --log-prefix "REJET INPUT INTIF: "
#$IPTABLES -A OUTPUT  -o $INTIF -j LOG --log-level debug --log-prefix "REJET OUTPUT INTIF: "
#$IPTABLES -A FORWARD -i $INTIF -j LOG --log-level debug --log-prefix "REJET FORWARD input INTIF: "
#$IPTABLES -A FORWARD -i $INTIF -j LOG --log-level debug --log-prefix "REJET FORWARD output INTIF: "
$IPTABLES -A INPUT   -i $INTIF -j DROP
$IPTABLES -A OUTPUT  -o $INTIF -j DROP
$IPTABLES -A FORWARD -i $INTIF -j DROP
$IPTABLES -A FORWARD -o $INTIF -j DROP

# Log de l'interface exterieure Portail Captif (en entre/sortie)
$IPTABLES -A INPUT   -i $PCEXTIF -j LOG --log-level debug --log-prefix "REJET INPUT PCEXTIF: "
$IPTABLES -A OUTPUT  -o $PCEXTIF -j LOG --log-level debug --log-prefix "REJET OUTPUT PCEXTIF: "
$IPTABLES -A INPUT   -i $PCEXTIF -j DROP
$IPTABLES -A OUTPUT  -o $PCEXTIF -j DROP

# Log de l'interface tunnel Portail Captif (en entre/sortie)
$IPTABLES -A INPUT   -i $PCTUNIF -j LOG --log-level debug --log-prefix "REJET INPUT PCTUNIF: "
$IPTABLES -A OUTPUT  -o $PCTUNIF -j LOG --log-level debug --log-prefix "REJET OUTPUT PCTUNIF: "
$IPTABLES -A FORWARD -i $PCTUNIF -j LOG --log-level debug --log-prefix "REJET FORWARD in PCTUNIF: "
$IPTABLES -A FORWARD -o $PCTUNIF -j LOG --log-level debug --log-prefix "REJET FORWARD out PCTUNIF: "
$IPTABLES -A INPUT   -i $PCTUNIF -j DROP
$IPTABLES -A OUTPUT  -o $PCTUNIF -j DROP
$IPTABLES -A FORWARD -i $PCTUNIF -j DROP
$IPTABLES -A FORWARD -o $PCTUNIF -j DROP

#    /      .---.   .---.
#   /      /    /  /     
#  /      /    /  / ...  
# /      /    /  /    /  
# \____  \___/   \___/  

# On loggue tout le reste...
$IPTABLES -A INPUT   -j LOG --log-level debug --log-prefix "REJET INPUT NOIF : "
$IPTABLES -A OUTPUT  -j LOG --log-level debug --log-prefix "REJET OUTPUT NOIF: "
$IPTABLES -A FORWARD -j LOG --log-level debug --log-prefix "REJET FORWARD NOIF: "

echo "Mise en place des regles de filtrage        [  OK  ]"

##################################################################
# NAT pour le portail captif
##################################################################
# C'est l'ensemble des interfaces virtuelles qui attribura une @ publique a une
# @ privee
for i in `seq 2 127`; do
  # Activation du NAT (sans rien faire) pour les reseaux 10.0.0.0/8 (sinon 
  # on ne parle pas car on est limite par le rp_filter)
  $IPTABLES -t nat -A POSTROUTING -s 10.8.246.${i} -d 10.0.0.0/8 -o $PCEXTIF -j SNAT --to-source 10.8.246.${i}
  # activation du NAT pour les adresses 2 a 63
  $IPTABLES -t nat -A POSTROUTING -s 10.8.246.${i} -o $PCEXTIF -j SNAT --to-source 147.173.246.${i}
  # Activation des adresses virtuelles
  ip address list | grep -q "147.173.246.${i} " || ip address add 147.173.246.${i} dev $PCEXTIF
done
echo "Mise en place des adresses secondaires      [  OK  ]"


Vérification de fonctionnement

On teste le portail captif. Pour cela, il faut faire les tests du tableau 4 dans l'ordre.

Validation de fonctionnement

La validation doit confirmer le passage du mot de passe en mode crypté pendant l'authentification. Elle doit aussi confirmer qu'une authentification est bien nécessaire pour accéder au réseau et qu'une fois la connexion établie, les communications autorisées sont en clair.
CNRS / Centre Réseau et Informatique Commun (CRIC) - Dernière modification : 26/06/2019.

Mail : CRIC @ grenoble.cnrs.fr (sans les espaces)