OpenBSD Captive Portal

classic Classic list List threaded Threaded
5 messages Options
Reply | Threaded
Open this post in threaded view
|

OpenBSD Captive Portal

Byron Klippert
Hello misc,

Using OpenBSD 5.0 I've managed to put together a simple captive portal
based on a ticketed system. When a customer wants to use the internet
they must get an access key from the front desk. When they associate
with the network they must authorize the key in order to pass through
the firewall.


This system was built very short notice and has been running relatively
smooth for several months. My intent is to turn it over to the public
for scrutiny and hopefully some feedback.


There are two web interfaces, one for the admins which allows key
creation and key summaries, and one for the user; which until they
authorize a valid key, only takes them to a page which asks for a key
input (Apache mod_rewrite). Once authenticated they can also check their
usage summary.


The web interfaces interact with the system through CGI scripts, httpd
is run chroot disabled (httpd_flags="-u").


The system offers up dhcpd leases to whomever associates successfully
with the access points, dhcpd is run to interact with pf's table entries
(dhcpd_flags="-L leased_users -C authorized_users vr0 vr1).


The other network services in effect are of course pf and named.


pf's config is setup to allow leased_users dns resolution and web access
to the gateway, once authenticated the user becomes part of the
authorized_users table and is unrestricted. The authorized_users table
has counters turned on. The counters are monitored by a cron script
which deletes the table entry for anyone who has exceeded a pre-defined
limit.


The scripts consist of: authorize-key.cgi, check-usage-admin.cgi
check-usage-user.cgi, generate-key.cgi, generate-keys.cgi,
generate-key-1GB.cgi, monitor-usage.cgi, monitor-usage-1GB.cgi,
search-records.cgi, show-keys.cgi, show-keys-1GB.cgi, show-limits.cgi,
show-start.cgi, show-users.cgi. Email me off-list and I'll be happy to
share the scripts.


The only way I can see someone getting passed this portal is through arp
spoofing or something similar. I haven't witnessed it yet although it is
a real possibility. What does this mean, well someone can force an IP
onto their computer and "piggy-back" on someone else's access key or
change their mac address and cause other confusion.


The question I have is relating to the way which I monitor usage
summaries. I've included the script below (monitor-usage.cgi) for
reference. I'm currently grep'ing and cut'ing the data output by pfctl.
So far it's been working great, BUT, is there an easier, more efficient
way to get data out from pfctl?


All comments welcome!


#!/bin/ksh
#
#       Monitor Usage (cron)
#

LOCKFILE_KEY_LIST="/tmp/key_list.lockfile"
LOCKFILE_AUTH_LOG="/tmp/auth_log.lockfile"
KEY_LIST="/var/www/cgi-bin/.key_list"
AUTH_LOG="/var/www/cgi-bin/.auth_log"
LIMIT_LOG="/var/www/cgi-bin/.limit_log"

USAGE_LIMIT="157286400"


# For each key in the active key list, search for the key and associated
IP's in the authorized user list
for KEY in `cat "$KEY_LIST"`; do
if [ `grep -w -e "$KEY" "$AUTH_LOG" >/dev/null 2>&1; echo $?` -eq "0" ];
then
TOTAL=0
for AUTH in `cat "$AUTH_LOG" | grep -w -e "$KEY"`; do
i=0
for ADDRESS in `echo "$AUTH" | cut -d ',' -f '3'`; do
i=$((++i))
       
if [ `sudo pfctl -t authorized_users -T show -v | grep -A 2 -e
${ADDRESS} | grep Bytes >/dev/null 2>&1; echo $?` -eq "0" ]; then
PFSTAT[$i]=$(sudo pfctl -t authorized_users -T show -v | grep -w -A 5 -e
${ADDRESS})
IP_ADDRESS[$i]=$(echo ${PFSTAT[$i]} | cut -d ' ' -f '1')
TIMESTAMP[$i]=$(echo ${PFSTAT[$i]} | cut -d ' ' -f '3-7')
IN_PASS_BYTES[$i]=$(echo ${PFSTAT[$i]} | cut -d ' ' -f '20')
OUT_PASS_BYTES[$i]=$(echo ${PFSTAT[$i]} | cut -d ' ' -f '34')
else
PFSTAT[$i]=$(sudo pfctl -t authorized_users -T show -v | grep -w -A 1 -e
${ADDRESS})
IP_ADDRESS[$i]=$(echo ${PFSTAT[$i]} | cut -d ' ' -f '1')
TIMESTAMP[$i]=$(echo ${PFSTAT[$i]} | cut -d ' ' -f '3-7')
IN_PASS_BYTES[$i]=0
OUT_PASS_BYTES[$i]=0
fi

A=${IN_PASS_BYTES[$i]}
B=${OUT_PASS_BYTES[$i]}
TOTAL_USAGE[$i]=$((A + B))
C=${TOTAL_USAGE[$i]}

TOTAL=$((C + TOTAL))

echo "$KEY,$TOTAL"
done
done

if [ "$TOTAL" -ge "$USAGE_LIMIT" ]; then
# Insert timestamp and key into usage log
echo -n "`date "+%Y/%m/%d@%H:%M:%S"`,$KEY," >> "$LIMIT_LOG"

for AUTH in `cat $AUTH_LOG | grep $KEY`; do
for ADDRESS in `echo $AUTH | cut -d ',' -f '3'`; do
# Append all the IP addresses paired to the access key
echo -n "$ADDRESS," >> "$LIMIT_LOG"

# Remove address from authorized users table
echo -n "$KEY,$ADDRESS, "; sudo pfctl -t authorized_users -T delete
"$ADDRESS"

# Create lockfile or wait
while true; do
if mkdir "$LOCKFILE_KEY_LIST" >/dev/null 2>&1; then
break
fi
sleep 3
done

# Remove key from key list
NEW_KEY_LIST=$(sed -e "/$KEY/d" "$KEY_LIST"); echo "$NEW_KEY_LIST" | tr
' ' '\n' > "$KEY_LIST"

# Remove lockfile
rmdir "$LOCKFILE_KEY_LIST"

# Create lockfile or wait
while true; do
if mkdir "$LOCKFILE_AUTH_LOG" >/dev/null 2>&1; then
break
fi
sleep 3
done

# Remove key from auth list
NEW_AUTH_LOG=$(sed -e "/$KEY/d" "$AUTH_LOG"); echo "$NEW_AUTH_LOG" | tr
' ' '\n' > "$AUTH_LOG"

# Remove lockfile
rmdir "$LOCKFILE_AUTH_LOG"
done
done

# Complete the usage log entry with the total bytes used up for the
access key
echo "$TOTAL" >> "$LIMIT_LOG"
fi
fi
done


 
  Byron Klippert
  [hidden email]
  http://byronklippert.ca
  Tel 867-332-4184

Reply | Threaded
Open this post in threaded view
|

Re: OpenBSD Captive Portal

David Diggles-2
On Mon, Aug 20, 2012 at 12:42:16PM -0700, Byron Klippert wrote:
> The web interfaces interact with the system through CGI scripts, httpd
> is run chroot disabled (httpd_flags="-u").

Just one comment for now.  You can run it as chroot if you copy any
dependancies into the chroot, including binaries, libraries.

...and be sure to update them if patches come out.

.d.d.

Reply | Threaded
Open this post in threaded view
|

Re: OpenBSD Captive Portal

Stuart Henderson
On 2012-08-21, David Diggles <[hidden email]> wrote:
> On Mon, Aug 20, 2012 at 12:42:16PM -0700, Byron Klippert wrote:
>> The web interfaces interact with the system through CGI scripts, httpd
>> is run chroot disabled (httpd_flags="-u").
>
> Just one comment for now.  You can run it as chroot if you copy any
> dependancies into the chroot, including binaries, libraries.

> ...and be sure to update them if patches come out.

depends what's needed, but it's often not really a security win
to copy enough of the OS into the chroot jail so that scripts can
run, especially if it means it's unlikely to be kept updated.

OTOH if the only need for non-chroot is to access PF tables, and
the scripts are in a language which can easily run inside chroot
(e.g. perl with mod_perl), see the 'tabled' package.

Reply | Threaded
Open this post in threaded view
|

Re: OpenBSD Captive Portal

Hermes Ojeda Ruiz
I was working few weeks ago to recover the project Wicap-PHP:

https://github.com/LogicalBricks/wicap-php

Caleb Phillips give me the source code to maintain. Now it works for
OpenBSD 5.x. The behavior is really simple, but maybe need a good install
script.

On Tue, Aug 21, 2012 at 10:10 AM, Stuart Henderson <[hidden email]>wrote:

> On 2012-08-21, David Diggles <[hidden email]> wrote:
> > On Mon, Aug 20, 2012 at 12:42:16PM -0700, Byron Klippert wrote:
> >> The web interfaces interact with the system through CGI scripts, httpd
> >> is run chroot disabled (httpd_flags="-u").
> >
> > Just one comment for now.  You can run it as chroot if you copy any
> > dependancies into the chroot, including binaries, libraries.
>
> > ...and be sure to update them if patches come out.
>
> depends what's needed, but it's often not really a security win
> to copy enough of the OS into the chroot jail so that scripts can
> run, especially if it means it's unlikely to be kept updated.
>
> OTOH if the only need for non-chroot is to access PF tables, and
> the scripts are in a language which can easily run inside chroot
> (e.g. perl with mod_perl), see the 'tabled' package.
>
>


--
Hermes Ojeda Ruiz
LogicalBricks Solutions
http://logicalbricks.com

Reply | Threaded
Open this post in threaded view
|

Re: OpenBSD Captive Portal

Byron Klippert
I should make clear that my approach was time sensitive (which is why I
stayed in shell) and requires only OpenBSD 5.0 base.

Trade-offs being mainly efficiency; depending on how often the
"monitor-usage.cgi" script is called.

I'd say that it complies with most of the tenants below:

+ Small is beautiful.
+ Make each program do one thing well.
+ Build a prototype as soon as possible.
+ Choose portability over efficiency.
+ Store data in flat text files.
+ Use software leverage to your advantage.
+ Use shell scripts to increase leverage and portability.
+ Avoid captive user interfaces.
+ Make every program a filter.


Cheers,

- Byron

On Tue, Aug 21, 2012, at 10:01 AM, Hermes Ojeda Ruiz wrote:

> I was working few weeks ago to recover the project Wicap-PHP:
>
> https://github.com/LogicalBricks/wicap-php
>
> Caleb Phillips give me the source code to maintain. Now it works for
> OpenBSD 5.x. The behavior is really simple, but maybe need a good install
> script.
>
> On Tue, Aug 21, 2012 at 10:10 AM, Stuart Henderson
> <[hidden email]>wrote:
>
> > On 2012-08-21, David Diggles <[hidden email]> wrote:
> > > On Mon, Aug 20, 2012 at 12:42:16PM -0700, Byron Klippert wrote:
> > >> The web interfaces interact with the system through CGI scripts, httpd
> > >> is run chroot disabled (httpd_flags="-u").
> > >
> > > Just one comment for now.  You can run it as chroot if you copy any
> > > dependancies into the chroot, including binaries, libraries.
> >
> > > ...and be sure to update them if patches come out.
> >
> > depends what's needed, but it's often not really a security win
> > to copy enough of the OS into the chroot jail so that scripts can
> > run, especially if it means it's unlikely to be kept updated.
> >
> > OTOH if the only need for non-chroot is to access PF tables, and
> > the scripts are in a language which can easily run inside chroot
> > (e.g. perl with mod_perl), see the 'tabled' package.
> >
> >
>
>
> --
> Hermes Ojeda Ruiz
> LogicalBricks Solutions
> http://logicalbricks.com