How to read the host name from a request URI in PHP? - php

For the router, I wanted to get the host name from the URI upon a server request. I know that I need to read it from the $_SERVER variable. But it seems that in the $_SERVER array there are multiple entries (at least two) for the host name.
Could you please tell me which value should I choose to read - the most reliable one?
For example, when I have an URI like this:
http://local.mvc/mycontroller/myaction
the $_SERVER array will have:
[HTTP_HOST] => local.mvc
[SERVER_NAME] => local.mvc
I need to obtain the value local.mvc.
Thank you for your time.

SERVER_NAME is the name assigned to the given server in its configuration (be it i.e. apache.conf file and its ServerName directive or similar for other software), while HTTP_HOST value is obtained from the headers of HTTP request that comes from client (web browser usually). These two might differ if your server servers multiple domains (like shared server / virtual server hosting). Depending on the use case you may want to use either of these, however HTTP_HOST seems like better choice as it is always tells what user wanted to reach.

the $_SERVER variable has 'REQUEST_URI'.
just var_dump the server variable, and is should be there (or look at the documentation)

If you're using PHP5 or PHP7, try php_uname
To get the host name:
php_uname("n");

Related

local hostname identification messed up when `host:` header is modified.

I created a simple php script with the following contents:
<?php
phpinfo();
?>
Then I executed it on the server normally as a URL (example: http://xxx.xxx.xxx.xxx/whatever.php) and received information about what's installed, with php, etc.
Next, I used an advanced tool (opera dragonfly) and requested the same URL again, with the host HTTP request header changed from xxx.xxx.xxx.xxx to a random word. I'll call the new value word.
The same page appears, but what I find is that the SCRIPT_URL environment variable value is http://word/whatever.php instead of http://xxx.xxx.xxx.xxx/whatever.php and HTTP_HOST and SERVER_NAME are both set to word.
Why can't one environment variable value be the domain part of the url someone types in (like http://xxx.xxx.xxx.xxx) and another one be the value of the http host: header? and how do I fix this?
I'm using apache.

How to check if request came with the right ssl certificate

I have a php file on a server. Some service will send requests to this file and i want to check if the variables: SSL_CLIENT_VERIFY, SSL_CLIENT_S_DN_O, SSL_CLIENT_S_DN_L, SSL_CLIENT_S_DN_CN, SSL_CLIENT_S_DN_C, SSL_CLIENT_I_DN_O, SSL_CLIENT_I_DN_CN, SSL_CLIENT_I_DN_C
has the right values.
How to check them in PHP?
Assuming you're using Apache Httpd, you should be able to get access to the SSL environment variables using $_SERVER (for example $_SERVER['SSL_CLIENT_S_DN_CN']).
You'll also need to make sure your SSLOptions directive is configured accordingly for these variables to be used.

Check if PHP is running in local server

Well. I read some topics in SO but I not found a very specific answer.
I need to check with PHP if a PHP code is running in local or remote host. Currently I check with $_SERVER['SERVER_NAME'] but it is inconsistent. In this case, if I run PHP with listed IPs like 127.0.0.1 or localhost it'll consider local, otherwise remote. If I share my IP with a friend, my code still local, but it consider remote because the shared IP isn't listed.
Well, I think that check IP for localhost is not a good idea (except if you know a good method). I tried methods like gethostbyaddr() and gethostbyname() but don't work correctly too.
I don't have a PHP code to show, but my code is basically that:
// true = localhost
return $_SERVER['SERVER_NAME'] === '127.0.0.1';
The fundamental question is: what can determine that PHP is running local? What is "local" for PHP? I think that it can solve the problem.
Obs.: I don't have access to CMD/Shell with PHP.
You could do what most PHP frameworks do and set a flag during your app's bootstrap phase that defines which environment the code is running in. In it's simplest form:
// the setting when run on a dev machine
define('ENV', 'local');
Then it's a simple case of:
if ( ENV == 'local' )
{
// do stuff
}
This is how I do it, which I find more reliable than trying to detect for 127.0.0.1:
if( strpos(gethostname(), '.local') !== false ) { }
Basically, the hostname's on my workstations all have .local appended to it. You can change this to match your workstation's hostname entirely.
Check $_SERVER['REMOTE_ADDR']=='127.0.0.1'. This will only be true if running locally. Be aware that this means local to the server as well. So if you have any scripts running on the server which make requests to your PHP pages, they will satisfy this condition too.
If someone is visiting your site via the web, the IP address you see will never be 127.0.0.1 (or ::1 for IPV6), regardless of the usage of a proxy. (Unless of course you're running the proxy yourself on the same server ;)
As far as I know, only you will be able to know what addresses are local or not. Your network could be set up with IP addresses that don't look local at all. PHP cannot as far as I know determine this by itself.

Determine whether current script is running on development or production server

I've got scripts that call different URLs depending on if they're processed by my online site (release), or my offline localhost (development). I'd like to find a quick way to find which is which.
I can come up with a few clunky ways to do this, but is there a definitive, fast, elegant method? Something like if(is_offline()) { ... }
A variable called $_SERVER["COMPUTERNAME"] is available on IIS servers, you can use it to determine if the script is running on your development server or production server (MYMACHINE vs. WWW37).
You can also use $_SERVER["HTTP_HOST"] variable (localhost vs. www.domain.com).
You can also create an empty text file on your development server (careful not to upload it) and use is_file() to check if its presence (is_file(".foo") == true vs. false).
You can check for PHP_OS if the operating systems on the two servers are different (WINNT vs. Linux).
You can check for the presence of certain path inside the __FILE__ constant (C:/inetpub/wwwroot/website/ vs. /home/www37/).
A variant of 3: #include("override_server_with_local_config.php");
You can look at $_SERVER['HTTP_HOST'] to see what hostname the script is running under.
You can look at $_SERVER['REMOTE_ADDR'] to see if the user requesting the page's IP is 127.0.0.1.
You can ping something on your local network to see if you're connected to it.
You can define a constant at the start of your code which you set to 'release' or 'development' on the appropriate machine.
The best way is to set a configuration variable somewhere that indicates production or development.
You could do it by hostname (localhost vs www.foobar.com), but this is a wonky solution. You may access your app using different host names for testing as well. Therefore, explicit is better than implicit.
a couple of checkings could make it possible
define('IS_LOCAL', !(
in_array($_SERVER['HTTP_HOST'], array('localhost','127.0.0.1')) === false &&
$_SERVER['REMOTE_ADDR'] !== '127.0.0.1' &&
$_SERVER['REMOTE_ADDR'] !== '::1'
));
One function can Help get_headers('URL').
get_headers
Tt fetches all the headers sent by the server. Check returned array to check status of URL. First element of returned array contains URL status.

Is it possible that REMOTE_ADDR could be blank?

As far as I'm aware, the webserver (Apache/Nginx) provides the ($_SERVER['REMOTE_ADDR']) based on the claimed location of the requesting user agent. So I understand they can be lying, but is it possible that this value could be blank? Would the network interface or webserver even accept a request without a correctly formed IP?
http://php.net/manual/en/reserved.variables.server.php
It is theoretically possible, as the matter is up to the http server or at least the corresponding PHP SAPI.
In practice, I haven't encountered such a situation, except with the CLI SAPI.
EDIT: For Apache, it would seem this is always set, as ap_add_common_vars always adds it to the table that ends up being read by the Apache module PHP SAPI (disclaimer: I have very limited knowledge of Apache internals).
If using PHP in a CGI environment, the specification in RFC 3875 seems to guarantee the existence of this variable:
4.1.8. REMOTE_ADDR
The REMOTE_ADDR variable MUST be set to the network address of the
client sending the request to the server.
Yes. I currently see values of "unknown" in my logs of Apache-behind-Nginx, for what looks like a normal request/response sequence in the logs. I believe this is possible because mod_extract_forwarded is modifying the request to reset REMOTE_ADDR based on data in the X-Forwarded-For header. So, the original REMOTE_ADDR value was likely valid, but as part of passing through our reverse proxy and Apache, REMOTE_ADDR appears invalid by the time it arrives at the application.
If you have installed Perl's libwww-perl, you can test this situation like this (changing example.com to be your own domain or application):
HEAD -H 'X-Forwarded-For: ' -sSe http://www.example.com/
HEAD -H 'X-Forwarded-For: HIMOM' -sSe http://www.example.com/
HEAD -H 'X-Forwarded-For: <iframe src=http://example.com>' -sSe http://www.example.com/
( You can also use any other tool that allows you to handcraft HTTP requests with custom request headers. )
Now, go check your access logs to see what values they logged, and check your applications to see how they handled the bad input. `
Well, it's reserved but writable. I've seen badly written apps that were scribbling all over the superglobals - could the script be overwriting it, e.g. with $_SERVER['REMOTE_ADDR'] = '';?
Other than that, even if the request were proxied, there should be the address of the proxy - could it be some sort of internal-rewrite module messing with it (mod_rewrite allows internal redirects, not sure if it affects this)?
It shouldn't be blank, and nothing can't connect to your web service. Whatever's connecting must have an IP address to send and receive data. Whether that IP address can be trusted is a different matter.

Categories