NAME Captive::Portal - Perl based solution for controlled network access ABSTRACT A so called *Captive Portal* written in perl for Linux Gateways. For a longer explanation see: DESCRIPTION Captive::Portal a.k.a. CaPo is a Hotspot solution for Linux Gateways. CaPo is developed and in service at Ulm University for thousands of concurrent users. The main focus is scalability, performance, simple administration and user-friendliness. The goals were achieved by using scalable technologies like ipset(8) instead of native iptables(8), FastCGI instead of CGI and a fine tuned concurrent session handling based on the filesystem locking mechanism without any need for an additional RDBMS. CaPo is compatible with any FastCGI enabled HTTP(S)-server. ALGORITHM IN SHORT 1. Internal NAT redirect HTTP-traffic on the gateways inside interface - from unknown clients - is redirected by an iptables(8) NAT-rule to a port the HTTP-server is listen, e.g. iptables -t nat -A PREROUTING -i eth1 -p tcp --dport 80 -j REDIRECT --to-port 5281 2. HTTP to HTTPS redirect The HTTP-server redirects the HTTP-request by a rewrite rule to an HTTPS-request for the CaPo script *capo.fcgi* , e.g. RewriteEngine On RewriteRule .* https://gateway.acme.org/capo/? [R,L] 3. SESSION LOGIN The *capo.fcgi* script offers a login/splash page. After successful login the firewall is dynamically changed to allow this clients IP/MAC tuple for internet access. 4. SESSION LOGOUT The capo.fcgi script offers a status/logut page. After successful logout the firewall is dynamically changed to disallow this IP/MAC tuple for internet access. 5. SESSION IDLE A cronjob fires periodically the capo-ctl.pl script checking for idle sessions. Idle means, the client didn't send any packet for a period of time (cfg param: IDLE_TIME = 10min). Before a session is put into idle state the client is once pinged. It is a design goal not requiring JavaScript on clients! 6. SESSION REACTIVATION For a short period of time (cfg param: KEEP_OLD_STATE_PERIOD = 1h) the session is still on disc, but in idle state. If a client request matches the sessions IP/MAC/COOKIE data, the session is reactivated without a login page. INSTALLATION Please see the INSTALL file in this distribution. As a minimum please be aware of the following access restrictions: Captive::Portal needs access to iptables(8) and ipset(8) to change the firewall-rules on request. You must add the following rule (or similar) to the sudoers file, depending on the username of your http daemon: WWW_USER ALL=NOPASSWD: /PATH/TO/iptables, /PATH/TO/ipset If you use fping(8) (see USE_FPING config parameter) to trigger idle sessions before going idle you must add fping to the sudoers file like ipset and iptables, regardless of the suid bit on fping, since we need special timing flags available only for root: WWW_USER ALL=NOPASSWD: /PATH/TO/iptables, /PATH/TO/ipset, /PATH/TO/fping The default $SESSIONS_DIR is set to '/var/cache/capo'. WWW_USER must be the owner of this dir with write permissions! CONFIGURATION The configuration file is searched in the following default places: $ENV{CAPTIVE_PORTAL_CONFIG} || $Bin/../etc/local/config.pl || $Bin/../etc/config.pl CONFIGURATION PARAMETERS The configuration syntax is perl. PRESET GLOBAL PACKAGE VARIABLES, CHANGES POSSIBLE The following variables can be used for interpolation in config values. $APP_NAME = 'capo' $APP_DIR = "$Bin/../" PRESET DEFAULTS, CHANGES POSSIBLE DOCUMENT_ROOT => "$APP_DIR/static" Basedir for static content like images, css or error pages. TEMPLATE_INCLUDE_PATH => "$APP_DIR/templates/local/:$APP_DIR/templates/orig" Directories to search for templates. RUN_USER => 'wwwrun' Drop privileges to RUN_USER. RUN_GROUP => 'www', Drop privileges to RUN_GROUP. SESSIONS_DIR => "/var/cache/$APP_NAME" Where to store the session files. This directory must exist und must be readable/writeable by RUN_USER. SECURE_COOKIE => ON If this attribute is set, the cookie will only be sent to your script if the CGI request is occurring on a secure channel, such as SSL. SESSION_MAX => 48 * 3600 # 2d Max session time until a forced disconnect. IDLE_TIME => 60 * 10 # 10 min How long to wait for activity from ip/mac until a session is marked idle. KEEP_OLD_STATE_PERIOD => 1 * 60 * 60, # 1h How long to keep idle session records on disk for fast reconnect with proper ip/mac/cookie match. USE_FPING => ON # use fping to trigger idle clients Use fping(8) to trigger idle clients. FPING_OPTIONS => [qw(-c 1 -i 1 -t 1 -q)] # SuSe default fping(8) options for current Linux distribution. LOCAL PARAMETERS, CHANGES NEEDED ADMIN_SECRET Passphrase for detailed sessions view. AUTHEN_SIMPLE_MODULES Authentication is handled by the Authen::Simple framework. You may stack any of the Authen::Simple::... plugins for authentication, see the $Bin/../etc/config.pl template. IPTABLES->capture_if => 'eth1' The inside gateway interface, e.g. 'eth1'. All http traffic, not allowed by any predefined rule, is captured and redirected to the capo.fcgi script. IPTABLES->capture_net => '192.168.0.0/22' The inside IP network in CIDR notation, e.g. '192.168.0.0/22' IPTABLES->capture_ports => [80, 8080] What tcp ports should be captured and redirected, e.g. [ 80, 8080] IPTABLES->redirect_port => 5281 The port where the HTTP-server is listen in order to rewrite this http request to an https request. The above settings result in a NAT rule equivalent to: iptables -t nat -A PREROUTING -i eth1 -s 192.168.0.0/22 ! -d 192.168.0.0/22 \ -p tcp -m multiport --dports 80,8080 -j REDIRECT --to-port 5281 IPTABLES->throttle => OFF You may throttle HTTP/HTTPS requests/sec per client IP. Some clients/gadgets fire a lot of HTTP traffic without human intervention. Depending on your hardware and your encryption resources this will overload your gateway. IPTABLES->throttle_ports => [ 80, 5281] You should protect/throttle port 80 and the redirect_port (see above). IPTABLES->throttle_seconds => 30 IPTABLES->throttle_hitcount => 15 Both parameters define the average and the burst. Average is hitcount/seconds and burst is hitcount in seconds. With the values of 30 and 15, the average would be 15hits/30s => 1hit/2s. The burst would be 15hits in 30 seconds. The above settings result in iptable rules equivalent to: # throttle/drop new connections iptables -t filter -A INPUT -p tcp --syn -m multiport --dports 80,5281 \ -m recent --name capo_throttle --rcheck --seconds 30 --hitcount 15 -j DROP # at last accept new connections but set/update the recent table iptables -t filter -A INPUT -p tcp --syn -m multiport --dports 80,5281 \ -m recent --name capo_throttle --set -j ACCEPT IPTABLES->open_services Allow access to open local services like DHCP, DNS, NTP, ... IPTABLES->open_clients Allow access for some dumb clients without autentication. IPTABLES->open_servers Allow access to some open servers. IPTABLES->open_networks Allow access to some open networks. I18N_LANGUAGES Supported languages for system messages and HTML templates. I18N_FALLBACK_LANG Fallback language if the client message isn't supported in the system message catalog and templates. I18N_MSG_CATALOG Translations of the system messages. LOGGING Logging is handled by the Log::Log4perl module. The logging configuration is searched in the following default places: $ENV{CAPTIVE_PORTAL_LOG4PERL} || $Bin/../etc/local/log4perl.conf || $Bin/../etc/log4perl.conf SEE ALSO capo.fcgi (f)cgi script for Captive::Portal capo-ctl.pl Controller script for Captive::Portal test-server.pl Simple HTTP server based on HTTP::Server::Simple::CGI to test the Captive::Portal installation. Don't use it for production. mock-server.pl Simple HTTP server based on WWW::Mechanize::CGI for the test suite during installation. BUGS AND LIMITATIONS There are no known problems with this module. Please report any bugs or feature requests to "bug-captive-portal at rt.cpan.org", or through the web interface at . I will be notified, and then you'll automatically be notified of progress on your bug as I make changes. AUTHOR Karl Gaissmaier, "" LICENSE AND COPYRIGHT Copyright 2010-2011 Karl Gaissmaier, all rights reserved. This distribution is free software; you can redistribute it and/or modify it under the terms of either: a) the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version, or b) the Artistic License version 2.0. The full text of the license can be found in the LICENSE file included with this distribution.