Find Available IP to host port - php

Im having a headache trying to figure out how to find an IP address in my list with the available ports.
My problem is quite simple actually but I just can't figure out how to program it.
I was hopping someone can point me in the right direction.
Maybe there is a way to optimize the list for it to be easier to search in it.
Any how here is my problem.
I have a list of IP and multiple ports on each of them own by a client.
I can have multiple clients on the same IP, but i can't have a client on multiple IP
So im trying to build a function that would tell me "hey you need to switch this client on this ip so you can have x client on this ip
So here is my example list.
$ReservedPortsOnIPs = array(
'10.0.0.1'=>array(
'TCP:80'=>array(
'ClientId'=>1
),
'TCP:443'=>array(
'ClientId'=>1
)
),
'10.0.0.2'=>array(
'TCP:80'=>array(
'ClientId'=>2
)
),
'10.0.0.3'=>array(
'TCP:443'=>array(
'ClientId'=>4
),
'TCP:22'=>array(
'ClientId'=>4
),
)
);
Now here is my code I have til now. ( im only able to find available IP ) so at the moment if for example im trying to find an ip available with lets say TCP:80 and TCP:443
There is none directly available but if I would change cleint 4 from 10.0.0.3 to 10.0.0.2 I would have 10.0.0.3 avaible for the ports im asking.
Im at a point where I need to do the same task but recursively but I have no idea how start ? :S
function PortAvailableInNetwork($Port, $ReservedPortsOnIPs){
foreach($ReservedPortsOnIPs as $IP => $Ports) {
if(!isset($Ports[$Port]))
return true; //We found it not used!
}
return false; // foreach runned and no ip has the port available.
}
function AddPort($Ports,$ClientId,&$ReservedPortsOnIPs)
{
//check if ports possibly available
if(!is_array($Ports))
{
if(!PortAvailableInNetwork($Ports,$ReservedPortsOnIPs))
return false;
}
else
foreach($Ports as $Port)
if(!PortAvailableInNetwork($Port,$ReservedPortsOnIPs))
return false;
$TmpReservedPortOnIp = $ReservedPortsOnIPs;
//Find Current Ports ClientId Has
$ClientsPorts = array();
if(!is_array($Ports))
$ClientsPorts[] = $Ports;
else
foreach($Ports as $Port)
$ClientsPorts[] = $Port;
foreach($ReservedPortsOnIPs as $IP => $Ports){
foreach($Ports as $Port => $PortInfo){
if($PortInfo['ClientId'] == $ClientId)
{
$ClientsPorts[] = $Port;
unset($TmpReservedPortOnIp[$IP][$Port]); //Remove the clientPort for search purposes
}
}
}
print_r($ClientsPorts);
//Now that we have all client ports lets search for an available ip address
$PortsAvailability = array();
foreach($TmpReservedPortOnIp as $IP => $Ports){
$PortsAvailability[$IP] = array('Available'=>array(),'UnAvailable'=>array());
foreach($ClientsPorts as $Port){
if(!isset($Ports[$Port]))
$PortsAvailability[$IP]['Available'][]=$Port;
else
$PortsAvailability[$IP]['UnAvailable'][]=$Port;
}
if(count($PortsAvailability[$IP]['Available']) == count($ClientsPorts))
return $IP;
}
//if we are at this step this mean no ip had all ports
usort($PortsAvailability,function($a,$b){
if(count($a['Available']) > count($b['Available']))
return -1;
else
return 1;
});
print_r($PortsAvailability);
}
echo AddPort(array('TCP:80','TCP:443'),5,$ReservedPortsOnIPs);
I am open to change my design, as I did this on top of my head the way I could see the problem and its maybe not the right way to do it.
thanks for your time reading my question :)

Related

PHP: Tor check not working

