Captive Portal Based on FreeRADIUS

While setting up firewall rules, make sure that you have a way to access the server other than through the network because you can end-up locking yourself out of the system.

This captive portal should not be used: it provides some connectivity ideas on how to use the scripting backends of FreeRADIUS but for a more correct solution please see the simple event correlator solution.

A captive portal would require a firewall change, so that, initially all packets will be blocked on the local interface (suppose the local interface is eth0). This can be accomplished by adding a rule early in the firewall chains:

iptables -A INPUT -i eth0 -j DROP

that will drop ALL the traffic on the local interface eth0. Now, the perl FreeRADIUS module can be used to call iptables and then allow certain MAC addresses through.

In order to do that (and since we have previously enabled perl in the post-auth section of FreeRADIUS the previous section), we edit /etc/FreeRADIUS/modules/perl in order to enable the func_post_auth hook and to specify a script:

--- perl.dist	2013-07-11 01:56:56.000000000 +0100
+++ perl	2013-07-10 12:27:57.000000000 +0100
@@ -11,7 +11,7 @@
 	#  'rlm_exec' module, but it is persistent, and therefore
 	#  faster.
 	#
-	module = ${confdir}/example.pl
+	module = ${confdir}/unlock_mac.pl
 
 	#
 	#  The following hashes are given to the module and
@@ -41,7 +41,7 @@
 	#func_checksimul = checksimul
 	#func_pre_proxy = pre_proxy
 	#func_post_proxy = post_proxy
-	#func_post_auth = post_auth
+	func_post_auth = post_auth
 	#func_recv_coa = recv_coa
 	#func_send_coa = send_coa
 	#func_xlat = xlat

It is important to notice that the post_auth hook will be triggered when FreeRADIUS has successfully authenticated the client. After the client has been authenticated, the perl script /etc/FreeRADIUS/unlock_mac.pl will be executed.

The perl script at /etc/FreeRADIUS/unclock_mac.pl uses sudo and uses iptables to add a rule that will allow the MAC address of the client reported by FreeRADIUS:

unlock_mac.pl
#!/usr/bin/perl
###########################################################################
##  Copyright (C) Wizardry and Steamworks 2013 - License: GNU GPLv3      ##
##  Please see: http://www.gnu.org/licenses/gpl.html for legal details,  ##
##  rights of fair usage, the disclaimer and warranty conditions.        ##
###########################################################################
# iptables
my $IPTABLES = '/usr/bin/sudo /sbin/iptables';
 
# FreeRADIUS log constants
use constant	INFO=>	3;
# FreeRADIUS return constants
use constant    RLM_MODULE_OK=>        2;#  /* the module is OK, continue */ 
 
sub post_auth {
        # if we are here, then authentication succeeded
        $mac = $RAD_REQUEST{'Calling-Station-Id'};
        $mac =~ s/\-/\:/g;
        $usr = $RAD_REQUEST{'User-Name'};
        if(index(`$IPTABLES -L -n`, "radius access for $usr") != -1) {
                return RLM_MODULE_OK;
        }
        system("$IPTABLES -I INPUT 1 -i eth0 -m mac --mac-source $mac -j ACCEPT -m comment --comment \"radius access for $usr\"");
        &radiusd::radlog(INFO, "Granted access for usr: ".$usr." with MAC address: ".$mac);
        return RLM_MODULE_OK;
}

The script requires an entry in /etc/sudoers:

freerad ALL= NOPASSWD: ALL

that can be further restricted to allow calling only /sbin/iptables instead of all commands.

Limitations

This implementation is broken: hostapd (the authenticator) should be responsible with triggering the scripts calling iptables. hostapd cannot do that - the hostapd code would have to be modified to do so.

Since FreeRADIUS is doing that job instead, FreeRADIUS is unable to tell whether a client has disconnected. Remember that FreeRADIUS only provides AAA but there is no hook for "the client has released the connection". Thus, FreeRADIUS can only add the MAC accept rule but it cannot delete it and there is no way of telling whether the client has disconnected or not.

Perhaps, a different approach would be to monitor hostapd's logs and, based on that, to add and remove MAC addresses as they are authenticated or they disconnect (checking every 5 seconds - as per the ap_max_inactivity setting in /etc/hostapd.conf). A great tool to use for a log variation would be the simple event correlator.


networking/802.1x/captive_portals/freeradius.txt ยท Last modified: 2022/04/19 08:27 by 127.0.0.1

Access website using Tor Access website using i2p Wizardry and Steamworks PGP Key


For the contact, copyright, license, warranty and privacy terms for the usage of this website please see the contact, license, privacy, copyright.