socket_bind() unable to bind address - php

I'm trying to create a Web Socket Server for a small project I am working on.
I have set up the server (located at home) and have port forwarded 80 and 22. I read this tutorial: here
And whenever I ssh into my server to run "startDarmon.php" I get the following error:
PHP Warning: socket_bind(): unable to bind address [98]: Address already in use in
/var/www/server/socket.class.php on line 48
2013-02-23 14:15:38 System: Socket bound to localhost:8000.
2013-02-23 14:15:38 System: Start listening on Socket
This is what i think is preventing my client from connecting to the server. So in the startDarmon.php file I have:
$WebSocket = new socketWebSocket('MY_IP_NOT_LAN_IP',8000);
And inside my client file, I have:
var host = "ws://MY_IP_NOT_LAN:8000/server/startDaemon.php";
Does anyone have any suggestions to why this is not allowing me to establish a connection?

I'm guessing the issue is on the Linux server.
Run the netstat -a -p -n command under root (e.g. with sudo) to understand which process is using that port. Then perhaps do a setsockopt(2) with SO_REUSEADDR
(see socket(7) for more).
The TCP protocol has some specified delays in minutes (eg keepalive, etc etc...). See e.g. tcp(7)
I do suggest reading a good book on Linux system programming like Advanced Linux Programming and perhaps some material on network programming.

You can reuse an address using the setting below:
if ( ! socket_set_option($sock, SOL_SOCKET, SO_REUSEADDR, 1))
{
echo socket_strerror(socket_last_error($sock));
exit;
}

Another application is already using the port that you are trying to use.You can run
lsof -i:port_no
to make the port free.

Related

Lost UDP packages with PHP socket_sendto

