Skip to content

Instantly share code, notes, and snippets.

@danielrichman
Created April 2, 2013 00:14
Show Gist options
  • Save danielrichman/5288899 to your computer and use it in GitHub Desktop.
Save danielrichman/5288899 to your computer and use it in GitHub Desktop.
<?php
/*
* Copyright (C) 2010 Daniel Richman
* This is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this. If not, see <http://www.gnu.org/licenses/>.
*/
@error_reporting(E_ALL);
Header("Content-type: text/plain");
/* Get info */
$remote_ip = $_SERVER["REMOTE_ADDR"];
$remote_port = $_SERVER["REMOTE_PORT"];
$local_ip = $_SERVER["SERVER_ADDR"];
$local_port = $_SERVER["SERVER_PORT"];
$rdns = get_rdns($remote_ip);
$ident = get_ident($local_port, $remote_ip, $remote_port, 1);
/* Add failure notices */
if ($rdns == false) $rdns = "None";
if ($ident == false) $ident = "No response";
/* Print output */
echo "HTTP Server: $local_ip:$local_port\n";
echo "HTTP Client: $remote_ip:$remote_port\n";
echo "Client RDNS: $rdns\n";
echo "Client Ident: $ident\n";
/* Functions */
function get_ident($local_port, $remote_ip, $remote_port, $timeout)
{
$query = "$remote_port, $local_port\n";
$errno = 0;
$errstr = '';
$socket = @fsockopen($remote_ip, 113, $errno, $errstr, $timeout);
if (!$socket) return false;
$result = @socket_set_timeout($socket, $timeout);
if (!$result) { @fclose($socket); return false; }
$result = @fwrite($socket, $query);
if (!$result) { @fclose($socket); return false; }
$response = @fread($socket, 1024);
@fclose($socket);
if (!$response || strlen($response) == 0) return false;
$response_array = @explode(':', $response);
if (count($response_array) < 3) return false;
$response_port_array = explode(',', $response_array[0]);
if (trim($response_port_array[0]) != $remote_port ||
trim($response_port_array[1]) != $local_port)
return false;
array_shift($response_array);
foreach ($response_array as $key => $value)
$response_array[$key] = trim($value);
return implode(' : ', $response_array);
}
function get_rdns($ip)
{
$segments = array_reverse(explode('.', $ip));
$segments[] = "in-addr";
$segments[] = "arpa";
$result = timed_dns($segments, 12 /* QTYPE PTR */, '8.8.4.4', 1);
if ($result === false) return false;
return implode('.', $result);
}
assert(mt_getrandmax() >= 65535);
function timed_dns($segments, $type, $server, $timeout)
{
/* Header */
$identifier = mt_rand(0, 65535);
$header_length = 12;
$header = pack('nC2n4',
$identifier,
0x01, /* options1: RD set, all others unset. */
0x00, /* options2: unset */
1, 0, 0, 0); /* one question, no answers, etc. */
assert(strlen($header) == $header_length);
/* Question Section */
$data = '';
foreach ($segments as $segment)
{
$data .= pack('C', strlen($segment));
$data .= $segment;
}
$data .= pack('Cnn',
0, /* Null terminator */
$type, /* QTYPE */
1); /* QCLASS: 1 - internet */
$errno = 0;
$errstr = '';
$socket = @fsockopen("udp://$server", 53, $errno, $errstr, $timeout);
if (!$socket) return false;
$result = @socket_set_timeout($socket, $timeout);
if (!$result) { @fclose($socket); return false; }
$result = @fwrite($socket, $header.$data);
if (!$result) { @fclose($socket); return false; }
$response = @fread($socket, 1024);
@fclose($socket);
if (!$response || strlen($response) == 0) { return false; }
/* Unpack the header */
$reply_header = unpack('nid/C2op/n4c',
substr($response, 0, $header_length));
/* Inspect the header */
if ($reply_header["id"] != $identifier) return false; /* wrong ID */
if (!($reply_header["op1"] & 0x80)) return false; /* not a reply */
if (($reply_header["op2"] & 0x0F)!= 0) return false; /* error */
if ($reply_header["c1"] != 1) return false; /* qdcount bad */
if ($reply_header["c2"] == 0) return false; /* ancount bad */
/* Check the query was the same */
if ($data != substr($response, $header_length, strlen($data)))
return false;
/* Grab the first answer */
$answer = substr($response, $header_length + strlen($data));
$answer_info_len = 12;
$answer_info = unpack('nname/ntype/nclass/Nttl/nrdlength',
substr($answer, 0, $answer_info_len));
if ($answer_info["type"] != $type) return false;
if ($answer_info["class"] != 1 /* internet */) return false;
if (strlen($answer) != $answer_info["rdlength"] + $answer_info_len)
return false;
$answer = substr($answer, $answer_info_len);
$answer_segments = Array();
while (true)
{
$length_r = unpack('Clen', $answer{0});
$length = $length_r["len"];
if (!$length) break;
$answer_segments[] = substr($answer, 1, $length);
$answer = substr($answer, 1 + $length);
}
/* All done */
return $answer_segments;
}
?>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment