Squid - 2.3 fixes: CP authentication + outdated SSL proxy directives



  • First patch:
    The database filenames AND the database content for captive portal has been changed.
    Also fixes odd error with SQLite3 DB module not loading by adding a runtime check for sqlite3.so and if its not loaded, then load it.
    check_ip.php must be changed into the following (changes is that the filename for the database is changed, but also the if directive and user= directive is changed to reflect the correct fields in db, also loader for sqlite3.so is also added):

    
    #!/usr/local/bin/php-cgi -q
    /*
    	check_ip.php
    	part of pfSense (https://www.pfSense.org/)
    	Copyright (C) 2013-2016 Marcello Coutinho
    	Copyright (C) 2016 ESF, LLC
    	All rights reserved.
    
    	Redistribution and use in source and binary forms, with or without
    	modification, are permitted provided that the following conditions are met:
    
    	1\. Redistributions of source code must retain the above copyright notice,
    	   this list of conditions and the following disclaimer.
    
    	2\. Redistributions in binary form must reproduce the above copyright
    	   notice, this list of conditions and the following disclaimer in the
    	   documentation and/or other materials provided with the distribution.
    
    	THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
    	INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
    	AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
    	AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
    	OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
    	SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
    	INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
    	CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
    	ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
    	POSSIBILITY OF SUCH DAMAGE.
    */
    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;
    }
    
    ?>
    
    

    The configuration directives for SSL bumping is changed in 3.5.x
    Following parts need to be changed in squid.inc: (search for the comment to find it):
    UPDATED: (However, the whitelist acl for at_step needs to be made a check so it only applies once)

    
    	// SSL interception acl options part 1
    	if ($settingsconfig['ssl_proxy'] == "on" && ! empty($settingsnac['whitelist'])) {
    		$conf .= "always_direct allow whitelist\n";
    		$conf .= "acl step1 at_step SslBump1\n"; //This shouldn't be defined later on if whitelist is enabled.
    		$conf .= "ssl_bump peek step1\n";
    		$conf .= "ssl_bump splice whitelist\n";
    	}
    
    
    
    		// SSL interception acl options part 2 without authentication
    		if ($settingsconfig['ssl_proxy'] == "on") {
    			$conf .= "always_direct allow all\n";
    			$conf .= "acl step1 at_step SslBump1\n"; //TODO: Skip this if whitelist is enabled
    			$conf .= "ssl_bump peek step1\n";
    			$conf .= "ssl_bump bump all\n";
    		}
    
    
    
    		// SSL interception acl options part 2
    		if ($settingsconfig['ssl_proxy'] == "on") {
    			$conf .= "always_direct allow all\n";
    			$conf .= "acl step1 at_step SslBump1\n"; //TODO: Skip this if whitelist is enabled
    			$conf .= "ssl_bump peek step1\n";
    			$conf .= "ssl_bump bump all\n";
    		}
    
    

    There is all the patches. Have tested all except the whitelist feature and they all work great.



  • Hi!

    I worked exactly the same changes in the filename and the database field numbers by myself last friday, coincidentally.

    Now thanks to your post I could solve the sqlite problem"Class 'SQLite3' not found"

    I'm trying the other paches also.

    Thanks for sharing.



  • Hello again sebastiannielsen.

    Based on your work I written these 2 patches. They seen to be working fine here on 2.3-RELEASE (amd64)

    Patch for /usr/local/bin/check_ip.php (Captive Portal Auth)

    --- /usr/local/bin/check_ip.php.ori	2016-04-24 18:27:46.471375000 +0000
    +++ /usr/local/bin/check_ip.php	2016-04-24 18:27:23.107198000 +0000
    @@ -30,6 +30,9 @@
     */
     require_once("config.inc");
     require_once("globals.inc");
    +if (!extension_loaded('sqlite3')) {
    +dl("sqlite3.so");
    +}
     error_reporting(0);
     global $g;
     // stdin loop
    @@ -41,14 +44,14 @@
     }
     while (!feof(STDIN)) {
     	$line = trim(fgets(STDIN));
    -	$files = glob("{$g['vardb_path']}/captive.*db");
    +	$files = glob("{$g['vardb_path']}/captive*.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[4] != "" && $row[4] == $line) {
    -				$answer = "OK user={$row[8]}";
    +			if ($row[2] != "" && $row[2] == $line) {
    +				$answer = "OK user={$row[4]}";
     				break 2;
     			}
     		}
    
    

    Patch for /usr/local/pkg/squid.inc (SSL)

    
    --- /usr/local/pkg/squid.inc.ori        2016-04-24 15:36:20.633654000 +0000
    +++ /usr/local/pkg/squid.inc    2016-04-24 16:22:46.804683000 +0000
    @@ -1728,7 +1728,9 @@
    	// SSL interception acl options part 1
    	if ($settingsconfig['ssl_proxy'] == "on" && ! empty($settingsnac['whitelist'])) {
    		$conf .= "always_direct allow whitelist\n";
    -		$conf .= "ssl_bump none whitelist\n";
    +		$conf .= "acl step1 at_step SslBump1\n"; //This shouldn't be defined later on if whitelist is enabled.
    +		$conf .= "ssl_bump peek step1\n";
    +		$conf .= "ssl_bump splice whitelist\n";
    	}
    
    	// Package integration
    @@ -1825,7 +1827,9 @@
    		// SSL interception acl options part 2 without authentication
    		if ($settingsconfig['ssl_proxy'] == "on") {
    			$conf .= "always_direct allow all\n";
    -			$conf .= "ssl_bump server-first all\n";
    +			$conf .= "acl step1 at_step SslBump1\n"; //TODO: Skip this if whitelist is enabled
    +			$conf .= "ssl_bump peek step1\n";
    +			$conf .= "ssl_bump bump all\n";
    		}
    		$conf .= "# Setup allowed ACLs\n";
    		$allowed = array('allowed_subnets');
    @@ -1886,7 +1890,9 @@
    		// SSL interception acl options part 2
    		if ($settingsconfig['ssl_proxy'] == "on") {
    			$conf .= "always_direct allow all\n";
    -			$conf .= "ssl_bump server-first all\n";
    +			$conf .= "acl step1 at_step SslBump1\n"; //TODO: Skip this if whitelist is enabled
    +			$conf .= "ssl_bump peek step1\n";
    +			$conf .= "ssl_bump bump all\n";
    		}
    		// Onto the ACLs
    		$password = array('localnet', 'allowed_subnets');
    
    

    Installed the package System_Patches to be aple to aply them.

    For each patch I made an entry to System>Patches like this:

    Description: Name or description
    URL/Commit ID: Leave empty
    Patch Contents: Paste all the content copied from the desirec patch above
    Path Strip Count: 1
    Base Directory: /
    Ignore Whitespace: check
    Auto Apply: do not check

    Please let me know if it works.

    Thanks sebastiannielsen for helping and sharing.



  • however, I did found a solution to the issue about double-defining the acl (which is not allowed):

    // SSL interception acl options part 1
    if ($settingsconfig['ssl_proxy'] == "on" && ! empty($settingsnac['whitelist'])) {
    $conf .= "always_direct allow whitelist\n";

    • $conf .= "ssl_bump none whitelist\n";
    • $conf .= "acl step1a at_step SslBump1\n";
    • $conf .= "ssl_bump peek step1a\n";
    • $conf .= "ssl_bump splice whitelist\n";
      }

    That should solve it.
    (However, that solution is not required further on, as only one of them can be in effect, either the non-authentication variant or authentication variant)

    Also, about SafePorts and SSLPorts, I would suggest updating so the predefined ports are part of the web interface default rather than hard coded (so ports can also be removed from the list, not just added).
    I have tested and its safe to boil down the SafePorts to 80,443 and SSLPorts to 443. (Theres no reason to allow outgoing NNTP SSL traffic)

    If you are using vouchers, I would recommend replacing user=$row[4] with user=$row[3], as [3] contains the user MAC, and this gives better traceability in the logs as a voucher code (which is set as user if you are using vouchers) is pretty much useless for auditing.



  • sebastiannielsen,

    I've been tring to improve some portions of squid regarding SSL bumping.

    I have made the changes and they are at the following patches:

    squid_nac.xml, added field for sites that must not be bumped.

    
    --- /usr/local/pkg/squid_nac.xml	2016-05-12 16:08:50.111288000 -0300
    +++ /usr/local/pkg/squid_nac.xml	2016-05-12 16:09:25.945138000 -0300
    @@ -167,6 +167,20 @@
     			<encoding>base64</encoding>
    
     		 <field>+			<fielddescr>SSL No Bump Sites</fielddescr>
    +			<fieldname>nobumpsites</fieldname>
    +			 <description>+				+				Destination domains that will be bumped by SSL Bumping.
    
    +				**Note: Put each entry on a separate line.**
    +				]]>
    +</description> 
    +			<type>textarea</type>
    +			<cols>50</cols>
    +			<rows>5</rows>
    +			<encoding>base64</encoding>
    +</field> 
    +		 <field><fielddescr>Block User Agents</fielddescr>
     			<fieldname>block_user_agent</fieldname></field> 
    

    squid.inc was edited to recognize the new field, nobumpsites, and to create the ACLs and ssl_bump directives in a suitable way.

    
    --- /usr/local/pkg/squid.inc	2016-05-12 16:37:16.548648000 -0300
    +++ /usr/local/pkg/squid.inc	2016-05-12 16:37:09.472173000 -0300
    @@ -691,6 +691,11 @@
     		$config['installedpackages']['squidnac']['config'][0]['blacklist'] = $settingsnac['blacklist'];
     	}
    
    +	if (!empty($settingsnac['nobumpsites']) && strstr($settingsnac['nobumpsites'], ",")) {
    +		$settingsnac['nobumpsites'] = base64_encode(implode("\n", explode(",", $settingsnac['nobumpsites'])));
    +		$config['installedpackages']['squidnac']['config'][0]['nobumpsites'] = $settingsnac['nobumpsites'];
    +	}
    +
     	if (!empty($settingsnac['block_user_agent']) && strstr($settingsnac['block_user_agent'], ",")) {
     		$settingsnac['block_user_agent'] = base64_encode(implode("\n", explode(",", $settingsnac['block_user_agent'])));
     		$config['installedpackages']['squidnac']['config'][0]['block_user_agent'] = $settingsnac['block_user_agent'];
    @@ -1550,6 +1555,7 @@
     		'banned_hosts' => 'src',
     		'whitelist' => 'dstdom_regex -i',
     		'blacklist' => 'dstdom_regex -i',
    +		'nobumpsites' => 'ssl::server_name',
     		'block_user_agent' => 'browser -i',
     		'block_reply_mime_type' => 'rep_mime_type -i',
     	);
    @@ -1725,12 +1731,6 @@
    
     	$conf = '';
    
    -	// SSL interception acl options part 1
    -	if ($settingsconfig['ssl_proxy'] == "on" && ! empty($settingsnac['whitelist'])) {
    -		$conf .= "always_direct allow whitelist\n";
    -		$conf .= "ssl_bump none whitelist\n";
    -	}
    -
     	// Package integration
     	if (!empty($settingsconfig['custom_options'])) {
     		$co_preg[0] = '/;/';
    @@ -1822,10 +1822,21 @@
     		}
     	}
     	if ($auth_method == 'none') {
    -		// SSL interception acl options part 2 without authentication
    +		// SSL interception acl options without authentication
     		if ($settingsconfig['ssl_proxy'] == "on") {
    +			$conf .= "# SSL bumping settings\n";
    +			$conf .= "acl step1 at_step SslBump1\n";
    +			$conf .= "acl step2 at_step SslBump2\n";
    +			$conf .= "acl step3 at_step SslBump3\n";
    +			$conf .= "ssl_bump peek step1\n";
    +			if (!empty($settingsnac['nobumpsites'])) {
    +				$conf .= "ssl_bump peek step2 nobumpsites\n";
    +				$conf .= "ssl_bump splice nobumpsites all\n";
    +				$conf .= "ssl_bump bump !nobumpsites\n";
    +			} else {
    +				$conf .= "ssl_bump bump all\n";
    +			}
     			$conf .= "always_direct allow all\n";
    -			$conf .= "ssl_bump server-first all\n";
     		}
     		$conf .= "# Setup allowed ACLs\n";
     		$allowed = array('allowed_subnets');
    @@ -1883,10 +1894,21 @@
     		// Custom User Options after authentication definition
     		$conf .= "# Custom options after auth\n" . sq_text_area_decode($settingsconfig['custom_options2_squid3']) . "\n\n";
    
    -		// SSL interception acl options part 2
    +		// SSL interception acl options with authentication
     		if ($settingsconfig['ssl_proxy'] == "on") {
    +			$conf .= "# SSL bumping settings\n";
    +			$conf .= "acl step1 at_step SslBump1\n";
    +			$conf .= "acl step2 at_step SslBump2\n";
    +			$conf .= "acl step3 at_step SslBump3\n";
    +			$conf .= "ssl_bump peek step1\n";
    +			if (!empty($settingsnac['nobumpsites'])) {
    +				$conf .= "ssl_bump peek step2 nobumpsites\n";
    +				$conf .= "ssl_bump splice nobumpsites all\n";
    +				$conf .= "ssl_bump bump !nobumpsites\n";
    +			} else {
    +				$conf .= "ssl_bump bump all\n";
    +			}
     			$conf .= "always_direct allow all\n";
    -			$conf .= "ssl_bump server-first all\n";
     		}
     		// Onto the ACLs
     		$password = array('localnet', 'allowed_subnets');
    
    

    The resulting squid.conf looks like the following (only related portions)

    
    acl nobumpsites ssl::server_name /var/squid/acl/nobumpsites.acl
    
    acl step1 at_step SslBump1
    acl step2 at_step SslBump2
    acl step3 at_step SslBump3
    ssl_bump peek step1
    ssl_bump peek step2 nobumpsites
    ssl_bump splice nobumpsites all
    ssl_bump bump !nobumpsites
    always_direct allow all
    
    

    The file "/var/squid/acl/nobumpsites.acl" has the domain names of servers that I want not no bump, one per line like this:

    .destinationsite.org
    .anotherwebsite.com
    .something.com

    It looks ok, but something strange happens.
    The ACL looks like it's empty, it simply does not work. But if instead of using a text file I put the same domain names directly on squid.conf, by editing it manually like this:

    "acl nobumpsites ssl::server_name .destinationsite.org .anotherwebsite.com .something.com"

    And issuing "squid -k reconfigure". It just works.

    What would be the difference between using the text file or not?
    Weird.
    The squid "how to" and some examples I found use the text file with no problem.

    I apreciate your attention and look forward for any opinion or idea.

    regards.



  • The script for cp authentication integration is updated on latest package version for pfSense 2.3.x.