I've installed a Tor relay and Nginx and created my .onion on my Linux server.
In torrc HiddenServicePort 80 127.0.0.1:8747
In nginx's default: listen 8747
I've modified TorDNSExitList's PHP Pear Net_DNS to use Net_DNS2. When I echo out the $ip, $myip, $myport I get:
ip = 127.0.0.1
my ip = 127.0.0.1
port = 8747
Thus it is picking the IP address as the local machine and not the Tor exit node's IP address. Is there another why to test if the page is access via the Tor network?
(I've also tried this suggestion)
The solution is to check for 127.0.0.1 IP address, seeing that torrc points to 127.0.0.1. This works when accessing the website via the .onion path. But the full check still needs to be done as the website can be access via the full URL, e.g. http:// [IP Address]:[Port] - using a "normal" or Tor browser. My changes to the function below:
<?php include("Net/DNS2.php");
// torel_check ($ip, $port, $destip) queries the Tor DNS Exit List server.
// The result of the query is one of the following:
// -1 : DNS lookup failed to get a response, or other error occurred.
// 0 : $ip does not appear to be a Tor exit.
// 1 : $ip is a known Tor exit for the provided destination IP / port.
function revaddr ($ip) {
list($a, $b, $c, $d) = split("[.]", $ip);
return("${d}.${c}.${b}.${a}");
}
function torel_qh ($ip, $port, $destip) {
$rsrcip = revaddr ($ip);
$rdstip = revaddr ($destip);
return("${rsrcip}.${port}.${rdstip}.ip-port.exitlist.torproject.org");
}
function torel_check ($ip, $port, $destip) {
try{
if($ip == "127.0.0.1") {
//TX: Access via .onion path
// is Tor exit
return (1);
}
//TX: Access web site directly
$ndr = new Net_DNS2_Resolver();
$qh = torel_qh($ip, $port, $destip);
// uncomment these two lines to query the server directly...
//$ns = "exitlist-ns.torproject.org";
//$ndr->nameservers( array($ns) );
// tune DNS params accordingly. this is just my preference.
$ndr->retrans = 2;
$ndr->retry = 3;
$ndr->usevc = 0;
// perform DNS query
// TX: Old Net_DNS check $ndr->search($qh)
if (! $pkt = $ndr->query($qh)) {
if (strcmp($ndr->errorstring, "NXDOMAIN") == 0) {
// response but no answer. does not appear to be Tor exit.
return (0);
}
// search failed: no response or other problem...
return(-1);
}
if (! isset($pkt->answer[0])) {
// response but no answer section. does not appear to be Tor exit.
// (this should only happen when authority sections are provided without answer)
return(0);
}
// is Tor exit
return(1);
} catch(Net_DNS2_Exception $e) {
return (-1);
}
}
// get client request parameters from Apache or equiv server:
$ip = $myip = $myport = 0;
if (isset ($_SERVER["REMOTE_ADDR"])) { $ip = $_SERVER["REMOTE_ADDR"]; }
if (isset ($_SERVER["SERVER_ADDR"])) { $myip = $_SERVER["SERVER_ADDR"]; }
if (isset ($_SERVER["SERVER_PORT"])) { $myport = $_SERVER["SERVER_PORT"]; }
$istor = torel_check($ip, $myport, $myip);
TX: is my comments

Bann one or more IP address with PHP withouthtaccess using .htaccess

I'm looking for good code in PHP for Banning some spammers IP's My server is giving me error 500 if I'm using .htaccess
This will do the work
$getip = $_SERVER["REMOTE_ADDR"];
$banned_ip = array();
$banned_ip[] = '194.9.94.*';
$banned_ip[] = '77.105.2.*';
foreach($banned_ip as $banned)
{
$blacked=str_replace('*', '', $banned);
$len=strlen($blacked);
if ($getip==$blacked || substr($getip, 0, $len)==$blacked)
{
$_banned_ip=true;
}
}
if($_banned_ip==true){
echo 'THIS IP IS BANNED!';
exit;
}
The simplest way would be to have a database that keeps a list of the banned ip addresses, if you want to do it on the PHP end rather than directly in the server.
for($i = 0;$i < count($listOfIps);$i++) {
if($listOfIps[$i] == filteredIP($_SERVER['REMOTED_ADDR'])) { //filteredIP is not a native function, it's just a representation of however you want to filter the ip addresses which are sent to you
$banned = true;
}
}
if($banned):
//redirect user or kill script
else:
//render page
endif;
However, there may be better solutions based on the page or application specifics, but this is the best solution I can think of based on your question

Trying to change a php script from blocking identical ip to blockingidentical ID numbers

I am very new to PHP and still trying to learn the "ins and outs" to it.(Self-taught) I have a petition website that I had a friend develop a code for, to block identical ip's from signing more than once.
This particular petition is sent to offices with multiple signers that use the same IP, so I am needing to change the code from blocking duplicate IP's to blocking duplicate "GLVAR" numbers the signer provides. I have the database setup, but I just dont know where to exactly change the coding to make this work.
Also, I am trying to send the information the signer submitted to my email address for an extra copy. I know this should be simple, but like I said, I am self teaching and very new, so any help would be greatly appreciated. Thank you so much for your time.
<?php
include('database/config.php');
include('database/database.php');
$err = '';
if(isset($_POST['submit'])){
$first = addslashes(trim($_POST['first']));
$last = addslashes(trim($_POST['last']));
$glvar = addslashes(trim($_POST['glvar']));
$ip = isset($_SERVER['HTTP_X_FORWARDED_FOR']) ? $_SERVER['HTTP_X_FORWARDED_FOR'] : $_SERVER['REMOTE_ADDR'];
//echo $ip;
if(($first!='')&& ($last!='')&& ($glvar!='')){
$database = new Database(HOST, DATEBASE, USERNAME, PASSWORD);
$allUsers = $database->select('user','ip','*',"ip = '".$ip."'");
//echo $ip;
$checkIp = 0;
$checkIp = count($allUsers);
$userData = array(
'first_name' => $first,
'last_name' => $last,
'glvar_id' => $glvar,
'ip' => $ip,
);
if(!$checkIp) {
$database->insert('user',$userData);
header('location:thank-you.html');
} else $err.='<p style="color:red">Ooops! You have already signed the petition</p>';
} else {
if($first=='') $err.='<p style="color:red">Your first name not empty</p>';
if($last=='') $err.='<p style="color:red">Your last name not empty</p>';
if($glvar=='') $err.='<p style="color:red">Your GLVAR ID not empty</p>';
}
}
?>
You should query the database for the glvar rather than the IP:
It might look like this depending on what the glvar_id columns look like in the database.
$allUsers = $database->select('user','glvar_id','*',"glvar_id = '".$glvar."'");
//echo $ip;
$checkglvar = 0;
$checkglvar = count($allUsers);
if you want to mail yourself on success then you will want to configure the php mail function for work and add it here:
if(!$checkIp) {
$database->insert('user',$userData);
mail("to#me.com", "Subject", "message");
header('location:thank-you.html');
}

IP Address using PHP not reliable

I use a javascript API from (http://www.iplocationtools.com) to give me the location data from a visitors IP. For some reason, their API won't give me the actual IP of the visitor, just the other info, which is why I have to use PHP and CodeIgniter to give me the IP instead.
So I use CodeIgniter/PHP to get the IP of a visitor and add it to the database along with location data from above by using PHP's ip2long([the ip code igniter gives me])
I'm confused when my database table looks like this: http://pulse.media.mit.edu/images/1.png
Which is wrong? I'm tempted to believe CodeIgniter is wrong since it gives me the same IP so many times. Age and sex are self reported and I doubt one person is making up all this information.
At the end of the day, all we really need is the users IP and location, preferably from the same source, so we don't compound errors.
Anybody have a better idea on how to do this?
EDIT: Here is the code that I'm using to get the IP address from CodeIgniter
$data['ip_address'] = ip2long($this->input->ip_address());
$this->pulse_model->voter_info($data);
Then the voter_info function just inserts it into the database where it's stored as an INT(11).
And here is the function ip_address:
function ip_address()
{
if ($this->ip_address !== FALSE)
{
return $this->ip_address;
}
if (config_item('proxy_ips') != '' && $this->server('HTTP_X_FORWARDED_FOR') && $this->server('REMOTE_ADDR'))
{
$proxies = preg_split('/[\s,]/', config_item('proxy_ips'), -1, PREG_SPLIT_NO_EMPTY);
$proxies = is_array($proxies) ? $proxies : array($proxies);
$this->ip_address = in_array($_SERVER['REMOTE_ADDR'], $proxies) ? $_SERVER['HTTP_X_FORWARDED_FOR'] : $_SERVER['REMOTE_ADDR'];
}
elseif ($this->server('REMOTE_ADDR') AND $this->server('HTTP_CLIENT_IP'))
{
$this->ip_address = $_SERVER['HTTP_CLIENT_IP'];
}
elseif ($this->server('REMOTE_ADDR'))
{
$this->ip_address = $_SERVER['REMOTE_ADDR'];
}
elseif ($this->server('HTTP_CLIENT_IP'))
{
$this->ip_address = $_SERVER['HTTP_CLIENT_IP'];
}
elseif ($this->server('HTTP_X_FORWARDED_FOR'))
{
$this->ip_address = $_SERVER['HTTP_X_FORWARDED_FOR'];
}
if ($this->ip_address === FALSE)
{
$this->ip_address = '0.0.0.0';
return $this->ip_address;
}
if (strpos($this->ip_address, ',') !== FALSE)
{
$x = explode(',', $this->ip_address);
$this->ip_address = trim(end($x));
}
if ( ! $this->valid_ip($this->ip_address))
{
$this->ip_address = '0.0.0.0';
}
return $this->ip_address;
}
$_SERVER['REMOTE_ADDR'] is the PHP code to return the IP address of the person viewing the page.
Old versions of ip2long() will return -1 if the IPv4 address is invalid. You may want to use inet_pton instead and expand the field used to hold it to 128 bits.
Based on your code, it looks like $this->input->ip_address() has the possibility of returning '0.0.0.0' if the IP is not valid or could not be determined. However, your comments also state that you need to record the ip address even if the above method returns '0.0.0.0'.
First, I'd recommend checking to see if $this->input->ip_address() and $this->valid_ip() are working as expected. Is $this->valid_ip() returning false for IP's that should be considered valid?
Second, I'd update your code to always fall back to $_SERVER['REMOTE_ADDR'] if $this->input->ip_address() returns '0.0.0.0'.
$ip_address = $this->input->ip_address();
if($ip_address == '0.0.0.0') {
$ip_address = $_SERVER['REMOTE_ADDR'];
}
$data['ip_address'] = ip2long($ip_address);
$this->pulse_model->voter_info($data);
Or if you wanted, you could not use $this->input->ip_address() and do as #rockerest suggests and just use $_SERVER['REMOTE_ADDR'] to being with.
$data['ip_address'] = ip2long($_SERVER['REMOTE_ADDR']);
$this->pulse_model->voter_info($data);

Verifying a Googlebot

I'm going to block all bots except the big search engines. One of my blocking methods will be to check for "language": Accept-Language: If it has no Accept-Language the bot's IP address will be blocked until 2037. Googlebot does not have Accept-Language, I want to verify it with DNS lookup
<?php
gethostbyaddr($_SERVER['REMOTE_ADDR']);
?>
Is it ok to use gethostbyaddr, can someone pass my "gethostbyaddr protection"?
function detectSearchBot($ip, $agent, &$hostname)
{
$hostname = $ip;
// check HTTP_USER_AGENT what not to touch gethostbyaddr in vain
if (preg_match('/(?:google|yandex)bot/iu', $agent)) {
// success - return host, fail - return ip or false
$hostname = gethostbyaddr($ip);
// https://support.google.com/webmasters/answer/80553
if ($hostname !== false && $hostname != $ip) {
// detect google and yandex search bots
if (preg_match('/\.((?:google(?:bot)?|yandex)\.(?:com|ru))$/iu', $hostname)) {
// success - return ip, fail - return hostname
$ip = gethostbyname($hostname);
if ($ip != $hostname) {
return true;
}
}
}
}
return false;
}
In my project, I use this function to identify Google and Yandex search bots.
The result of the detectSearchBot function is caching.
The algorithm is based on Google’s recommendation - https://support.google.com/webmasters/answer/80553
In addition to Cristian's answer:
function is_valid_google_ip($ip) {
$hostname = gethostbyaddr($ip); //"crawl-66-249-66-1.googlebot.com"
return preg_match('/\.googlebot|google\.com$/i', $hostname);
}
function is_valid_google_request($ip=null,$agent=null){
if(is_null($ip)){
$ip=$_SERVER['REMOTE_ADDR'];
}
if(is_null($agent)){
$agent=$_SERVER['HTTP_USER_AGENT'];
}
$is_valid_request=false;
if (strpos($agent, 'Google')!==false && is_valid_google_ip($ip)){
$is_valid_request=true;
}
return $is_valid_request;
}
Note
Sometimes when using $_SERVER['HTTP_X_FORWARDED_FOR'] OR $_SERVER['REMOTE_ADDR'] more than 1 IP address is returned, for example '155.240.132.261, 196.250.25.120'. When this string is passed as an argument for gethostbyaddr() PHP gives the following error:
Warning: Address is not a valid IPv4 or IPv6 address in...
To work around this I use the following code to extract the first IP address from the string and discard the rest. (If you wish to use the other IPs they will be in the other elements of the $ips array).
if (strstr($remoteIP, ', ')) {
$ips = explode(', ', $remoteIP);
$remoteIP = $ips[0];
}
https://www.php.net/manual/en/function.gethostbyaddr.php
The recommended way by Google is to do a reverse dns lookup (gethostbyaddr) in order to get the associated host name AND then resolve that name to an IP (gethostbyname) and compare it to the remote_addr (because reverse lookups can be faked, too).
But beware, end lokups take time and can severely slow down your webpage (maybe check for user agent first).
Google also publishes a machine readable file containing the IP addresses of their crawlers, see the link below.
See:
https://developers.google.com/search/docs/advanced/crawling/verifying-googlebot
https://webmasters.googleblog.com/2006/09/how-to-verify-googlebot.html
//The function
function is_google() {
return strpos($_SERVER['HTTP_USER_AGENT'],"Googlebot");
}
How to verify Googlebot.
If you have a site that has thousands of pages then going for reverse DNS will be costly, So I think the best method is to hard code ips list. (Php code example)
function googleBotIPsList(){
return "ips"; //hard coded IPs here.
}
Also you can make another function which gets the latest ips. Now upto you how frequently you call this function.
function getLatestGoogleBotIPsList(){
$ch = curl_init();
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_URL,"https://developers.google.com/static/search/apis/ipranges/googlebot.json");
$result=curl_exec($ch);
curl_close($ch);
$result = (json_decode($result, true));
$ips='';
for($i=0;$i<count($result['prefixes']);$i++) {
$ips .= ($result['prefixes'][$i]['ipv6Prefix'] ? $result['prefixes'][$i]['ipv6Prefix'] : $result['prefixes'][$i]['ipv4Prefix']).',';
}
return rtrim($ips,',');
}
Then use strpos to check from the hardcoded list
if(strpos(googleBotIPsList(),zen_get_ip_address()) !==false){
// Insert into your table etc.
}

Categories