=^.^=

Transparent Proxy for Hot Spot/Public Network Web-Based Authentication on ClearOS

karma

Despite the title  neither making a hot spot nor "public" network is my intent in this article, but what it will cover can be directly applied to these situations.

One of my clients is a small ISP and collocation datacentre which has a network that is configured 100% statically on both sides. This sounds tedious at first but consider that we could use a DHCP server to direct un-configured clients (new server/virtual machine, new router, wiped configuration, new computer etc.) to use a gateway running a transparent web proxy that forcefully tells them to call in and have their router/host reconfigured remotely or by phone.

This ensures that clients call in quickly (because they can't do anything but see the instructions telling them to) rather than assume there is a long-but-temporary problem with the connection, leading to unjustified dissatisfaction with the service. We also want to want to try and outrun any rogue DHCP servers that might be out there because some asshat plugged his d-link in backwards.

I created a VM a couple years ago that did just this but it has succumbed to file system corruption and they would like a new one. In the last week I have been drafting an article on using transparent proxy techniques to provide blanket anonymity to a private network, quelle coincidence! Since it's Christmas eve (and I'm a little drunk) I thought I might get fancy and slap a "technician's login" on this one so the field techs can do quicker and easier testing by using DHCP.

My client has multiple peers and subnets; if they let their clients whom have dropped their configuration simply use DHCP as a "fallback" network to provide the illusion of service continuity we end up with several problems:

  • Clients with public IP addresses who depend on them for incoming connections would probably not notice until "the phones start ringing" because from their side of the NAT they are still able to browse the web etc.
  • Degradation of service where bandwidth controls and Quality of Service have been implemented; defending against accusations of not meeting Service Level Agreements
  • Running the risk of overloading a single pipe with fallback users if they go unattended
    • Load balancing can help address this but has its own caveats
  • IP-based accounting and service monitoring will be negatively impacted

Before we begin you will need a working deployment of ClearOS, either installed to a dedicated physical server or running in a virtual machine. You can use my pre-installed virtual machines to get running quickly:

Note: Virtual machines should be given at least 300MB RAM to work with when using Squid or you may encounter counter-intuitive out-of-memory issues.

We will need to install at least three modules from ClearSDN.  If you are using the above-listed virtual machine images you must load the following address into your browser before you can register with ClearSDN: https://lan-ip:81/admin/register.php?Reset=yes . In webconfig, go to Software Modules under the ClearCenter menu and ensure the following modules are installed:

  • Content filtering module (DansGuardian)
  • Web proxy server module (Squid)
  • Caching nameserver module (provides DHCP)
  • Firewall - custom rules

First you'll need to set up a DHCP pool on the private network. Click on DHCP Server in the Network menu. Delete the default pool then click the Add button next to your private network's entry. I chose to use 192.168.66.0/24 for the private network and since the whole thing will be for DHCP clients it's safe to set the pool from .2 to .254. Once you have saved the pool settings click the Start button at the top of the page to activate dnsmasq's DHCP functionality.

Click on Web Proxy under the Gateway menu. Click the To Auto button then the Start button at the top of the page. Enable Transparent Mode and Content Filter then click the Update button.

Click on Content Filter under the Gateway menu. Click the To Auto button then the Start button at the top of the page. Check the Blanket Block checkbox and click the Update button.

Set up a host to use DHCP and acquire a lease. Try to load any website. If you were successful you should be presented with a nice ClearOS page telling you the content filter has blocked the request. We can replace this page with our own custom sign-in page if we drop it in /var/webconfig/htdocs/public/filtered.inc.php:

