Check if a server is online - php

I'm currently implementing LDAP Authentication. I cache the credentials as a fallback in case the LDAP server is offline. As part of this caching I need to check if my LDAP server is online. Rather than using PHP's Ldap methods it would be better to use something simple like a ping.
Please note that it should be able to handle any protocols. E.g., I can't use fsockopen because it does not support ldaps://. [I know that I could register my own protocol wrappers].
I want this check to be generic and simple.

I'm using fsockopen for exactly that purpose. It doesn't matter whether it supports ldaps or not I figured out, because there are two possibilities in the end:
The appropriate port is open, so I can assume that the LDAP-Server is up and running or
The appropriate port is not open, so I can assume that the LDAP-Server is not running.
You can check that like this:
$fp = #fsockopen($host, $port, $errno, $errstr, 30);
if (! $fp) {
// Port is unavailable
}
fclose($fp);
Now you know, the port to connect to is open and I can fire up LDAP.
I've found two edge-cases that you won't be able to check for using this method though
The LDAP-Server is in an undefined state and has the port still open but is not responding or
Some other application has opened the port.
You can check that though by using
$con = ldap_connect($ldapURI);
if (! ldap_bind($con, $user, $password)) {
// Something is fishy
}
Fishy might be invalid credentials (which should not happen at this first bind, right?) or the server listening on that port is not responding in a manner that we expect. So it's either not an LDAP-Server or the server is in an undefined state.
To fail fast, you should adapt the timeouts appropriately so you're not waiting half a minute just to know that something went wrong.
YOu can set the timeout for fsockopen using the fifth parameter and you can set the timeouts for LDAP using
ldap_set_option($con, LDAP_OPT_NETWORK_TIMEOUT, [whatever is appropriate]);
ldap_set_option($con, LDAP_OPT_TIMEOUT, [whatever is appropriate]);
ldap_set_option($con, LDAP_OPT_TIMELIMIT, [whatever is appropriate]);
// Only available when your LDAP-extension is compiled against the Netscape LDAP C-SDK
ldap_set_option($con, LDAP_X_OPT_CONNECT_TIMEOUT, [whatever is appropriate]);
You'll need to set them after ldap_connect but before ldap_bind.
LDAP_OPT_TIMEOUT and LDAP_X_OPT_CONNECT_TIMEOUT are not (yet) documented on php.net though!
For more infos on these constants have a look at https://linux.die.net/man/3/ldap_set_option but beware that not all the constants mentioned there are implemented in the PHP-LDAP-Extension.

Related

socket_accept seems to hang on the first connection