I have a PHP CMS system, that's sending a UDP package to switch off a device on the local network.
$sock = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP);
if (!$sock) {
echo "COULD NOT CREATE SOCKET";
}
$result = socket_sendto($sock, "Ausgang1AUS", 11, 0, "192.168.20.49", 30303);
socket_close($sock);
if ($result) echo "UDP SENT ".$result." BYTES";
This has been working perfectly on our old (dedicated) linux server.
Now since switching to a new (virtual) linux server, these packages never reach their target.
I get no error in PHP (just my "UDP SENT 11 BYTES", but the packages just do not arrive anywhere in the local network.
It DOES work if I send the UDP to the server itself (using it's own IP).
It DOES work if I run this script on another machine in the local network.
It DOES work if I send UDP via netcat, e.g.
echo "Ausgang1AUS" | nc -u 192.168.20.49 30303. So it shouldn't be a general blocking problem.
Firewall and SELinux are both disabled on the machine.
Does anyone have an idea whats happening? Could it be some PHP setting or some user privilege? Is there any tool I could use to find out whats's happening to the UDP package?
I'm pretty lost at the moment...
Edit:
Seems to have nothing to do with php socket_sendto in the end, but connect to the LENGTH of the data sent. So #stark was right, using echo (thus introducing a newline) changed the length from 11 bytes to 12 bytes, and suddenly packages do arrive.
I posted a new question on SuperUser
Is this virtual Linux server running on a Windows VM? There was a recent Windows update that introduced a bug in hypervisor which is causing UDP packets under 12 bytes to fail checksum validation.
There's a Github issues here where other users are reporting the same issue on WSL2.
https://github.com/microsoft/WSL/issues/8610
You can see there's a workaround posted in that thread that might help in your situation, at least until Microsoft manage to fix the issue:
ethtool -K eth0 tx off

How to make "php -S" to work on local network?

In OS X Mavericks (and newer), start a PHP server from the command line:
cd to/your/directory
php -S localhost:8888
It works, but the server only available on that computer only. Is there a way to test it on other devices within the same LAN?
EDIT:
You will want to launch the server with the command
php -S 0.0.0.0:8888
This will allow you to access the server remotely (see docs http://php.net/manual/en/features.commandline.webserver.php)
After this is done there are 2 ways to view the site on your local network
http://192.168.1.2:8888 where 192.168.1.2 is the IP address of your computer which you can find in your System Preferences under Network.
http://myMac.local:8888 where myMac is your local computer name which you can find in your System Preferences under Sharing.
REMEMBER: Both of these options may require your firewall to allow incoming traffic to port 8888 (or whatever port your script is listening on), if you have that running.
Start with:
php -S 0.0.0.0:8888
otherwise you bind the server to localhost;

PHP Sockets on Linux - Free tcp port immediately after/when php exits via command?

I have a nginx server running a php script 24/7 that receives messages via sockets and stores them using mysql.
Sometimes I have to stop it running for a reason or another and I need a way to have it restart as soon as possible in order to avoid losing messages.
I use this script (.sh) to stop and run the process again:
pkill -f socketserver.php
#<Line that frees the tcp port>
/usr/bin/php /var/www/webroot/ROOT/socketserver.php #uses tcp port: 20491
If I don't use the command that frees the tcp port, I have (and will have) to wait something between 2 and 5 minutes until the OS perceives there is no process using that tcp port and frees/releases it.
Should I use: fuser, tcpkill, what?
I prefer things that are already installed on the ubuntu server 14.04
Thank you.
You cannot forcibly "free" a TCP port. To remove the obligatory wait time, the socket server should set the SO_REUSEADDR socket option when it creates the listening socket.
This way you'll still lose messages if the server is busy when you restart it. A better solution is doing what other people do: have a "master" process create and bind the listening socket, and delegate accepting connections and working on them to a child process. Most reasons you have for restarting, like reloading config, can be done by restarting the child only, while the listening socket stays open for connections.
Building on #Joni's answer, you'll want to use the socket_set_option() function before binding your socket (http://php.net/manual/en/function.socket-set-option.php - and yes, this code is shamelessly copy/pasted from that page):
if (!socket_set_option($socket, SOL_SOCKET, SO_REUSEADDR, 1)) {
echo 'Unable to set option on socket: '. socket_strerror(socket_last_error()) . PHP_EOL;
}
Once you use this, subsequent restarts of the script should work fine, without the need to manually free the socket.

PHP Client can't connect to RabbitMQ server on localhost

OS: CentOS 6.4
I am trying to connect to the RabitMQ server using the php client as follows,
$connection = new AMQPConnection('10.1.150.109', 5672, 'guest', 'guest');
$channel = $connection->channel();
But when I ran the script from the browser, it gives me this,
exception 'PhpAmqpLib\Exception\AMQPRuntimeException' with message 'Error Connecting to server(13): Permission denied ' in /var/www/html/event/vendor/videlalvaro/php-amqplib/PhpAmqpLib/Wire/IO/StreamIO.php:27
netstat show this,
tcp 0 0 :::5672 :::* LISTEN 10776/beam
In this post, this guy gives the answer implicitly, Client can't connect to RabbitMQ server on localhost. But he has not described the procedure which he followed to fix the issue.
I thank you in advanced for anyone who can help me in this regard.
Since I don't like the accepted answer, here's one I think is better.
Disabling SELinux is a hack. It may work but it's probably not a good idea. What isn't immediately obvious from the question (or the other question it references) is HOW the php client is being run. I.e. from the command line or via a browser.
SELinux by default won't allow httpd (i.e. apache) to connect to port 5672.
In my case, running the php script from the command line works - the connection is accepted. However, running it from a browser fails because of this SELinux policy.
I imagine that "reconfiguring the listen address from 0.0.0.0 to 127.0.0.1" is a reference to the hostname parameter, which in my case is set to "localhost" rather than an explicit IP address. (For sure 0.0.0.0 is going to fail!)
You can enable httpd to access port 5672 in SELinux: https://serverfault.com/questions/563872/selinux-allow-httpd-to-connect-to-a-specific-port
what happens if you
telnet 10.1.150.109 5672

PHP connect via SSH tunnel to LDAP in other network

I'm developing website for my school. In that school we authenticate users via LDAP, so there was an idea to do the same via school-site. On that site everything is working perfectly, but during developing I need very often to test if such solution works, of not. In order not to commit my changes so often I want to test this site on my local computer, but for connecting with LDAP i want to use ssh tunnel. In school network we have one server through witch we are connecting with inside of our school network. It's address is phoenix.lo5.bielsko.pl. Inside this network we have LDAP server with opened 389 and 636 ports. It's address is auth.lo5. I don't have access to auth.lo5 via SSH, I can only connect with it to get some LDAP entries. So, I've tried to run SSH tunnel by running:
ssh -L 636:auth.lo5:636 hfaua#phoenix.lo5.bielsko.pl
Then, I've set in my /etc/hosts that auth.lo5 is pointing to 127.0.0.1. I'm connecting to LDAP in PHP in such a way:
ldap_connect('ldaps://auth.lo5', 636);
But I'm getting error Can't contact LDAP server. I think, that problem might be on phoenix.lo5.bielsko.pl in its SSH daemon config or in arguments passed to ldap_connect() function. Can you tell me, what should I set in sshd_config or in arguments passed to ldap_connect to get it working?
I posted the same question in similar thread, but no one has answered my question.
P.S. In my /etc/ssh/sshd_config I have line AllowTcpForwarding yes
If I got it right phoenix.lo5 and auth.lo5 are 2 different machines.
If so you have to create a tunnel to the ssh machine, and then send the ldap queries to the right machine.
Your command: ssh -L 636:auth.lo5:636 hfaua#phoenix.lo5.bielsko.pl is right if phoenix.lo5.bielsko.pl can resolve auth.lo5 via DNS or /etc/hosts, if not you need to use its internal ip address.
Also if you want to use port 636 on your pc, you need to run your command as superuser (root or with sudo) else you need to use an high port (above 1024) as stated by Borealid
Once the tunnel is up you have to point to localhost to do the queries
I ran into this same issue. Running with -d1 showed me this error:
TLS: hostname (mylaptop.local) does not match common name in certificate (*.mydomain.com).
TLS reverse lookup of 'localhost' is 'mylaptop.local', checking if that matches the certificate common name
Could be you're hitting a similar problem.
I was able to fake it out by running:
sudo hostname someserver.mydomain.com
which caused SSL to assume it was talking to the right host.
I was also getting the error hostname (mylaptop.local) does not match common name in certificate (*.mydomain.com). However I did not want to edit the hostname of my machine to match that of the LDAP server. Instead I edited the hosts file (etc/hosts on linux) file to add a line that would intercept requests to the LDAP server eg:
127.0.0.1 ldap.server.com
This has the added benefit of not requiring you to change which server name you are trying to connect to in your code, you only need to change the port number if you chose a different port.
Try replacing all instances of auth.lo5 with localhost:
ssh -L 636:localhost:636 hfaua#phoenix.lo5.bielsko.pl
and
ldap_connect('ldaps://localhost', 636);
If that doesn't work, try turning off SSL to see if that works:
ssh -L 389:localhost:389 hfaua#phoenix.lo5.bielsko.pl
and
ldap_connect('localhost', 389);

Categories