corz.org uses cookies to remember that you've seen this notice explaining that corz.org uses cookies, okay!
<?php
$ip_version = '0.5.1';
/*
ip - tells you your ip address, aka. "What's my IP?"
Simply tells the HTTP client your current ip address. handy.
Simply being the operative word - it's plain text, nothing else, so
you can use a regular web browser, or incorporate something like..
curl https://corz.org/ip
into your scripts/DUC/FTP client/etc.. /ip just happens to be where
I keep it, for ease of use (and easy to remember). I have a mod_rewrite
redirect that points you to the real script, currently..
rewriterule ^ip$ /public/machine/source/php/ip.php [nc]
or something along those lines. Feel free to link to mine, it's a
permanent feature.
You can get back your host "name", if you have one, by sending ?name=true
rewriterule ^host$ /public/machine/source/php/ip.php?name=true [nc]
NOTE: if you are running this somewhere relativelty quiet, the entire
script can be reduced to a couple of lines..
<?php
header('Content-Type: text/plain');
header('Connection: Close');
echo $_SERVER['REMOTE_ADDR'];
?>
Everything else is for dealing with potential abuse.
Enjoy!
;o)
(c) 2004->tomorrow! cor + corz.org ;o)
*/
// prefs..
//
// Minimum check interval, in minutes..
// Note: you can use fractions, e.g. for 30 seconds, use: 0.5
//
$ip['min_interval'] = 10; // minutes
// location of ip sessions directory..
$ip['sessions_folder'] = '/home/cor/tmp/ip';
// An email address that banned users can mail once they have fixed their setup.
// this is sent in plain text - you may want to use some kind of obfuscation..
$ip['display_email'] = 'abuses at this domain';
/*
Garbage Collection Limit
[default: $ip['GC_limit'] = 10000;]
To prevent your server's hard drive filling up with stale client sessions,
we run a periodic garbage collection routine to sweep up the old files.
How periodically, is up to you. By default, we will check for garbage every
10,000 hits. I'm thinking this would be around a 2-daily hit rate for a
small site (@ 5000 hits per day).
Obviously, you can chage this number to anything you like, depending on how
busy your site is, and how much space you have on the disks.
If you don't want ip to clean up its garbage, set this to 0. And ensure you
have some other mechanism to handle it.
NOTE: this does not clean up your banned ip addresses, you will need to deal
with those manually. Or better yet, just leave them!
*/
$ip['GC_limit'] = 10000;
/*
GarbAge!
[default: $ip['GC_age'] = 168;] // a week
How old, in hours, is considered "stale"?
Any ID files older than this will be swept away (deleted).
*/
$ip['GC_age'] = 168;
//
// end prefs
// let's go..
// grab their ip..
$ip['remote_ip'] = $_SERVER['REMOTE_ADDR'];
// and their host name
$ip['remote_name'] = gethostbyaddr($ip['remote_ip']);
// If IP is BANNED - die right now..
//
if (file_exists($ip['sessions_folder'].'/banned/'.$ip['remote_ip'])) {
send_banned_header();
}
$banned_host = false;
// Plug bad hosts into this file. Partial match is fine.
$ip['banned_hosts'] = file($_SERVER['DOCUMENT_ROOT'].'/inc/data/ip_banned_hosts');
// Please don't plug my ip URL into your API - that's how to get your entire platform banned!
// This service is for corz.org visitors, thanks!
if (stristr(@$_SERVER['HTTP_USER_AGENT'], 'Linux; U; Android')) {
$banned_host = true;
}
if (is_array($ip['banned_hosts'])) {
foreach($ip['banned_hosts'] as $somehost) {
if (strstr($ip['remote_name'], $somehost)) {
$banned_host = true;
}
}
}
if ($banned_host) {
header('Warning: This service is for corz.org visitors - If you want to plug it into your API/Appliance, please contact me to discuss license terms. Better yet, use the STUN protocol, which was designed specifically for that sort of thing!');
send_banned_header();
}
// Let us begin..
ip_collect_garbage($ip['sessions_folder'].'/Counter', $ip['GC_limit'], $ip['GC_age']);
// Some basic throttling - max hits one per X minutes
$ip['session'] = array();
$ip['sess_file'] = $ip['sessions_folder'].'/'.$ip['remote_ip'];
if (file_exists($ip['sess_file'])) {
$ip['session'] = read_ip_session($ip['sess_file']);
}
$last_hit = 0;
if (isset($ip['session']['last_hit'])) {
$last_hit = $ip['session']['last_hit']; // UNIX timestamp
}
$now = time();
$lp = chr(9).'OK! ';
$banned = false;
$log_str = gmdate('Y-m-d H:i:s').':';
$hits_log = $_SERVER['DOCUMENT_ROOT'].'/inc/log/.ip_hits';
// the "page"..
header('Content-Type: text/plain; charset=utf-8');
header('Connection: Close');
// format the check interval for display...
$pl = '';
$cint = 'minute';
if ($ip['min_interval'] !== 1) {
$pl = 's';
if ($ip['min_interval'] < 1) {
$cint = 'second';
$ip['min_interval'] = 60*$ip['min_interval'];
}
}
$intv_msg = $ip['min_interval'].' '.$cint.$pl;
if (($now - $last_hit) > ($ip['min_interval']*60)) {
if (isset($_GET['name']) and $_GET['name']) {
echo $ip['remote_name'];
} else {
echo $ip['remote_ip'];
}
unset($ip['session']['throttle_msg_sent']);
// reset hammer count - they backed-off.
$ip['session']['hammer_count'] = 0;
} else {
// HAMMER!
$lp = chr(9).'DENY! ';
if (!isset($ip['session']['throttle_msg_sent'])) {
echo 'Minimum check interval is ',$intv_msg,"\n\n",'NOTE: 10 infractions = banned!';
$ip['session']['throttle_msg_sent'] = true;
$lp = chr(9).'NOTIFIED!';
}
// increasse the hammer count..
$ip['session']['hammer_count'] += 1;
if ($ip['session']['hammer_count'] == 10) {
echo "This is your final warning!\n\nPlease set your check interval to less than $intv_msg.";
}
if ($ip['session']['hammer_count'] > 10) {
$lp = chr(9).'BANNED! ';
$banned = true;
echo "This IP address is now banned!\n\nTo lift the ban, please set your check interval to less than $intv_msg\nand then email: ",$ip['display_email'],".";
}
}
// store the time of THIS hit..
$ip['session']['last_hit'] = time();
// write out updated session to session file..
write_ip_session($ip['sess_file'], $ip['session']);
// some basic logging..
// IP Address / Host..
$log_str .= ' ['.$ip['remote_ip'].'] ';
$log_str .= @str_repeat (' ', 15-strlen($ip['remote_ip']));
//$ip['remote_name'] = gethostbyaddr($ip['remote_ip']);
$log_str .= '['.$ip['remote_name'].']' ;
$log_str .= @str_repeat (' ', 32-strlen($ip['remote_name']));
$log_str .= $lp;
$ua = substr(@$_SERVER['HTTP_USER_AGENT'], 0, 100);
$ua = str_replace('Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome', 'Chrome', $ua);
if ($ua) {
$log_str .= chr(9).'User Agent: '.$ua;
}
write_log($hits_log, $log_str);
// they are gone!
if ($banned) { ban_ip_user(); }
function write_log($log_file, $logstring) {
if ($logstring and $log_file) {
// Write the log..
if (!file_exists($log_file)) { file_put_contents($log_file, ''); }
if ($fp = fopen($log_file, 'a')) {
fwrite($fp, $logstring."\n");
fclose($fp);
}
}
}
// We are using an Anti-Hammer-like "fake" session, as 9 out of 10
// devices will not support php sessions at all (no cookies).
// read serialized array data from a file, and return as an array..
function read_ip_session($no_cookie_file) {
if (file_exists($no_cookie_file)) {
$file_handle = fopen($no_cookie_file, 'rb');
if ($file_handle) {
$lock = flock($file_handle, LOCK_EX);
if ($lock) {
$file_contents = @fread($file_handle, filesize($no_cookie_file));
flock ($file_handle, LOCK_UN);
}
}
fclose($file_handle);
$file_contents = unserialize($file_contents);
if (is_array($file_contents)) {
return $file_contents;
}
}
return false;
}
// serialize an array and write the string data to a file..
function write_ip_session($no_cookie_file, $array) {
$data = serialize($array);
if (empty($data)) { return; }
$fp = @fopen($no_cookie_file, 'wb');
if ($fp) {
$lock = flock($fp, LOCK_EX);
if ($lock) {
fwrite($fp, $data);
flock ($fp, LOCK_UN);
}
fclose($fp);
clearstatcache();
return (true);
}
}
// Ban someone who is hammering..
//
// This is elegant - we simply move the session file to a "banned" directory.
// Then we can check for its existence before we begin. If it exists, we die().
//
function ban_ip_user() {
global $ip;
if (!file_exists($ip['sessions_folder'].'/banned')) {
mkdir($ip['sessions_folder'].'/banned', 0777);
}
// move the session file to the banned directory..
rename($ip['sessions_folder'].'/'.$ip['remote_ip'], $ip['sessions_folder'].'/banned/'.$ip['remote_ip']);
}
function send_banned_header() {
global $ip, $hits_log;
write_log($hits_log, '['.$ip['remote_ip'].']['.$ip['remote_name'].'] BANNED!');
header($_SERVER['SERVER_PROTOCOL'].' 403 Forbidden');
header('Status: 403 Forbidden');
header('Connection: Close');
die(1);
}
/*
collect garbage
You could transplant this into another web app fairly easily.
Useful stuf..
*/
function ip_collect_garbage($count_file, $limit, $GC_age=168) {
if ($limit === 0) { return; }
if (ip_increment_hit_counter($count_file) >= $limit) {
$file_list = array();
if ($the_dir = @opendir(dirname($count_file))) {
while (false != ($file = readdir($the_dir))) {
if ((ord($file) != 46)) {
$file_path = dirname($count_file).'/'.$file;
if (file_exists($file_path)) {
if (filemtime($file_path) < (time() - $GC_age*60*60)) {
@unlink($file_path);
}
}
}
}
}
ip_increment_hit_counter($count_file, 0, 1); // reset the counter
}
}
/*
increment a counter
from my "file-tools.php", available elsewhere.
*/
function ip_increment_hit_counter($count_file, $report_only=false, $reset=false) {
$count = false;
if (!file_exists($count_file) or $reset) {
$file_pointer = fopen($count_file, 'wb');
fwrite ($file_pointer, '0');
fclose ($file_pointer);
}
// now the counter..
if (file_exists($count_file)) {
// read in the old score..
$count = trim(file_get_contents($count_file));
if ($report_only) { return $count; }
if (!$count) { $count = 0; }
$count++;
// write out new score..
if (is_writable($count_file)) {
$file_pointer = fopen($count_file, 'wb+');
$lock = flock($file_pointer, LOCK_EX);
if ($lock) {
fwrite($file_pointer, $count);
flock ($file_pointer, LOCK_UN);
}
fclose($file_pointer);
clearstatcache();
}
}
return $count;
}
/*
changes:
0.2:
Added basic hit logging.
Once enabled, I realize that corz.org/ip is getting over two thousand hits a
MINUTE! Holy Shit!
I noticed that a lot of these hits came from the same ISP, picked an IP at
random and popped it into my web browser. Auth login! Tried admin/admin and
got straight in! Tried another, the same story. And another.. YES! WTF!
Seriously? It looks like VNPT (using Yes Telecom hardware) have put my ip
check URL into their router firmware, for some reason - checks every 13s!
Thanks guys!
I wonder if their users realize how insecure their gateways are? I mean you
can get to everything - user/pass wifi setup, everything. pfff...
BTW, I tried a further six IPs at random and EVERY SINGLE ONE had its admin
open to the public with the default (Zyxel) admin/admin user/pass. SHODDY!
0.3:
Added throttle using Anti-Hammer-like fake session. Works great.
The minimum interval is configurable. If they attempt to update in this
time, they get a notification (one time) informing them of the minimum
interval, and thereafter nothing, until they back-off and wait a few
minutes. The default minimum interval is 1 minute.
0.4:
Added banning facility. After 10 strikes, they are out!
0.5:
Added garbage collection - old session files will be automatically cleaned-
up after a certain time. You can set how long is considered "stale"; by
default it is set to one week.
*/
?>