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.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 | <?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.noah.hearle.com/server-white-listing/ * * * \*****************************************************/ session_start(); chdir(__DIR__); define('EMAIL_SUBJECT', 'IP Whitelist Request'); define('RECIPIENT_NAME', 'Your Name'); define('RECIPIENT_EMAIL', 'ip@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.noah.hearle.com/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:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | #!/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.noah.hearle.com/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.
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.