I'm trying to make a simple listener on port 8195. When I try the following code block in PHP CLI conditions, it only shows 'Test' once, then hangs. If I delete the file 'votifier.run', the file designed to be the on/off switch, it still continues to hang. It never shows 'Client connected'.
Furthermore, if I try to connect to the host via Telnet on port 8195 while the script is running, I simply get a connection failed message. It's like it's looking for one connection and just not giving up.
// Set the IP and port to listen to
$address = 'localhost';
$port = 8195;
// Create a TCP Stream socket
$sock = socket_create(AF_INET, SOCK_STREAM, 0);
// Bind the socket to an address/port
socket_bind($sock, $address, $port);
// Start listening for connections
socket_listen($sock);
// Loop continuously
while ( file_exists('votifier.run') ) {
echo 'Test';
$client = socket_accept($sock);
if( $client ) {
echo 'Client connected';
// Don't hang on slow connections
socket_set_timeout($client, 5);
// Send them our version
socket_write("VOTIFIER MCWEBLINK\n");
// Read the 256 byte block
$block = socket_read($client, 256);
...
The answer:
socket_accept() will usually hang until a connection is made. If a connection attempt was made, the script would continue, but because the socket was being created on localhost, it would only accept connections to it from localhost.
The fix is to use your external IP rather than 'localhost' or '127.0.0.1'. Then you can Telnet to it.
I'm just guessing here, but could it be that the address you are trying to bind to should not be a hostname?
If the socket is of the AF_INET family, the address is an IP in dotted-quad notation (e.g. 127.0.0.1).
EDIT
Ok, I've taken your script and tried to reproduce your error but couldn't. There are a couple of flaws in it but none that would cause a telnet client's connection attempt to fail.
Since none of the aforementioned applies, let's go thru the checklist one by one:
sockets module loaded/compiled
localhost does resolve to 127.0.0.1
the port isn't taken by any other application running
there's no rule of any sort of firewall that would prevent communication between the telnet client and your server
the machine which you connect from is allowed to connect to the server host (try the same host if it isn't)
the file that's being checked in the while-loop does exist
you are sure that there isn't another fatal error within your script that would prevent the snippet you posted from running
These are all the possible error sources I can think of, atm. Try fixing up the minor flaws first, then go thru the checklist.
if( $client ) {
echo 'Client connected';
// Don't hang on slow connections
socket_set_option(
$client,
SOL_SOCKET,
SO_RCVTIMEO | SO_SNDTIMEO,
array('sec' => 5, 'usec' => 0)
);
// Send them our version
socket_write($client, "VOTIFIER MCWEBLINK\n");
^^^^^^^
// Read the 256 byte block
$block = socket_read($client, 256);
You should be using threads. If the client never sends anything your code will block in the read() method. Each accepted socket should be completely handled in a new thread.
You may want to check this:
PHP Votifier example for Minecraft Topsites
It explains how the code works, it's the basic function that makes the encryption, fills up the 256 blank spaces and sends the packet too. You can work a little with it as you may want to improve it.
You can see a live demo of the running php for the plugin here: http://topg.org/test_votifier

PHP cannot connect to LDAP Oracle Directory Server Enterprise Edition

Been playing with this for days and can not get php to bind to ldap on Oracle's DSEE.
function test(){
// LDAP variables
$ldaphost = "xxx.xxxxx.com";
$ldapport = 636;
$ldaprdn = 'cn=xyxyxyxy,ou=Accounts,dc=xxx,dc=xxxxx,dc=com';
$ldappass = 'vcvcvcvcvc';
ldap_set_option(NULL, LDAP_OPT_DEBUG_LEVEL, 7); // isn't helping
// Connecting to LDAP
$ldapconn = ldap_connect($ldaphost, $ldapport)
or die("Could not connect to $ldaphost");
if ($ldapconn) {
// binding to ldap server
$ldapbind = ldap_bind($ldapconn, $ldaprdn, $ldappass);
// verify binding
if ($ldapbind) {
echo "LDAP bind successful...";
} else {
echo "LDAP bind failed...";
}
}
}
I get the error:
Message: ldap_bind() [function.ldap-bind]: Unable to bind to server: Can't contact LDAP server
Tearing my hair out on this one. I just can't get the thing to bind.
Have tried a straight telnet to the host on port 636 and am not being blocked by any firewall. Peculiarly I am not getting any extra debug info from the 'LDAP_OPT_DEBUG_LEVEL' on screen or in my logs.
start_tls() and ldaps is mutually exclusive, meaning you cannot issue start_tls() on the ssl port (standard 636), or initiate ldaps on an unecrypted port (standard 389). The start_tls() command initiate a secure connection on the unencrypted port after connection is initiated, so you would then issue this before the bind takes place to make it encrypted. Another set of common ports is 3268 (unecrypted) and 3269 (ssl) which might be enabled in your server.
ldap_set_option(NULL, LDAP_OPT_DEBUG_LEVEL, 7);
is logging to your web servers error log, depending on your log level, or to stout (from PHP CLI). To gain more information here, check your web server log level setting, or simply run your php script from command line.
To successfully use the ssl port, you need to specify the ldaps:// prefix, while on the unencrypted port this is not necessary (with a ldap:// prefix).
Looking at your code, this could be a protocol version issue as PHP by default use version 2. To solve this, you can issue:
ldap_set_option($conn, LDAP_OPT_PROTOCOL_VERSION,3);
ldap_set_option($conn, LDAP_OPT_REFERRALS,0);
before you attempt to bind.
You can also have a look at the code in Problems with secure bind to Active Directory using PHP which I successfully use in CentOS 5, but is having problems in Ubuntu. If your server has an open unencrypted port, it's a good idea to do an unencrypted test bind against it to rule out any connectivity issues.
To check if the port is open, you can check if telnet connects to it, E.G:
telnet my.server.com 3268
If the port is open, then you should be able to bind using it.
*Edit: If the ssl certificate is deemed invalid, the connection will fail, if this is the case, setting the debug level to 7 would announce this. To get around this specific problem you need to ignore the validity:
You can ignore the validity in windows by issuing
putenv('LDAPTLS_REQCERT=never');
in your php code. In *nix you need to edit your /etc/ldap.conf to contain
TLS_REQCERT never
The port 636 is the SSL enabled port and requires an SSL enabled connection.
You should try to connect on port 389, or change your code to include the secure layer (much more complex).
Kind regards,
Ludovic
To connect using SSL you should try
$ldapconn = ldap_connect('ldaps://'.$ldaphost);
This will automatically connect on port 636 which is the default ldaps-port. Depending on your server installation and configuration it may be possible that connections are only allowed on port 389 (using no encryption or using TLS) or only on port 636 using SSL-encryption. Although it might be possible that your server exposes other ports. So in general you need to know which port you're gonna connect to and which encryption method the server requires (no encryption, SSL or TLS).
Is the certificate of the LDAP server signed by a valid CA? Maybe your client just rejects the certificate!

PHP LDAP not working securely

I am trying to get a LDAPs client in PHP working. My code is in place, and it works using the standard LDAP protocol.
However, when I change ldap://server to ldaps://server, it doesn't work. Setting the debug mode to 7 yields this error. I should add that this a linux server using openSSL.
TLS: can't connect: The Diffie Hellman prime sent by the server is not acceptable (not long enough)..
Is there any way to get past this? Changing anything on the LDAP server is not an option as I only have client privileges on it.
EDIT: Only setting in my LDAP.conf is
TLS_REQCERT never
EDIT2: Here is my code
if(isset($_POST['pass'])){
$username = $_POST['user'];
$password = $_POST['pass'];
ldap_set_option(NULL, LDAP_OPT_DEBUG_LEVEL, 7);
$ds=ldap_connect("ldaps://server.com");
ldap_set_option($ds, LDAP_OPT_REFERRALS, 0);
ldap_set_option($ds, LDAP_OPT_PROTOCOL_VERSION, 3) ;
//Check LDAP server for user
if(!#ldap_bind($ds, "uid={$username},ou=people,o=site.ca,o=site", "{$password}") || strlen($password)==0){
// LDAP login was not successful
printf("Sorry, wrong username/password\n\n\n");
return;
}
$ldapSearch=#ldap_search($ds, "ou=people,o=site.ca,o=site", "uid={$_POST['user']}");
$result = #ldap_get_entries($ds, $ldapSearch);
}
This could be due to a bug in your version of libgnutls
http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=440344
First of all, this is for Ryerson? Come on! (I used to work at York U! Gotta tease the guys downtown a little. Could be worse, you could be at U of T!). But seriously, depending on your LDAP server at the backend, there are two usual approaches.
ldaps://ldap.ryerson.ca:636 might work better, in that it will try and do an SSL bind, expecting you have trusted the public key of the CA that signed the certificate in use for SSL.
TLS is really SSL V3.1 and one of the very nice features it adds is that it works fine on port 389 as well, but can issue a StartTLS command which takes a clear text connection you started on 389 and enables encryption.
My suspicion is that from the error code it is trying to make an LDAP over SSL on the clear text port which will fail.

Connection to secure FTP Server from PHP

This question is in line with this question, I am trying to connect to secure FTP Server and it is not able to connect, wierd part is that I am able to do ssh and connect to the server but when I try to do it from php code using few different approaches but it is not working
Approaches:
FTP Wrappers
ftp_connect & ftp_login
ftp_ssl_connect
ssh2_sftp
ssh2-scp-send & ssh2-scp-receive -- Have not tried this approach yet but recommended in comments portion and so would work on this and will post updates later.
Code for Approach 1:
$ftp_server = "ftp://username:password#192.168.1.1:21/{$log_file_name}";
$opts = array('ftp' => array('overwrite' => TRUE));
$context = stream_context_create($opts);
$put_file = file_put_contents($ftp_server, $response, LOCK_EX,$context);
Here also am not able to connect to secure FTP Server, any suggestions as to why it is not able to connect ?
Code for Approach 2:
ftp_server = 'www.server.com';
$conn_id = ftp_connect($ftp_server) or die ("Cannot connect to host");
//Program dies out here and give error message "Cannot connect to host",
//but why ftp_login does not work here, Any Suggestions ?
$ftp_user_name = "login";
$ftp_user_pass = "password";
// login with username and password
$login_result = ftp_login($conn_id, $ftp_user_name, $ftp_user_pass);
// check connection and login result
if ((!$conn_id) || (!$login_result))
{ echo "FTP connection has encountered an error!";
echo "Attempted to connect to $ftp_server for user $ftp_user_name....";
//exit;
} else
{
echo "Connected to $ftp_server, for user $ftp_user_name".".....";
}
Code for Approach 3:
Here am using same code as approach 1 but instead of ftp_connect, am using ftp_ssl_connect
Code for Approach 4:
$connection = ssh2_connect('www.server.com', 22);
ssh2_auth_password($connection, 'login', 'password');
$sftp = ssh2_sftp($connection);
//exit();
$stream = fopen("ssh2.sftp://$sftp/path/to/file", 'r');
Can anyone advise why am I not able to connect to secure FTP Server using above approaches but still am able to do so using ssh ?
Are there any other approaches to connect to secure FTP Server using php ?
UPDATE:
Q1. I tried again using ftp_connect but it just died out and why does it dies out, what are the scenarios in which ftp_connect dies out ?
Q2. Do we have only this approaches to connect to the server or are there any other which we can implement ?
Q3. Is this php language related that it does not support secure FTP Connection ? OR there is any other way of doing this using php, if yes than do provide different approaches as it would be very helpful.
UPDATE 1:
I was trying to google more on the issue and it seems that if ftp_connect does not work than firewall could be one of the reason for it. I am not totally sure if that is the case but I am researching more on it and post an update in here if I find anything useful.
Possible Solution :
Problem
If I remove the "or die" then you get the error:
When running from a webpage:
Warning: ftp_login() expects parameter 1 to be resource, boolean given in /var/www/ftp_test.php on line 28
var_dump($conn_id); returns bool(false).
From command line /usr/bin/php /var/www/ftp_test.php
var_dump($conn_id); returns resource(4) of type (FTP Buffer).
Script completes.
Solution 1
This could be one solution :
Try to turn off selinux and here is the way or Search : How to disable selinux for turning it off temporarily or permanently.
Solution 2
If you don't want to turn off selinux completely, you might get what you need by just setting the httpd_can_network_connect using the setsebool command.
Verify that it was previously set to "off":
getsebool httpd_can_network_connect
Set it to "on":
setsebool httpd_can_network_connect=1
Turn selinux back on:
setenforce 1
Check to be sure php ftp_connect still works when running under httpd.
Set the policy (-P) to "on" so it persists over a reboot:
setsebool -P httpd_can_network_connect=1
Solution 3
There could also be issue with company firewall. Make sure it is configured properly and has access rights set properly.
Solution 4
Another approach is to use cURL : libcurl as it can be used to connect and communicate to many different types of servers with many different types of protocols
Solution 5
There is open source project called PHP Secure Communication Library (phpspeclib) which can be also used to establish secure connection to FTP Server.
Many cheap webhoster will not give you ssh (hence no ftp via ssh aka
sftp) but only ssl-secured ftp aka ftps (see here). You might
have that problem. As others suggested, use filezilla or
another ftp client to test your credits and chosen security method
beforehand.
ftp_ssl_connect() at least under windows will be a long journey,
since you have to compile your own php binaries, see here.
As this php contributor rightfully points out, no secure
connection is secure, as long as you don't know, who you are talking
too, aka „peer certification“ through valid certificates.
phpseclib is probably your best bet. But I haven't figure out, how to
ensure, it uses peer verification (guessing, the truth is in
openssl.conf ...)
So even at the time of writing, I wonder more than ever, if
peer-validated ftps (ftp with ssl/tls authentification) is possible... also see my question here.
As for ´ftp via ssh´ alias ´sftp´: No direct advice, but note, that many cheap 'non-dedicated server' webhosts do not support it (which is bad). Company firewalls might block the relevant ports.
As for 'ftp using ssl/tls' alias 'ftps': Your answer is here. Don't waste time on ftp_ssl_connect() :-)
(Yes, it's poorly documented on the php site, to say the least)
This page has what you seek (I think)
http://kevin.vanzonneveld.net/techblog/article/make_ssh_connections_with_php/
and here are the manual pages
http://php.net/manual/en/book.ssh2.php
I, too, encountered quite a lot of issues when dealing with encrypted connections.
First thing is to check the protocol you are looking to use. Secure FTP is most commonly refearing to FTP over SHH but can also mean SCP, SFTP or FTPS.
One way to figure out is to check connecting using a client like filezilla.
If the protocol is handled via a PHP module, the best approach is indeed, to use it. In this case, you need to make sure that, in addition to the protocol-related one, the OPENSSL module is installed for php.
There are some cases where the module support still won't work. In this case, using the libcurl module is one option. This is the case for instance when you need to use a client certificate.
Unfortunately, here again, you may encounter some problems due to the partial support of libcurl in the php module. One scenario I experimented is when the server certificate is judged invalid by the module.
The last solution I usually use is to run the curl binary from an exec statement, for the later case using the "-k" switch.
I tried the phpseclib library and it works in Windows and Linux.
If you are using composer, just add in your require section :
"phpseclib/phpseclib": "0.3.*#dev"
And then, you can do this : http://phpseclib.sourceforge.net/sftp/examples.html#put

Port checking from php

I'm trying to connect to gmail pop server from a phplist installation and it fails, but i'm not sure whether my webhost opened port 995 or not. They say they have opened it, but i'm in doubt. Is there a way i can check it from a php script? They are running php 5.2.0 on a windows server, though i'm not sure what OS is that. phpinfo() says "Windows NT DEDI514 5.2 build 3790"
You can put code in a php script to open a connection to a specific hostname (or IP address) and port.
If you know the expected response, you should be able to tell if you are getting a connection. If you get something like "Connection refused", then either you are being blocked, or the destination host is not accepting connections on that port.
This example uses IP address 192.0.2.0 and port 995. Replace these with whatever you want to test.
<?php
echo "\nOpening connection\n\n";
$fp = fsockopen("192.0.2.0", 995, $errno, $errstr);
if (!$fp) {
echo "ERROR: $errno - $errstr\n";
} else {
echo fread($fp, 1024);
fclose($fp);
}
?>
You can also send data to the server using
fwrite($fp, "blah blah blah\r\n");
There is more information about fsockopen here.
I think you'll need to ping or traceroute to a machine that will respond on that port.
This article should have much more than you want to know, but there's an example script at the bottom that you can modify to test.
http://www.planet-source-code.com/vb/scripts/ShowCode.asp?lngWId=8&txtCodeId=1786
There are some other scripts here:
http://www.theworldsend.net/
I can't vouch for any of these personally, but they look like what you need.
And, of course, if you can ssh or telnet into your server, you can do all this much more easily using the ping and traceroute commands.
Maybe safe mode is active? This prevents calling services on other servers.
Edit:
All filesystem and stream functions are affected by the safe mode settings!
The open_basedir setting affects fopen()!

Categories