PfSense 2.3.2: Captive Portal + Non Transparent Squid3



  • Hi!

    I'll start by apologizing, i know this is a know problem, treated in other topics, like this one, https://forum.pfsense.org/index.php?topic=111670.0

    First, i'm working in a 2.3.2 (64bit) version of pfSense.

    Now, according to that topic, it is possible to have a working environment with Captive Portal + Squid3 + SquidGuard AND WPAD. I mean, without using the transparent option of squid. The fact is, i can't make it work, i don't know if i'm missing something in the translation from Portuguese or what,  but it simply won't work.

    I've tried all modifications i could find of the

    /usr/local/bin/check_ip.php

    file, most of which make it impossible for the Squid service to start.

    This one, for example:

    
    #!/usr/local/bin/php-cgi -q
    
    require_once("config.inc");
    require_once("globals.inc");
    error_reporting(0);
    global $g;
    // stdin loop
    if (!defined(STDIN)) {
    	define("STDIN", fopen("php://stdin", "r"));
    }
    if (!defined(STDOUT)) {
    	define("STDOUT", fopen('php://stdout', 'w'));
    }
    while (!feof(STDIN)) {
    	$line = trim(fgets(STDIN));
    	$files = glob("{$g['vardb_path']}/captiveportal*.db");
    	$answer="ERR";
    	foreach ($files as $file) {
    		$result = squid_cp_read_db($file);
    		//1419045939,1419045939,2000,2000,192.168.10.11,192.168.10.11,08:00:27:5c:e1:ee,08:00:27:5c:e1:ee,marcello,marcello,605a1f46e2d64556,605a1f46e2d64556,,,,,,,,,,,first,first
    		foreach ($result as $row) {
    			if ($row[2] != "" && $row[2] == $line) {
    				$answer = "OK user={$row[4]}";
    				break 2;
    			}
    	$check_ip = trim(fgets(STDIN));
    	$dbs = glob("{$g['vardb_path']}/captiveportal*.db");
    
    	foreach ($dbs as $db) {
    		if(!strpos($db, "_radius")) {
    			$status = squid_check_ip($db, $check_ip);
    			break;
    	}
    }
    	fwrite(STDOUT, "{$answer}\n");
    	if (isset($status)) {
    		fwrite(STDOUT, "OK user={$status}\n");
    	} else {
    		fwrite(STDOUT, "ERR\n");
    	}
    }
    /* read captive portal DB into array */
    function squid_cp_read_db($file) {
    	$cpdb = array();
    	$DB = new SQLite3($file);
    	if ($DB) {
    		$response = $DB->query("SELECT * FROM captiveportal");
    		if ($response != FALSE) {
    			while ($row = $response->fetchArray()) {
    				$cpdb[] = $row;
    			}
    		}
    		$DB->close();
    
    function squid_check_ip($db, $check_ip) {
    	exec("sqlite3 {$db} \"SELECT ip FROM captiveportal WHERE ip='{$check_ip}'\"", $ip);
    	if ($check_ip == $ip[0]) {
    		exec("sqlite3 {$db} \"SELECT username FROM captiveportal WHERE ip='{$check_ip}'\"", $user);
    		return $user[0];
    }
    	return $cpdb;
    }
    
    ?>
    
    

    Makes this happen:

    cache.log ->

    Error in argument 1, char 3: option not found
    Error in argument 1, char 3: option not found
    WARNING: check_cp #Hlpr9 exited
    FATAL: The check_cp helpers are crashing too rapidly, need help!

    Any help would be appreciated.

    Thanks!
    Diego.

    PF: I'm not using RADIUS, the idea is just to use one instance of Captive Portal, with users from the pfSense User Manager.



  • Ok.

    It's working. I don't know if that file has anything to do… But here is my current config...

    check_ip.php looks like this:

    
    #!/usr/local/bin/php-cgi -q
    require_once("config.inc");
    require_once("globals.inc");
    if (!extension_loaded('sqlite3')) {
    dl("sqlite3.so");
    }
    error_reporting(0);
    global $g;
    // stdin loop
    if (!defined(STDIN)) {
    	define("STDIN", fopen("php://stdin", "r"));
    }
    if (!defined(STDOUT)) {
    	define("STDOUT", fopen('php://stdout', 'w'));
    }
    while (!feof(STDIN)) {
    	$line = trim(fgets(STDIN));
    	$files = glob("{$g['vardb_path']}/captive*.db");
    	$answer = "ERR";
    	foreach ($files as $file) {
    		$result = squid_cp_read_db($file);
    		foreach ($result as $row) {
    //Database contains 5 fields: 1461302438 - 2006 - 192.168.4.100 - fc:aa:14:7d:e6:de - admin - 80b7d55a1bacb9c6
    			if ($row[2] != "" && $row[2] == $line) {
    				$answer = "OK user={$row[4]}";
    				break 2;
    			}
    		}
    	}
    	fwrite(STDOUT, "{$answer}\n");
    }
    /* read captive portal DB into array */
    function squid_cp_read_db($file) {
    	$cpdb = array();
    	$DB = new SQLite3($file);
    	if ($DB) {
    		$response = $DB->query("SELECT * FROM captiveportal");
    		if ($response != FALSE) {
    			while ($row = $response->fetchArray()) {
    				$cpdb[] = $row;
    			}
    		}
    		$DB->close();
    	}
    	return $cpdb;
    }
    
    ?>
    
    

    proxy.pac file looks like this:

    
    function FindProxyForURL(url, host) {
     //proxy  pfSense-IP:3128;
     var wpad = "PROXY wpad.localdomain.local:3128";
     host = host.toLowerCase();
     var hostIP = dnsResolve(host);
     if (hostIP == 0) return wpad;
     if (isPlainHostName(host)) return "DIRECT";
     if (shExpMatch(host, ".local")) return "DIRECT";
     //mi dominio localdomain.local;
     if (shExpMatch(host, ".localdomain.local")) return "DIRECT";
     //redes privadas;
     if (isInNet(dnsResolve(host), "127.0.0.0", "255.0.0.0")) return "DIRECT";
     if (isInNet(dnsResolve(host), "10.0.0.0", "255.0.0.0")) return "DIRECT";
     if (isInNet(dnsResolve(host), "10.0.0.0", "255.255.0.0")) return "DIRECT";
     if (isInNet(dnsResolve(host), "10.0.0.0", "255.255.255.0")) return "DIRECT";
     //PrivateNet;
     if (isInNet(dnsResolve(host), "192.168.20.0", "255.255.255.0")) return "DIRECT";
     //end;
     if (isInNet(dnsResolve(host), "192.168.0.0", "255.255.0.0")) return "DIRECT";
     if (isInNet(dnsResolve(host), "192.168.0.0", "255.255.255.0")) return "DIRECT";
     if (isInNet(dnsResolve(host), "172.16.0.0", "255.240.0.0")) return "DIRECT";
     if (shExpMatch(host, "fe80::*")) return "DIRECT";
     if (shExpMatch(url, "http:*")) return "DIRECT";
     if (shExpMatch(url, "https:*")) return wpad;
     return wpad;
    }
    
    

    Squid is set up with ONLY HTTP Transparent and Cautive Portal Authentication.

    This way, client pcs obtain proxy config from wpad, which forces all traffic BUT HTTP traffic to squid, and the HTTP traffic is routed using the transparent option of the Squid config, this causes the Cautive Portal to kick in and ask for user and password.

    I hope that this would be of use to someone else…



  • Can you send the configs you made to make this setup work? I've been figuring this setup for weeks now.


Log in to reply