ConfigServer Firewall has been great at keeping unwanted users at bay on my web servers, but it also causes plenty of problems – notably when the SMTP authentication fails multiple times. This is usually caused by an email account trying to send an email and repeatedly using bad credentials to login. After a short period of time, CSF or cPHulk kicks in and blocks all communication with their website.
Managing this is a pain as there is no way (as far as I can tell) to allow clients to white list themselves when this happens. So, I’ve put up a page on a different server that handles requests for white listing.
There are two components here: one for the self-contained request page and a bash script to handle the white listing quickly, away from cPanel.
<?php
/*****************************************************\
* *
* REMOTE SERVER CLIENT BLOCK CHECK PAGE *
* *
* Coded by Noah Hearle, Design Extreme *
* http://designextreme.com *
* *
* Created: 2015/05/06 *
* Modified: 2015/05/19 *
* *
* Post your comments at: *
* https://blog.nahoo.co.uk/server-white-listing/ *
* *
\*****************************************************/
session_start();
chdir(__DIR__);
define('EMAIL_SUBJECT', 'IP Whitelist Request');
define('RECIPIENT_NAME', 'Your Name');
define('RECIPIENT_EMAIL', 'rs_wpss_encode_strip@yourdomain.com');
define('ADMIN_CODE', 'SomeRandomCode23234');
define('DATA_FILE', '../ip_log.txt');
define('REMOTE_URL', 'http://yourdomain.com/simple/test/page/');
define('REMOTE_IMAGE_URL', 'http://yourdomain.com/test/image.gif');
define('WHITE_LIST_SCRIPT_PATH', '/path/to/script/whitelist_ip.sh');
define('HISTORY_LENGTH', 10);
$ip = getip();
$ignore = (isset($_REQUEST['ignore']) && $_REQUEST['ignore']);
$name = (isset($_POST['name']) && $_POST['name'] != NULL) ? preg_replace('/,/','',$_POST['name']) : NULL;
$email = (isset($_POST['email']) && $_POST['email'] != NULL) ? preg_replace('/,/','',$_POST['email']) : NULL;
$status = (isset($_POST['status']) && $_POST['status'] != NULL) ? preg_replace('/,/','',$_POST['status']) : NULL;
$admin = (isset($_GET[ADMIN_CODE])) ? (bool)$_GET[ADMIN_CODE] : ((isset($_SESSION['ip_admin'])) ? $_SESSION['ip_admin'] : FALSE);
$email_sent = (isset($_SESSION['ip_email_sent']) && $_SESSION['ip_email_sent'] != NULL) ? $_SESSION['ip_email_sent'] : FALSE;
if (!$admin && ((!isset($_SESSION['ip']) || isset($_SESSION['ip']) && $_SESSION['ip'] != $ip) || ($name != NULL && $email != NULL)))
{
if (!$ignore)
{
$fp = fopen(DATA_FILE, 'a');
fputs($fp, date("Y-m-d H:i").','.$ip.(($name != NULL && $email != NULL) ? ','.$name.','.$email.','.$status : '')."\n");
fclose($fp);
}
if (!$email_sent && preg_match('/^\w+([-+.]\w+)*@(\w+([-.]\w+)*\.\w+([-.]\w+)*)$/i',$email) && checkdnsrr(preg_replace('/[^@]*@([^@]+)$/','$1',$email), 'MX'))
{
if ($ignore)
{
$email_sent = time();
}
else
{
$data = array(
'sender_email' => $email,
'sender_name' => $name,
'recipient_email' => RECIPIENT_EMAIL,
'recipient_name' => RECIPIENT_NAME,
'subject' => EMAIL_SUBJECT,
'text' => 'New IP Whitelist request from '.$name.' <'.$email.'> on '.date("r").PHP_EOL.PHP_EOL.'Status: '.$status.PHP_EOL.PHP_EOL.'IP: '.$ip.PHP_EOL.PHP_EOL.'sh '.WHITE_LIST_SCRIPT_PATH.' '.$ip
);
if (email($data))
{
$email_sent = time();
}
}
}
}
$_SESSION['ip'] = $ip;
$_SESSION['ip_admin'] = $admin;
$_SESSION['ip_email_sent'] = $email_sent;
if ($admin)
{
$ip_tail = tail_ip_log(DATA_FILE, HISTORY_LENGTH, FALSE);
}
function getip()
{
if( isset( $_SERVER["HTTP_X_FORWARDED_FOR"] ) )
{
$realip = $_SERVER["HTTP_X_FORWARDED_FOR"];
}
elseif( isset( $_SERVER["HTTP_CLIENT_IP"] ) )
{
$realip = $_SERVER["HTTP_CLIENT_IP"];
}
else
{
$realip = $_SERVER["REMOTE_ADDR"];
}
return $realip;
}
function tail_ip_log($file, $count=10, $repeat=TRUE)
{
$ret = array();
$data = file($file);
if (empty($data))
{
return $ret;
}
for ($i = (count($data)-1); $i>0; $i--)
{
if (!preg_match('/^([^,]+),([^,]+)(?:,([^,]+),([^,]+)(?:,([^,]+))?)?$/i', $data[$i], $m))
{
continue;
}
$k = (!$repeat) ? str_replace('.', '_', $m[2]) : $i;
if (!$repeat && array_key_exists($k,$ret))
{
continue;
}
$ret[$k] = array($m[1],$m[2],$m[3],$m[4],$m[5]);
$count--;
if ($count == 0)
{
break;
}
}
return $ret;
}
function email ($data)
{
$sender_email = (string)$data['sender_email'];
$sender_name = (string)$data['sender_name'];
$return_email = (isset($data['return_email'])) ? (string)$data['return_email'] : (string)$data['sender_email'];
$recipient_email = (string)$data['recipient_email'];
$recipient_name = (string)$data['recipient_name'];
$subject = (isset($data['subject']) && $data['subject'] != NULL) ? (string)$data['subject'] : 'No Subject';
$text = (isset($data['text'])) ? $data['text'] : NULL;
$html = (isset($data['html'])) ? $data['html'] : nl2br(htmlspecialchars($text));
$sender = $sender_name.' <'.$sender_email.'>';
$recipient = $recipient_name.' <'.$recipient_email.'>';
$newline = (preg_match('/win/i',strtolower(php_uname('s')))) ? "\r\n" : "\n";
$headers = 'From: '.$sender.$newline;
$headers .= 'Reply-To: '.$sender_email.$newline;
$headers .= 'X-Mailer: PHP/'.phpversion().$newline;
return mail($recipient, $subject, $text, $headers, '-f '.$return_email);
}
?><!doctype html>
<html>
<head>
<meta charset="utf-8">
<!----------------------------------------------------\
| |
| REMOTE SERVER CLIENT BLOCK CHECK PAGE |
| |
| Coded by Noah Hearle, Design Extreme |
| http://designextreme.com |
| |
| Created: 2015/05/06 |
| Modified: 2015/05/19 |
| |
| Post your comments at: |
| https://blog.nahoo.co.uk/server-white-listing/ |
| |
\----------------------------------------------------->
<title>Your IP Address is: <?= htmlspecialchars($ip); ?></title>
<link href='http://fonts.googleapis.com/css?family=Slabo+27px&family=Roboto' rel='stylesheet' type='text/css'>
<style type="text/css">
<!--
body,td,th,input,button { color:#D6D1A3; font-family:Roboto,Calibri,'Trebuchet MS',Arial; font-size:15px; }
html { height:100%; }
body { background:#000e00; background:-moz-linear-gradient(top,#000e00 0%,#404a40 100%); background:-webkit-gradient(linear,left top,left bottom,color-stop(0%,#000e00),color-stop(100%,#404a40)); background:-webkit-linear-gradient(top,#000e00 0%,#404a40 100%); background:-o-linear-gradient(top,#000e00 0%,#404a40 100%); background:-ms-linear-gradient(top,#000e00 0%,#404a40 100%); background:rgba(0,0,0,0) linear-gradient(to bottom,#000e00 0%,#404a40 100%) repeat scroll 0 0; filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#000e00',endColorstr='#404a40',GradientType=0); }
h1 { font-family:'Slabo 27px','Courier New',Courier,monospace; font-size:60px; font-weight:700; text-shadow:0 4px 1px rgba(0,0,0,0.8); margin:40px 0; }
h2 { margin:20px 0; font-size:30px; }
h3 { margin:20px 0; font-size:25px; }
p { line-height:140%; }
#main { background-color:rgba(100,255,100,0.08); border:2px solid #6a856a; border-radius:5px; box-shadow:14px 16px 10px rgba(0,0,0,0.09),-9px -5px 32px rgba(133,233,155,0.19) inset; margin:120px auto 0; max-width:1300px; min-width:360px; padding:30px 20px; text-align:center; width:85%; }
table { width:320px; margin:20px auto; }
table th,table td { text-align:left; padding:6px; }
#admin { width:auto; }
#admin th,#admin td { text-align:left; padding:6px; border-bottom:1px dashed #D6D1A3; }
input { background-color:#eeecc4; border:1px solid #d6d1a3; color:#555f2e; padding:4px 2%; width:96%; }
button { background-color:rgba(100,255,100,0.08); border:2px solid #6a856a; border-radius:3px; box-shadow:14px 16px 10px rgba(0,0,0,0.09),-9px -5px 32px rgba(133,233,155,0.19) inset; color:#eeecc4; font-weight:700; padding:4px 0; width:100%; }
#circle { font-family:Helvetica,Arial,sans-serif; color:#433F23; border:4px solid #d6d1a3; border-radius:104px; font-size:200px; font-weight:700; height:200px; line-height:104%; margin:0 auto; padding:0; text-align:center; width:200px; transition:all 2s ease-in-out; }
#circle_frame { height:212px; border:0 none; overflow:hidden; width:212px; text-align:center; }
#circle.allowed { border:4px solid #A8BF27; color:#A8BF27; }
#circle.blocked { border:4px solid #D56567; color:#D56567; }
#circle.unknown { color:#d6d1a3; }
-->
</style>
<script>
<!--
var count = 0;
function remote_server_connection(count, status, img) {
if (typeof count == 'undefined') {
count = 0;
}
if (typeof status == 'undefined') {
status = 'Unknown';
}
if (typeof img == 'undefined') {
img = null;
}
var http = new XMLHttpRequest(),
url = '<?= REMOTE_URL; ?>',
image_url = '<?= REMOTE_IMAGE_URL; ?>';
if (count == 0) {
img = new Image();
img.onerror = function () {
this.src = null;
return 'Blocked';
}
img.src = image_url;
count++;
}
else if (count == 1 && img != null) {
count++;
if (img.height > 0) {
status = 'Allowed';
}
}
else {
count++;
if (http.open('HEAD', url, false)) {
http.send();
status = (http.status == 200) ? 'Allowed' : 'Blocked';
}
}
if (!document.getElementById('circle')) {
document.getElementById('circle_container').innerHTML = '<div id="circle"></div>';
}
if (status == null) {
status = 'Unknown';
}
if (count < 2 && status == 'Unknown') {
setTimeout(function() { status = remote_server_connection(count, status, img)}, 400);
}
else {
document.getElementById('server_status').value = status;
document.getElementById('circle').className = status.toLowerCase();
document.getElementById('circle').innerHTML = ((status == 'Allowed') ? '☑' : ((status == 'Blocked') ? '☒' : '?'));
if (status == 'Unknown') {
document.getElementById('circle_container').innerHTML = '<iframe src="<?= REMOTE_URL; ?>" id="circle_frame"></iframe>';
}
}
if (document.getElementById('current_status_message')) {
switch (status) {
case 'Allowed':
document.getElementById('current_status_message').innerHTML = 'Your IP is not blacklisted and you should have no problems connecting to your website and emails.';
document.getElementById('submission_form').style.opacity = 0.66;
break;
case 'Blocked':
document.getElementById('current_status_message').innerHTML = 'It appears that you’re blocked from accessing your website and emails and your IP may be blacklisted. Please send us your IP address here.';
break;
default:
break;
}
}
return status;
}
window.onload = function() {
if (document.getElementById('server_status')) {
remote_server_connection(count);
}
else {
setInterval(function() { window.location.reload(); }, 120000);
}
}
-->
</script>
</head>
<body>
<div id="main">
<form action="./" method="post" id="form">
<h3>Your IP Address is: </h3>
<h1><?= htmlspecialchars($ip); ?></h1>
<?php if ($admin)
{
?> <table id="admin">
<tr>
<th style="text-align: right;">Date</th>
<th style="text-align: right;">IP</th>
<th>Name</th>
<th>Email</th>
<th>Status</th>
</tr>
<?php
$i = 0;
foreach ($ip_tail as $a)
{
if ($a[0] == NULL)
{
continue;
}
echo ' <tr'.(($i > 0) ? ' style="opacity: '.(1-$i/HISTORY_LENGTH) : '').';">
<td style="text-align: right;">'.htmlspecialchars($a[0]).'</td>
<td style="text-align: right;">'.htmlspecialchars($a[1]).'</td>
<td>'.((isset($a[2]) && $a[2] != NULL) ? htmlspecialchars($a[2]) : '—').'</td>
<td>'.((isset($a[3]) && $a[3] != NULL) ? htmlspecialchars($a[3]) : '—').'</td>
<td>'.((isset($a[4]) && $a[4] != NULL) ? htmlspecialchars($a[4]) : '—').'</td>
</tr>
';
$i++;
}
?> </table>
<?php
}
else
{
if (($name != NULL && $email != NULL))
{
if (!is_bool($email_sent) && $email_sent == time())
{
?>
<p>Your details have been logged and an email notification has been sent.</p>
<?php
}
else
{
?>
<p>Your details have been logged.</p>
<?php
}
}
else
{
?>
<p>Your IP address is a way to identify your internet connection. </p>
<p id="current_status_message">If you’re having problems accessing your website and emails, your IP may be blacklisted. So you may wish to send us your IP address here.</p>
<?php
}
?>
<table id="submission_form">
<tr>
<td><input type="text" name="name" id="name" value="<?= htmlspecialchars($name); ?>" placeholder="Your name"></td>
</tr>
<tr>
<td><input type="email" name="email" id="email" value="<?= htmlspecialchars($email); ?>" placeholder="Your email"></td>
</tr>
<tr>
<th><button type="submit" name="send" value="1" id="send">Send Details</button><input type="hidden" id="server_status" name="status" value=""><input type="hidden" id="ignore" name="ignore" value="<?= $ignore; ?>"></th>
</tr>
</table>
<?php
}
?>
</form>
<?php
if (!$admin)
{
?>
<div id="circle_container"></div>
<?php
}
?></div>
</body>
</html>You will need to edit this file and create a log file, preferably above web root, to handle the IP requests. Storing this in a table is an alternative.
Place this page on a different server to your own. Access the logs by adding adding your random code = 1 to the URL, e.g. ?soMeRanD0mCod3234=1. You can contact me if you’re interested in a free sub domain account.
This is the bash script that white lists the IP if there is a genuine request:
#!/bin/sh ####################################################### # # # SIMPLE SERVER WHITE LISTING # # # # Coded by Noah Hearle, Design Extreme # # http://designextreme.com # # # # Created: 2014/10/29 # # # # Post your comments at: # # https://blog.nahoo.co.uk/server-white-listing/ # # # ####################################################### ip=$1 echo "Firewall Log for $ip: "; grep -m 10 $ip /var/log/lfd.log; echo ''; /scripts/cphulkdwhitelist $ip; /usr/sbin/csf -dr $ip; /usr/sbin/csf -a $ip; /usr/sbin/csf -q;
I have mine running at: ip.designextreme.com and there is a simple page on the test server.
Last updated on


I corrected the JavaScript to cycle through a few different attempts to connect using the client browser. It now works consistently with Firefox, Chrome and Internet Explorer.
Recently I have automated some of the white listing processes. If you show you interest here, I will reply individually to you and if there is suitable interest, I’ll update this post with my improvements.