ClearOS’s content filter is based on Dansguardian. Dansguardian allows for custom configurations thereby, allowing us to easily customize the page displayed when blocked. Today, we are going to add a login/override/bypass to our content filter’s block page. You can choose to change the look of the page if you wish but, ours will look like this when we are done:
As the information to do this was a little bit hard to find, I am documenting my adventure here. However, the original article I followed can be found at: http://honestpchelp.com/2011/clearos-dansguardian-accessdenied-php-bypass-script/
I assume you have already set up content filtering for your network and therefore, will not cover it here.
You first need to login to your server as root (or else use ‘sudo‘ in front of your commands), whether by SSH or by physically being at it (hit ‘alt+F2‘ if you are at it). Once logged in we need to locate the file ‘dansguardian.conf‘. For me, this file was located at ‘/etc/dansguardian-av/‘. You can use the following to find it if it’s happens to be in a different location:
#find / -name dansguardian.conf
Now that we know where the file is, we can start editing:
#vi /etc/dansguardian-av/dansguardian.conf
Three settings that we need to change/verify are as follow:
- Reporting level needs set to either ‘1’ or ‘2’
- Point Dansgaurdian to our soon-to-be created access denied page
- Turn on the non-standard delimiter
reportinglevel = 1 accessdeniedaddress = http://ip-address:82/public/accessdenied.php nonstandarddelimiter = on
Make sure to change ‘ip-address‘ to your ClearOS’s IP address!
Now it’s time to edit ‘dansguardianf1.conf‘ which is located in the same directory:
#vi /etc/dansguardian-av/dansguardianf1.conf
There a few changes we’ll need to make in this file:
- Change ‘bypass‘ to ‘-1‘ which configures Dansguardian to use our custom page
- Generate a MD5 sum key that will be unique to our page (You can generate your own at: http://www.miraclesalad.com/webtools/md5.php Just type anything you feel into the box.)
- Change the reporting level to match that of ‘dansguardian.conf‘
bypass = -1 bypasskey = '3ff4480e30247f9a1d8bad4efe7e1055' reportinglevel = 1
Now on to the glue of this project: our ‘accessdenied.php‘ page. We need to find where our transparent web-proxy serves up it’s pages from:
#find / -name public
Mine is located at ‘/var/webconfig/htdocs/public‘. To create our ‘accessdenied.php‘ page we’ll use:
#vi /var/webconfig/htdocs/public/accessdenied.php
After this, paste in the following code (this is my customized page that has been modified from the original article):
<?php //======================================================================= // break up the query string into useable pieces //======================================================================= $url = explode("::",$_SERVER["QUERY_STRING"]); // Save the url string, we'll need it later $url2 = $_SERVER["QUERY_STRING"]; foreach ($url as $temp){ $pieces = explode("==",$temp); $value[$pieces[0]] = urldecode($pieces[1]); } $myurl=$value['DENIEDURL']; $magic = "3ff4480e30247f9a1d8bad4efe7e1055"; $clientip=$value['IP']; // Obviously this is completely impossible if you use the // random passphrase $bypass_time = 10; //Time in minutes to bypass the content filter $unixtimekey = time() + ($bypass_time * 60); $time=time(); // If these lines are missing, some web browsers won't work // properly if (!eregi("https?://.+/.*", $myurl)){ $myurl = $myurl . "/"; } //This is the most important part. //The MD5 Hash MUST be hex encoded and uppercase with no //padding, salt, etc other than what is shown here //This can take some experimenting in Perl //DO NOT just use the time() function at this point $hash = strtoupper(md5($myurl . $magic . $clientip . $unixtimekey)); $hash .= $unixtimekey; // If these lines are missing, some URL's won't work properly if (eregi("\?", $url2)){ $bypass = $value['DENIEDURL'] . "&GBYPASS=" . $hash; }else{ $bypass = $value['DENIEDURL'] . "?GBYPASS=" . $hash; } ?> <html> <head> <title>Access Denied</title> <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"> <style> body,td,p { font: x-small Verdana,Arial,Helevetica; } table.main { border: 2px solid #cccccc; width: 600px; } td.top_denied { font: x-large Georgia; font-weight: bold; color: #ffffff; padding: 10; text-align: center; background-color: #CC3333; } td.top_granted { font: x-large Georgia; font-weight: bold; color: #ffffff; padding: 10; text-align: center; background-color: #339933; } td.body { background-color: #ffffff; padding: 10; } td.bottom { background-color: #eeeeee; height: 25px; text-align: center; } p.url_denied { text-align: center; font-size: medium; color: #ff0000; border: 1px dashed #ff0000; background-color: #FFF0F0; padding: 3; } p.url_granted { text-align: center; font-size: medium; color: #339933; border: 1px dashed #339933; background-color: #EFFAEF; padding: 3; } p.reason { border: 1px dashed #ff0000; background-color: #FFF0F0; padding: 3; } input.text { width: 100%; border: 1px inset; font-size: xx-small; color: #666666; font-weight: normal; padding-left:2; } input.button { width: 150px; } td.overide { border: 1px dashed #339933; background-color: #EFFAEF; } </style> </head> <body bgcolor="#f4f4f4"> <script> // functions for navigation function goBack(){ history.back(); } </script> <?php if (!$value['ACTION']): ?> <table border="0" align="center" cellpadding="0" cellspacing="0" class="main"> <tr><td class='top_denied'>Access Denied</td></tr> <tr> <td class='body'> <p class='url_denied'><?php print $value['DENIEDURL']; ?></p> <p>Access has been denied for the following reason:</p> <p class='reason'><?php print $value['REASON']; ?></p> <br> <table width="576" border="0" cellpadding="3" cellspacing="0"> <tr valign="top"> <td width="250"><br><p align="justify">You are seeing this page because you attempted to access content that appears to contain inappropriate material. Please check the URL and try again or enter your username and password to access this page for <?php echo $bypass_time." "; if($bypass_time==1){echo "minute";}else{echo "minutes";}; ?>.</p> <p align="justify"></p> <br><br> <p align="center"><strong>Cookies Must Be Enabled</strong><br> </td> <td width="230" class='overide'> <p align="center"><strong>Enable Access</strong></p> <form action="http://ip-address:82/public/accessdenied.php?ACTION==verify::<?php print $url2; ?>" method="post"> <div align="center">Please enter your username and password to continue:<br> <br> <table> <tr> <td>Username:</td><td><input type="text" name="username" size="20"></td> </tr> <tr> <td>Password:</td><td><input type="password" name="passwd" size="20"></td> </tr> </table> <br> <input type="submit" name="Submit" value="Override" class='button'> <br> <br> <input type="button" name="Button" value="Go Back" class='button' onClick="goBack()"> </div></form></td> </tr> </table> </td> </tr> <tr><td class='bottom'><strong>C-Smart Solutions</strong></td></tr> </table> <?php endif; ?> <?php if ($value['ACTION']): ########################################### # Check credentials ########################################### $username=$_POST['username']; $passwd=$_POST['passwd']; $file=file("/var/webconfig/htdocs/access.txt"); $found=false; foreach ($file as $line){ if(!$line = trim($line)) continue; //break up each line on white space $f_temp = preg_split('/\s+/', $line); if ($f_temp[0] == $username){ if ($f_temp[1] == $passwd){ $found=true; ?> <table border="0" align="center" cellpadding="0" cellspacing="0" class="main"> <script> // functions for navigation function visitSite(){ document.location.href = "<?php print $bypass; ?>"; } </script> <tr><td class='top_granted'>Access Granted</td></tr> <tr> <td class='body'> <p>Access to the following page has been granted for <?php echo $bypass_time." "; if($bypass_time==1){echo "minute";}else{echo "minutes";}; ?>.</p> <p class='url_granted'><?php print $value['DENIEDURL']; ?></p> <p class='reason'><?php print $value['REASON']; ?></p> <p><input type="button" name="Button" value="Continue" class='button' onclick="visitSite()"></p> </td> </tr> <tr><td class='bottom'><strong>C-Smart Solutions</strong></td></tr> </table> <? } } } if ($found == false){ $url3 = implode("::", $url); $url3 = str_replace("ACTION==verify","",$url3); print "<script>document.location.href='accessdenied.php?$url3'</script>"; //print "<script>document.location.href='accessdenied.php'</script>"; } ?> <?php endif; ?> </body> </html>
Some key settings to take note of are:
- $magic = “3ff4480e30247f9a1d8bad4efe7e1055”;
- $bypass_time = 10;
- <form action=”http://ip-address:82/public/accessdenied.php?ACTION==verify::<?php print $url2; ?>” method=”post”>
- $file=file(“/var/webconfig/htdocs/access.txt”);
‘$magic‘ should match the MD5 sum key you generated earlier and ‘$bypass_time‘ is the time in minutes to unblock a site that has been granted access. Also, be sure to replace ‘ip-address‘ within the form’s action string with your ClearOS’s IP address and change ‘$file‘ to specify your authentication file’s location (we’ll create it next).
The last step we need to do before we are finished with our project is to create our authentication file, ‘access.txt‘:
#vi /var/webconfig/htdocs/access.txt
The authentication file should contain a username and password separated by the use of a tab or space:
username password
You may make multiple username/password combinations by entering each combination on it’s own line:
username password username1 password1 username2 password2
Now that we have finished we need to restart our ClearOS machine and test.
Congratulations! We have successfully modified our content filter’s block page to include our custom page and override feature!
Phew! You can pat yourself on the back for that one!
UPDATE:
ClearOS 6 requires a few minor changes for this to work:
Instead of placing the files ‘accessdenied.php‘ and ‘access.txt‘ in ‘/var/webconfig/htdocs/‘, you need to place them in ‘/usr/clearos/apps/content_filter/htdocs/‘.
In Dansgaurdian’s configuration file, you need to change the location of the ‘accessdeniedaddress‘ variable accordingly:
accessdeniedaddress = http://ip-address:82/approot/content_filter/htdocs/accessdenied.php
You’ll also need to change the relevant PHP code so that it matches:
<form action="http://ip-address:82/approot/content_filter/htdocs/accessdenied.php?ACTION==verify::<?php print $url2; ?>" method="post"> $file=file("/usr/clearos/apps/content_filter/htdocs/access.txt");
Below you can find an updated version of the ‘accessdenied.php‘ script:
<?php $url = explode('::',$_SERVER['QUERY_STRING']); $url2 = $_SERVER['QUERY_STRING']; foreach ($url as $temp){ $pieces = explode('==',$temp); $value[$pieces[0]] = urldecode($pieces[1]); } $myurl=$value['DENIEDURL']; $magic = '3ff4480e30247f9a1d8bad4efe7e1055'; $clientip=$value['IP']; $bypass_time = 10; $unixtimekey = time() + ($bypass_time * 60); $time=time(); if (!eregi('https?://.+/.*', $myurl)){ $myurl = $myurl . '/'; } $hash = strtoupper(md5($myurl . $magic . $clientip . $unixtimekey)); $hash .= $unixtimekey; if (eregi('\?', $url2)){ $bypass = $value['DENIEDURL'] . '&GBYPASS=' . $hash; }else{ $bypass = $value['DENIEDURL'] . '?GBYPASS=' . $hash; } ?> <!DOCTYPE HTML PUBLIC '-//W3C//DTD HTML 4.01 Transitional//EN'> <html dir='LTR'> <!-- Head --> <head> <!-- Basic Head Information --> <title>the.defender - Content Filter</title> <meta http-equiv='Content-Type' content='text/html; charset=UTF-8'> <!-- Theme IE Workarounds --> <meta http-equiv='X-UA-Compatible' content='IE=9'> <!-- Theme Favicon --> <link href='/themes/default/images/favicon-green.ico' rel='shortcut icon' > <!-- Theme Style Sheets --> <link type='text/css' href='/themes/default/css/jquery-ui-1.8.5.custom.css' rel='stylesheet'> <link type='text/css' href='/themes/default/css/summary-table.css' rel='stylesheet'> <link type='text/css' href='/themes/default/css/theme.css' rel='stylesheet'> </head> <!-- Body --> <body> <script> function goBack(){ history.back(); } </script> <!-- Page Container --> <div id='theme-page-console-container'> <div class='theme-splash-logo' style='margin-top: 30px;'></div> <div id='theme-content-splash-container'> <div class='theme-form-container'> <?php if (!$value['ACTION']): ?> <form method='post' action='http://ip-address:82/approot/content_filter/htdocs/accessdenied.php?ACTION==verify::<?php print $url2; ?>'> <table cellspacing='0' cellpadding='0' border='0' class='theme-form-wrapper' style='table-layout: fixed; word-wrap: break-word;'> <tbody><tr class='theme-form-header'> <td><span class='theme-form-header-heading'>Content Filter</span></td> <td align='right'><span class='theme-form-header-status'> </span></td> </tr> <tr class='theme-fieldview' id='web_address_field'> <td class='theme-field-left'> <label id='web_address_label' for='web_address'>Web Address</label> </td> <td class='theme-field-right'> <span id='web_address_text' style='color: red;'><strong><?php print $value['DENIEDURL']; ?></strong></span> </td> </tr> <tr class='theme-fieldview' id='description_field'> <td class='theme-field-left'> <label id='description_label' for='description'>Description</label> </td> <td class='theme-field-right'> <span id='description_text'><?php print $value['REASON']; ?></span> </td> </tr> </table> <p> </p> <table cellspacing='0' cellpadding='0' border='0' class='theme-form-wrapper'> <tbody><tr class='theme-form-header'> <td><span class='theme-form-header-heading'>Override</span></td> <td align='right'><span class='theme-form-header-status'> </span></td> </tr> <tr> <td colspan='2'> You are seeing this page because you attempted to access content that appears to contain inappropriate material. Please check the URL and try again or enter your username and password to access this page for up to <?php echo $bypass_time.' '; if($bypass_time==1){echo 'minute';}else{echo 'minutes';}; ?>. <strong>Cookies must be enabled</strong> for this feature to work. </td> </tr> <tr class='theme-fieldview'> <td class='theme-field-left'> Username: </td> <td class='theme-field-right'> <input type='text' name='username' size='20'> </td> </tr> <tr class='theme-fieldview'> <td class='theme-field-left'> Password: </td> <td class='theme-field-right'> <input type='password' name='passwd' size='20'> </td> <tr class='theme-fieldview'> <?php if ($value['CREDENTIALS']=='invalid'): ?> <td colspan='2' style='text-align: center; color: red;'> Username or Password is invalid </td> <?php endif; ?> <tr> <td colspan='2' style='text-align: right;'> <div class='theme-button-set ui-buttonset'> <input type='button' onclick='goBack()' class='theme-button-set-first theme-form-submit-add theme-form-important ui-button ui-widget ui-corner-left' value='Go Back' name='Button' style='margin-left: 5px;'> <input type='submit' class='theme-button-set-last theme-form-submit-add theme-form-important ui-button ui-widget ui-corner-right' value='Override' name='Submit'> </div> </td> </tr> </tbody> </table> </form> <script> document.getElementsByName('username')[0].select(); </script> <?php endif; ?> <?php if ($value['ACTION']): $username=$_POST['username']; $passwd=$_POST['passwd']; $file=file('/usr/clearos/apps/content_filter/htdocs/access.txt'); $found=false; foreach ($file as $line){ if(!$line = trim($line)) continue; $f_temp = preg_split('/\s+/', $line); if ($f_temp[0] == $username){ if ($f_temp[1] == $passwd){ $found=true; ?> <script> function visitSite(){ document.location.href = "<?php print $bypass; ?>"; } </script> <table border='0' cellpadding='0' cellspacing='0' class='theme-form-wrapper' style='table-layout: fixed; word-wrap: break-word;'> <tbody> <tr class='theme-form-header'> <td><span class='theme-form-header-heading'>Access Granted</span></td> <td align='right'><span class='theme-form-header-status' > </span></td> </tr> <tr class='theme-fieldview'> <td colspan='2'> <p style='padding: 10px'> Access to the following page has been granted for <strong><?php echo $bypass_time." "; if($bypass_time==1){echo "minute";}else{echo "minutes";}; ?></strong>. </p> </td> </tr> <tr class='theme-fieldview'> <td colspan='2'> <p style='background-color: #EFFAEF; border: 1px dashed #339933; color: #339933; font-size: 12px; padding: 10px; text-align: center;'> <strong><?php print $value['DENIEDURL']; ?></strong> </p> </td> </tr> <tr class='theme-fieldview'> <td style='text-align: right; padding: 10px 0 0' colspan='2'> <div class='theme-button-set ui-buttonset'> <input type='button' onclick='goBack()' class='theme-button-set-first theme-form-submit-add theme-form-important ui-button ui-widget ui-corner-left' value='Go Back' name='Button' style='margin-left: 5px;'> <input type='button' name='Button' value='Continue' onclick='visitSite()' class='theme-button-set-last theme-form-submit-add theme-form-important ui-button ui-widget ui-corner-right'> </div> </td> </tr> </tbody> </table> <? } } } if ($found == false){ $url3 = implode('::', $url); $url3 = str_replace('ACTION==verify','',$url3); $url3 = str_replace('CREDENTIALS==invalid','',$url3); print "<script>document.location.href='accessdenied.php?$url3::CREDENTIALS==invalid'</script>"; //print "<script>document.location.href='accessdenied.php'</script>"; } ?> <?php endif; ?> <p> </p> <p style='text-align: center;'><strong>C-Smart Solutions</strong></p> </div> </div> </div> </body> </html>
The page should look like the rest of your ClearOS 6 pages since I simply copied the HTML code from the default page that is displayed by the content filter.
Comments are closed.