How to do NAT with PHP sockets

2020-07-22 17:19发布

问题:

I'm trying to make a peer to peer app in php to work in the same kind of way skype works. It works with internal addresses, but when I try to send data to my external address the message never gets there. Obviously I'm missing some address translation, but I'm at a loss for how to do that with PHP sockets. Is it possible?

This is the code i have at the moment to receive the message, which I run first to wait for some message:

<?php
$socket = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP) or die("Could not create socket: " . socket_strerror(socket_last_error($socket)));
socket_bind($socket, "0.0.0.0", 100) or die("Could not bind socket: " . socket_strerror(socket_last_error($socket)));

$ret = "";
$from_ip = "";
$from_port = 0;


echo "waiting...\n";
socket_recvfrom($socket, $ret, 6, 0, $from_ip, $from_port);

var_dump($ret, $from_ip, $from_port);

socket_close($socket);

And then when its waiting, I run this code to send a message:

<?php
$socket = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP) or die("Could not create socket: " . socket_strerror(socket_last_error($socket)));


$to_ip = "externalip"; //works with internal "127.0.0.1";
$to_port = 100;
$message = "hello!";

socket_sendto($socket, $message, strlen($message), 0, $to_ip, $to_port);
echo "sent\n";

socket_close($socket);

But it sends and exits, but the first script is still waiting... Been at this for a while now, can anyone help me out?

-- Edit --

Ok so i've implemented a stun server and set up port forwarding for it like so:

<?php

echo "-- STUN SERVER --\n";

$socket = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP) or die("Could not create socket: " . socket_strerror(socket_last_error($socket)));
socket_bind($socket, "0.0.0.0", 5104) or die("Could not bind socket: " . socket_strerror(socket_last_error($socket)));


do {
    $ret = "";
    $from = "";
    $port = 0;

    echo "waiting...\n";
    socket_recvfrom($socket, $ret, 6, 0, $from, $port);

    echo "received: $ret\n";

    $message = $from.":".$port;
    socket_sendto($socket, $message, strlen($message), 0, $from, $port);
    echo "sent: $message\n\n";
}
while (true);

and changed my first script to get its ip/port from the stun server:

<?php
$socket = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP) or die("Could not create socket: " . socket_strerror(socket_last_error($socket)));
socket_bind($socket, "0.0.0.0", 100) or die("Could not bind socket: " . socket_strerror(socket_last_error($socket)));

$ret = "";
$from = "";
$port = 0;


echo "sending info to stun server...\n";
$to_ip = "stunip";
$to_port = 5104;
$message = "get_ip";
socket_sendto($socket, $message, strlen($message), 0, $to_ip, $to_port);

echo "waiting for stun...\n";
$stuninfo = "";
socket_recvfrom($socket, $stuninfo, 25, 0, $from, $port);

var_dump($stuninfo); // i use this info in my second script


echo "waiting...\n";
socket_recvfrom($socket, $ret, 6, 0, $from, $port);

var_dump($ret, $from, $port);

socket_close($socket);

It gets the info from the stun server ok and waits for another connection, but when i use that info in my second script, the first script still doesn't receive any message.. is there another step I'm missing?