PHP Check subdomain sensitive to IP address - php

I'm having some issue with something that seemed simple to me at first, but is now proving very difficult. Maybe I'm over thinking it - would love your help.
Overview:
I have a web application with two interfaces (1 for clients and 1 for customers). All customers get routed one way and all clients get routed another. I determine which login screen to show based on their subdomain. customers get the base domain (+www) and clients go to [clientName].example.com
Problem:
I was determining this before by doing string manipulations on env("HTTP_HOST") -- see code below. However, this now poses an issue when using local IPs (for testing with other devices/ people). My code, which looks for '.' in the host environment fails because IPs have 3 dots and 'localhost' has 0
These are the different naming parameters I've established and how I'd like the route...
CUSTOMER ----------------------------- CLIENT
xyz.example.com ------>
<------ www.example.com
<------ example.com
xyz.localhost ------>
<------ www.localhost
<------ localhost
xyz.192.168.X.X ------>
<------ www.192.168.X.X
<------ 192.168.X.X
I could be really over thinking this and am hoping there's some simple Php function like "get_subdomain()" that will do this for me. But I'm not seeing it and would really love some help.
Thanks!
Current Code:
$host = env("HTTP_HOST");
$group = null;
// if there is exactly one dot IE example[dot]com then there is no subdomain
if(substr_count($host,'.')==1){
$group = 'customer'
}else{ // there is a subdomain
$subdomain = substr($host, 0, strpos($host, "."));
if($subdomain=='www'){
$group = 'customer'
}else{
$group = 'client'
}
}
CakePhp if that helps?

I hope this answer does not seem to avoid your specific question, but it seems to me that you are inviting alternatives in your question. I do think you are over-thinking the solution, especially since it is primarily to assist you in your test environment.
What I suggest is that you define your own local domains for testing instead of using IP Addresses. So for example you could (in your hosts file or equivalent) define:
xyzclient.mylocaldomain 192.168.1.1 [or whatever your local ip is]
www.mylocaldomain 192.168.1.1
xyz.localhost 192.168.1.1
www.localhost 192.168.1.1
Then you don't need to code any differently for local or live environments. Just in case: this guide to setting up and configuring local domains may be useful.

Related

How to restrict website accessing, if user is on remote device and not on a work computer? (work time tracker app)

I would like to make a PHP website, where employees can log in/out themselves and these logs will count as a time when they started and ended their working day. I would like to allow them to do that only on their work computer and not for example on their phone while they are still on the way, but they want to avoid "being late".
So I'm struggling with a few ideas, but any of them seems to be the right solution.
Allow using the website only for specific IP addresses. But then I realized that in our place IP address is dynamic and changing it for static costs too much in our area.
Check user location. But then I saw that when I'm checking my public IP address, the location is completely wrong! Our building isn't even close to the loaded area.
Using a COOKIE/token on a work computer. But it's very easy to set the same cookie on your own device and I'm not the only IT employee here.
Checking MAC address. As I read here it's possible only in specific cases.
Block access for mobiles. But detecting a mobile is based on browser and if the user click "Request Desktop Site" scripts will say that's a computer.
Is there another method, which I can use to achieve my goal? Am I missing something?
May I bind my app for example with some other technologies that will allow me to do that? Or maybe I should try a combination of all of them?
I couldn't find any script, which would take care of that. In the worst case it doesn't have to be "perfectly secure", but I would like to be it at least hard, annoying, or time-consuming to try to "cheat" in this system.
I would run your app in the office LAN. Nobody will be able to access it from outside except if they can do remote desktop to the office computer or if they have VPN. But if you are in the IT team you may could fix IP ranges for the office computers so that you could exclude the VPN.
In terms of security, in any case it may be better having it running in your LAN. I'm sure you've got a server somewhere and if it's not the case then you could use a NAS (Synology offers NGINX, Apache, PHP and much more) or a little Rasperry Pie or something similar.
If you haven't got a fixed IP, you could also use DynDNS and have it mapped to a sub-domain such as company-name.dyndns.org and then on your PHP app you could have a cron job that gets the IP address from the domain name and updates it every minutes (I'm sure it's quickly run). It could then store it inside a config file, this way:
<?php
define('ALLOWED_IP_FILE', 'allowed-ips.inc.php');
$ALLOWED_DOMAINS = [
'your-company.dyndns.org',
'you-at-home.dyndns.org',
];
$allowed_ips = [];
foreach ($ALLOWED_DOMAINS as $allowed_domain) {
$ip = gethostbyname($allowed_domain);
if ($ip !== $allowed_domain) {
// Store with the IP in the key and value for ease when checking the IP validity.
$allowed_ips[$ip] = $ip;
} else {
fprintf(STDERR, "ERROR: Could not find the IP of $allowed_domain!\n");
}
}
$allowed_ips_export = var_export($allowed_ips, true);
$config_file_content = <<<END_OF_CONFIG
<?php
// Don't edit! This config file is generated by cron-ip-address.php.
\$ALLOWED_IPS = $allowed_ips_export;
END_OF_CONFIG;
if (file_put_contents(ALLOWED_IP_FILE, $config_file_content) === false) {
fprintf(STDERR, 'ERROR: Could not write config file ' . ALLOWED_IP_FILE . "\n");
}
This generates a config file to include in your app. Example of content generated if you run the script I wrote above:
<?php
// Don't edit! This config file is generated by cron-ip-address.php.
$ALLOWED_IPS = array (
'142.250.203.99' => '142.250.203.99',
'23.201.250.169' => '23.201.250.169',
);
Now, in your app, just include it and test the presence of the IP in the $ALLOWED_IPS array:
<?php
include ALLOWED_IP_FILE; // If this is declared in a common config file.
// include 'allowed-ips.inc.php'; // If you haven't got a common config file.
if (!isset($ALLOWED_IPS[$_SERVER['REMOTE_ADDR']])) {
http_response_code(403);
die('Sorry, you cannot access it from here.');
}
Ideally, if what you actually want to track is when employees are in the workplace and logged on / for how long, it would be probably better to just track local machine-logins via a domain controller - a method reachable from the internet is suboptimal exactly for the reasons you mentioned.
If you have an intranet which users cannot tunnel into but can access from their work machines, I'd say hosting your login-page only inside that intranet is the easiest way to achieve what you want with the methods you suggest.
Alternatively, if employee work-machines use windows under a domain controller - you can restrict access to Windows certificate-storage, then install/push a certificate and require that to be present via your server-configuration. In that case, it doesn't matter if the website is accessible from the internet. I'm sure there are similar solutions if work-machines are not on Windows.
This admittely old question gives some pointers in the right direction on how to require client certificates from a Webserver (IIS in that case).

How to get the Public IP

I'm trying to get the Public IP of someone that use the form of the page I do.
I don't know with which programming language would do that. I was reading on the web and I found some:
// PHP Code
$_SERVER["REMOTE_ADDR"]
This outputs: 127.0.0.1 (Local IP).
Then I found this too:
// PHP Code
$externalContent = file_get_contents('http://checkip.dyndns.com/');
preg_match('/\b(?:\d{1,3}\.){3}\d{1,3}\b/', $externalContent, $m);
$externalIp = $m[0];
This outputs the correct IP (Public IP), but that needs to use other web page (http://checkip.dyndns.com/).
I wonder How do the pages like that get the Public IP?. I am looking for a way to get it without need to use other web page. Thanks.
The $_SERVER["REMOTE_ADDR"] should work fine for what you are trying to do here. The reason you are getting 127.0.0.1 is because you are running this in a local environment.
If you put this script on a live webserver and I access it, you will get the same IP from $_SERVER["REMOTE_ADDR"] as I get when I check whatismyip
And anyhow, having the server call:
$externalContent = file_get_contents('http://checkip.dyndns.com/');
will only get you successful in returning your servers IP address, not the visitors.
This problem had me stumped for a long while.
If you have access to your own remote server, what I did to solve this problem was create a simple server-side script echo $_SERVER['REMOTE_ADDR']; to give me the public IP assigned by my ISP to my device from my localhost.

Read a file from a different server

Reason:
I am a webmaster of 7 sites, and to manage unwanted comments on a contact form I block the IP of bad commentators. Each time i get a new bad IP I have to edit each contact form on all 7 servers, which is very time consuming. What i would like is for the IP addresses to be put in 1 file on my server and just read in my all the other sites.
Current Code: (I have shortened the IP array)
<?php
$deny = array("91.200.14.59", "91.207.7.141");
if (in_array ($_SERVER['REMOTE_ADDR'], $deny)) {
header("location: index.php?page=error404");
exit();
} ?>
Answer Required:
How do i get the above code to read the IP file (array) from another server?
An example of the code would truly be appreciated.
Thanks
I'd be going about this the other way around: keep the list up to date locally (in a version control repository no less), and push the changes using a deploy tool. For instance, Ansible is a neat little tool. Example configuration:
---
- hosts: comment-forms
tasks:
- name: Ensure blacklist is up to date
copy: src=blacklist.txt
dest=/var/www/conf/blacklist.txt
owner=www-data
group=www-data
mode=440
Then deploy whenever you update the list:
$ ansible-playbook blacklist.yml
It's that easy, once you've set it up. And it means you don't need to make costly remote requests from your servers all the time.
here what you can do:
Create one blocked IP file on one of your servers.
e.g filename = blockip.txt
content of blockip.txt:
91.200.14.59,91.207.7.141..
Make sure the file is accessible via http protocol.
e.g: http://www.example.com/blockip.txt
On your application server, create a function which will read blockip.txt file and compare with the remote ip .
e.g:
<?php function check_spam_user($remote_ip){
$x = file_get_content('http://www.example.com/blockip.txt');
if(strpos($x,$remote_ip) === FALSE){
//real user
}
else {
//spammers
}
} ?>
You can use any logic for reading file and comparing ip address.
With this every time you got new IP address you need to update just blockip.txt file, rest all will be taken care by function check_span_user().

Is there anyway in PHP to use uniquely identify a user's router?

Is there anyway in PHP to use uniquely identify a user's router? I'd like t know what users are on the same router.
The general answer is going to basically be no - detecting network topology is a non-trivial operation (and certainly detecting the path packets took to you can be well-nigh impossible from an endpoint). However, it sounds like you have some kind of specific topology which perhaps if you tell us more about we might be able to help you with.
Presuming the following things:
You have two ingress routers
Your web server only has one ethernet interface
You're trying to determine which router the traffic came through
You could VLAN tag all incoming traffic at each ingress interface (and put all your hosts on untagged switch interfaces), and give yourself an interface alias on your web server for each VLAN, and thus by knowing which virtual interface you came in on, you'll know what ingress router the traffic came from.
You can retrieve the users IP address using $_SERVER['REMOTE_ADDR'] and then use a traceroute utility to get the hops and check for the routers that you wish to find, if you know the IPs of both of them.
Assuming that the router is not address-translating for them, otherwise this will not work, as it relies on being able to get back through the router to the user. If either router can return to the user, then it will not work at all. Good for dial-in users though.
<?php
$ip = $_SERVER['REMOTE_ADDR'];
$router1IP = "123.123.123.123";
$output = array();
exec('traceroute -n ' . $ip, $output, $result);
if ($result == 0) {
$outputText = implode("\n", $output);
if (preg_match("/" . preg_quote($router1IP) . "/", $output)) {
echo "Router 1";
} else {
echo "Router 2";
}
}
?>
The best you can do is identify a users IP address using the $_SERVER['REMOTE_ADDR']. If ip address corresponds to router, you're in luck.

PHP - Domain to IP

I current have a system which works like this:
Insert IP and it will post the IP to another .php page. However, when I try post http://google.com it does not turn the domain into a IP.
How would I do that? E.g. when a user inserts http://google.com or any domain it will auto resolve the IP.
I know the function gethostbyadd, I dont know how to structure it out e.g. Forms, table, post data.
Thanks if any can help.
What have you got together so far? How is it failing?
A wild guess is that you're typing in http://google.com/ and trying to get an IP from that, and that will fail, as the URL contains protocol information as well. You need to pass the domain name, and only the domain name to gethostbyname:
gethostbyname('www.google.com'); // Works
gethostbyname('http://www.google.com'); // Will not work
If you have the protocol part (http://) in the beginning, you can use parse_url:
gethostbyname(parse_url('http://www.google.com', PHP_URL_HOST));
If you're having some other, specific problem, let us know. If you don't know where to start, I suggest start by reading up on a programming manual ;)
I think you're looking for gethostbyname:
$ip = gethostbyname('www.google.com');
Note, make sure you strip the http:// and any white space/trailing characters as this will likely prevent accurate results.
the function you are looking for is $x = gethostbyname('stackoverflow.com');
You probably need to look into using http://www.php.net/manual/en/function.gethostbynamel.php
In some people the function gethostbyname is running slowly or running once in a while. Some say that the apache needs rebooting to get the function started. I can not confirm this, but I want to give an alternative method how to find IP by Domain using nslookup
function getAddrByHost($host, $timeout = 1) {
$query = `nslookup -timeout=$timeout -retry=1 $host`;
if(preg_match('/\nAddress: (.*)\n/', $query, $matches))
return trim($matches[1]);
}
echo getAddrByHost('example.com');
speed test using XHProf:
attempt 1
gethostbyname 5,014,593 microsec
getAddrByHost 29,656 microsec
attempt 2
gethostbyname 5,016,678 microsec
getAddrByHost 13,887 microsec
attempt 3
gethostbyname 5,014,640 microsec
getAddrByHost 8,297 microsec
Conclusion: the function gethostbyname is performed for more than 5 seconds, which is very long. Therefore, I advise you to use a faster function getAddrByHost
note: php use this file /etc/resolv.conf to get DNS servers:
In my case I use BIND (named) which works on the host 127.0.0.1
# /etc/resolv.conf
nameserver 127.0.0.1
nameserver 8.8.8.8
nameserver 4.4.4.4

Categories