<?php
        WebHeader("CONFIGURATION ERROR", "splash");
        print("<div style=\"margin-top: 100px;\"></div>");
        WebDialogWarning("Your router or computer is not configured correctly. Please call tech support immediately at (XXX) XXX-XXXX.<br>
You may be asked to provide the make of your router and this IP address: <strong>{$_SERVER['REMOTE_ADDR']}</strong>.");
        print("<form style=\"margin: 0px; padding: 0px;\" action=\"https://{$_SERVER['SERVER_ADDR']}:81/admin/tech.php\" method=\"post\">");
    WebTableOpen("Technician's Login", "600");
    echo "
        <tr>
            <td class='mytablesubheader' nowrap width='200'>Username</td>
            <td><input type=\"text\" name=\"username\"></td>
        </tr>
        <tr>
            <td width='200' class='mytablesubheader' nowrap>Password</td>
            <td><input type=\"password\" name=\"password\"></td>
        </tr>
        <tr>
            <td class='mytablesubheader' nowrap>  </td>
            <td style=\"text-align: center;\"><input type=\"submit\" value=\"Login\"></td>
        </tr>
    ";
    WebTableClose("600");
        print("</form>");
        WebFooter("splash");
?>

The layout broke a little when I changed the logo image so I added the 100px div at the top to space things out properly, you may not need it. As you can see we will be processing the request via the webconfig vhost on port 81. This will let us take advantage of its user permissions and function libraries. It does add a kink in fluidity however, as the first time one logs in they will have to accept an unsigned certificate.

UPDATE: I realized after deciding against using the ClearOS API to manipulate netfilter that using webconfig on port 81 for the authentication script is not necessary, further it probably never was due to the fact :82 is actually a webconfig vhost.

Before we make our login processor we need to prep the firewall. Only port 80 is under our control at this point but knowledgeable clients can still tunnel their connection through SSH, VPNs and so forth. If you have installed the custom firewall rules module edit ??/etc/rc.d/rc.firewall.custom otherwise use /etc/rc.firewall.local. The difference is that the custom firewall module provides an interface through webconfig. Add:

?iptables -t nat -A PREROUTING -d ! $LAN_ADDRESS -j DROP # Disable NAT

where $LAN_ADDRESS is the IP of your LAN interface. In our authentication script we'll be using this line to enable access and bypass proxying for individual IPs:

iptables -t nat -I PREROUTING -s $IP_ADDRESS -j ACCEPT

We also need to install the at daemon so we can put a time limit on the IP's connectivity:

# yum install at

It will automatically be set to start on boot if you install it via yum. Add webconfig to /etc/at.allow:

webconfig

We also need to give webconfig (or httpd if you will be using the web server module) permission to manipulate the NAT table. Run visudo and add this line to the bottom:

?webconfig ALL=(root) NOPASSWD: /sbin/iptables-bin

In my example authentication script below I'm going to use a simple array to store authentication credentials. It will be up to you to work in your own authentication system, I suggest either tying it into ClearOS' built-in LDAP implementation or via MySQL so that it can be managed through a web interface.  Create tech.php (or whatever suits you) in /var/webconfig/htdocs/admin/:

<?php

$credentials['tech'] = 'tech1234';
$credentials['emergency'] = 'emerg1234';

$validated = false;

foreach($credentials as $user => $pass)
{
        if($_POST['username'] == $user and $_POST['password'] == $pass)
                $validated = true;
}

if($validated)
{
        exec("sudo /sbin/iptables-bin -t nat -I PREROUTING -s {$_SERVER['REMOTE_ADDR']} -j ACCEPT");
        exec("echo \"sudo /sbin/iptables-bin -t nat -D PREROUTING -s {$_SERVER['REMOTE_ADDR']} -j ACCEPT\" | at now + 1hours");
        header("Location: http://www.google.ca/");
        die();
}
else
{
        die("You have not been validated. Please go back and try again.");
}

?>

You may choose to make the experience more fluid by passing the $url variable available from filtered.php as a hidden form element in filtered.inc.php then supplying it as the value for our Location HTTP header.

See Also:

Comments

• milen

planning to test it today and I will add more comments :) thanks again for nice tutorial.

• milen

very nice tutorial. it would be interesting for me to know what happens if I grant access to some IP, but he drops for some wi-fi reason and other MAC gets his IP via the DHCP? Is there some way to reserve for some time MAC to IP lock table or something... so that we are sure that we don't grant access to unlogged users?

Thanks, Cheers