Skip to content

Instantly share code, notes, and snippets.

@0x15f
Last active March 24, 2019 08:17
Show Gist options
  • Save 0x15f/4795c19fbbde46062c90ca14e1e5e230 to your computer and use it in GitHub Desktop.
Save 0x15f/4795c19fbbde46062c90ca14e1e5e230 to your computer and use it in GitHub Desktop.
<?php
class UDPProxy extends \Threaded {
// private static $ENCRYPT_KEY = 'jsd8hv8QWCH';
/**@var stream*/
public $socket;
/**@var stream*/
public $sql;
/**@var array*/
public $clients = [];
/**@var array*/
public $threads = [];
/**@var array*/
public $lastPacket = [];
/**@var bool*/
public $shouldStop = false;
/**@var int*/
public $threadCount = 5;
public function __construct(string $address, int $port, string $db_address, string $db_user, string $db_password, string $db_name, int $threadCount = 5, int $timeout = 2) {
$socket = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP);
if(@socket_bind($socket, $address, $port)) {
socket_set_option($socket, SOL_SOCKET, SO_REUSEADDR, 0);
@socket_set_option($socket, SOL_SOCKET, SO_SNDBUF, 1024 * 1024 * 8);
@socket_set_option($socket, SOL_SOCKET, SO_RCVBUF, 1024 * 1024 * 8);
/*$sql = mysqli_connect('p' . $db_address, $db_user, $db_password, $db_name);
if(!$sql) {
echo mysqli_connect_error($sql) . PHP_EOL;
exit;
}*/
@socket_set_nonblock($socket);
@socket_set_timeout($socket, $timeout);
// $this->sql = $sql;
$this->socket = $socket;
$this->threadCount = $threadCount;
for($i = 0; $i < $threadCount; $i++) {
$this->threads[$i] = (new UDPThread($this, $i));
}
}
else {
echo trim(socket_strerror(socket_last_error($socket))) . PHP_EOL;
exit;
}
}
public function start() {
foreach($this->threads as $contents) {
$contents->start();
}
}
public function process() {
if(!$this->shouldStop) {
socket_recvfrom($this->socket, $buffer, 65536, 0, $address, $port);
if(is_null($buffer)) {
return;
}
$identifier = hash('sha1', strval($address . $port));
if(!isset($this->clients[$identifier])) {
$contents = new \Threaded;
$threadIndex = null;
while(!isset($this->threads[$threadIndex])) {
$threadIndex = mt_rand(0, $this->threadCount);
}
$contents->client_addr = $address;
$contents->client_port = $port;
$contents->client_socket = socket_create(AF_INET, SOCK_DGRAM, 0);
$contents->forward_addr = '66.70.171.222'; // play.cosmicpe.me
$contents->forward_port = 19132;
$contents->last_packet = time();
$contents->thread_index = $threadIndex;
// $contents['send_server_queue'] = [];
// $contents['send_client_queue'] = [];
$socket = $contents->client_socket;
socket_sendto($socket, $buffer, strlen($buffer), 0, $contents->forward_addr, $contents->forward_port);
$this->clients[$identifier] = $contents;
$this->threads[$threadIndex]->addClient($identifier, $contents);
echo "Adding client for ('{$address}', {$port})" . PHP_EOL;
}
else {
$client = $this->clients[$identifier];
$this->lastPacket[$identifier] = time();
socket_sendto($client->client_socket, $buffer, strlen($buffer), 0, $client->forward_addr, $client->forward_port);
}
}
else {
exit; // todo: handle shutdown better
}
}
}
class UDPThread extends \Thread {
/**@var UDPProxy*/
private $proxy;
/**@var int*/
private $threadIndex;
/**@var array*/
private $clients = [];
public function __construct(UDPProxy $proxy, int $threadIndex) {
$this->proxy = $proxy;
$this->threadIndex = $threadIndex;
}
public function addClient(string $identifier, \Threaded $contents) {
$this->clients[$identifier] = $contents;
}
public function run() {
while(!$this->proxy->shouldStop) {
foreach($this->clients as $identifier => $contents) {
if($this->proxy->lastPacket[$identifier] - strtotime('-5 seconds') > 5) {
unset($this->clients[$identifier]);
unset($this->proxy->clients[$identifier]);
continue;
}
socket_recvfrom($contents->client_socket, $buffer, 65536, 0, $server_address, $server_port);
if(is_null($buffer)) {
continue;
}
if($server_address !== $contents->forward_addr or $server_port !== $contents->forward_port) {
continue;
}
socket_sendto($this->proxy->socket, $buffer, strlen($buffer), 0, $contents->client_addr, $contents->client_port);
}
}
}
}
$proxy = new UDPProxy('0.0.0.0', 26625, "", "", "", "");
$proxy->start();
while(true) {
$proxy->process();
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment