Using fsockopen with UDP and proxy? - php

So I've been wondering (and testing), can I use fsockopen with proxy and UDP traffic?
Cause for example this:
$fp = fsockopen('udp://host.name.com', 512, $errno, $errstr);
if(!$fp){ die($errno . ' - ' . $errstr); }
works... but as soon as I add proxy
$proxy = "123.58.183.141 "; // proxy
$port = 1080; // proxy port
$fp = fsockopen("udp://".$proxy, $port, $errno, $errstr);
if(!$fp){ die($errno . ' - ' . $errstr); }
// after connecting to proxy... connect to target...
fputs($fp, "CONNECT host.name.com:512\r\n");
and try to send some data with fwrite read reply with fread I get nothing.
But without proxy everything works perfectly. I tried load of public proxies but I could never get reply...
Any thoughts on thisone? Also I'm starting to think "fputs($fp, "CONNECT host.name.com:512\r\n");" is not the right way for this... or is it?

Related

How to use fsockopen (or compatible) with SOCKS proxies in PHP?

I've coded a non-evil, non-spammy IRC bot in PHP, using fsockopen and related functions. It works. However, the problem is that I need to support proxies (preferably SOCKS5, but HTTP is also OK if that is somehow easier, which I doubt). This is not supported by fsockopen.
I've gone through all search results for "PHP fsockopen proxy" and related queries. I know of all the things that don't work, so please don't link to one of them.
The PHP manual page for fsockopen mentions the function stream_socket_client() as
similar but provides a richer set of options, including non-blocking connection and the ability to provide a stream context.
This sounded promising at first, supposedly allowing me to just replace the fsockopen call with stream_socket_client and specify a proxy, maybe via a "stream context"... but it doesn't. Or does it? I'm very confused by the manual.
Please note that it must be a PHP code solution; I cannot pay for "Proxifier" or use any other external software to "wrap around" this.
All the things I've tried seem to always result in me getting a bunch of empty output from the server, and then the socket is forcefully closed. Note that the proxy I'm trying with works when I use HexChat (a normal IRC client), with the same network, so it's not the proxies themselves that are at fault.
As far as I know there is no default option to set a SOCKS or HTTP proxy for fsockopen or stream_socket_client (we could create a context and set a proxy in HTTP options, but that doesn't apply to stream_socket_client). However we can establish a connection manually.
Connecting to HTTP proxies is quite simple:
The client connects to the proxy server and submits a CONNECT request.
The server responds 200 if the request is accepted.
The server then proxies all requests between the client and destination host.
<!- -!>
function connect_to_http_proxy($host, $port, $destination) {
$fp = fsockopen($host, $port, $errno, $errstr);
if ($errno == 0) {
$connect = "CONNECT $destination HTTP/1.1\r\n\r\n";
fwrite($fp, $connect);
$rsp = fread($fp, 1024);
if (preg_match('/^HTTP\/\d\.\d 200/', $rsp) == 1) {
return $fp;
}
echo "Request denied, $rsp\n";
return false;
}
echo "Connection failed, $errno, $errstr\n";
return false;
}
This function returns a file pointer resource if the connection is successful, else FALSE. We can use that resource to communicate with the destination host.
$proxy = "138.204.48.233";
$port = 8080;
$destination = "api.ipify.org:80";
$fp = connect_to_http_proxy($proxy, $port, $destination);
if ($fp) {
fwrite($fp, "GET /?format=json HTTP/1.1\r\nHost: $destination\r\n\r\n");
echo fread($fp, 1024);
fclose($fp);
}
The communication protocol for SOCKS5 proxies is a little more complex:
The client connects to the proxy server and sends (at least) three bytes: The first byte is the SOCKS version, the second is the number of authentication methods, the next byte(s) is the authentication method(s).
The server responds with two bytes, the SOCKS version and the selected authentication method.
The client requests a connection to the destination host. The request contains the SOCKS version, followed by the command (CONNECT in this case), followed by a null byte. The fourth byte specifies the address type, and is followed by the address and port.
The server finally sends ten bytes (or seven or twenty-two, depending on the destination address type). The second byte contains the status and it should be zero, if the request is successful.
The server proxies all requests.
<!- -!>
More details: SOCKS Protocol Version 5.
function connect_to_socks5_proxy($host, $port, $destination) {
$fp = fsockopen($host, $port, $errno, $errstr);
if ($errno == 0) {
fwrite($fp, "\05\01\00");
$rsp = fread($fp, 2);
if ($rsp === "\05\00" ) {
list($host, $port) = explode(":", $destination);
$host = gethostbyname($host); //not required if $host is an IP
$req = "\05\01\00\01" . inet_pton($host) . pack("n", $port);
fwrite($fp, $req);
$rsp = fread($fp, 10);
if ($rsp[1] === "\00") {
return $fp;
}
echo "Request denied, status: " . ord($rsp[1]) . "\n";
return false;
}
echo "Request denied\n";
return false;
}
echo "Connection failed, $errno, $errstr\n";
return false;
}
This function works the same way as connect_to_http_proxy. Although both functions are tested, it would be best to use a library; the code is provided mostly for educational purposes.
SSL support and authentication.
We can't create an SSL connection with fsockopen using the ssl:// or tls:// protocol, because that would attempt to create an SSL connection with the proxy server, not the destination host. But it is possible to enable SSL with stream_socket_enable_crypto and create a secure communication channel with the destination, after the connenection with the proxy server has been established. This requires to disable peer verification, which can be done with stream_socket_client using a custom context. Note that disabling peer verification may be a security issue.
For HTTP proxies we can add authentication with the Proxy-Authenticate header. The value of this header is the authentication type, followed by the username and password, base64 encoded (Basic Authentication).
For SOCKS5 proxies the authentication process is - again - more complex. It seems we have to change the authentication code fron 0x00 (NO AUTHENTICATION REQUIRED) to 0x02 (USERNAME/PASSWORD authentication). It is not clear to me how to create a request with the authentication values, so I can not provide an example.
function connect_to_http_proxy($host, $port, $destination, $creds=null) {
$context = stream_context_create(
['ssl'=> ['verify_peer'=> false, 'verify_peer_name'=> false]]
);
$soc = stream_socket_client(
"tcp://$host:$port", $errno, $errstr, 20,
STREAM_CLIENT_CONNECT, $context
);
if ($errno == 0) {
$auth = $creds ? "Proxy-Authorization: Basic ".base64_encode($creds)."\r\n": "";
$connect = "CONNECT $destination HTTP/1.1\r\n$auth\r\n";
fwrite($soc, $connect);
$rsp = fread($soc, 1024);
if (preg_match('/^HTTP\/\d\.\d 200/', $rsp) == 1) {
return $soc;
}
echo "Request denied, $rsp\n";
return false;
}
echo "Connection failed, $errno, $errstr\n";
return false;
}
$host = "proxy IP";
$port = "proxy port";
$destination = "chat.freenode.net:6697";
$credentials = "user:pass";
$soc = connect_to_http_proxy($host, $port, $destination, $credentials);
if ($soc) {
stream_socket_enable_crypto($soc, true, STREAM_CRYPTO_METHOD_ANY_CLIENT);
fwrite($soc,"USER test\nNICK test\n");
echo fread($soc, 1024);
fclose($soc);
}

PHP stream_socket_client not using proxy

I'm trying to get stream_socket_client working with proxy server.
Peace of code:
<?php
$context = stream_context_create(['http' => ['proxy' => '147.135.210.114:54566', 'request_fulluri' => true]]);
//$file = file_get_contents("http://www.google.com", false, $context);
$fp = stream_socket_client("tcp://www.google.com:80", $errno, $errstr, 30, STREAM_CLIENT_CONNECT, $context);
if (!$fp) {
echo "$errstr ($errno)<br />\n";
} else {
fputs($fp, "GET / HTTP/1.0\r\nHost: www.google.com\r\nAccept: */*\r\n\r\n");
while (!feof($fp)) {
echo fgets($fp, 1024);
}
fclose($fp);
}
?>
While file_get_contents uses proxy (tcpdump -i any -A host 114.ip-147-135-210.eu) stream_socket_client simply omits it and goes directly to google.com. What am I doing wrong? My final goal is to connect to RabbitMQ (AMQP protocol) via proxy, but I can't even get simple HTTP connection working.
if anyone came here struggling, I ended up solving this by connecting to the proxy first then issuing http headers to get the content I wanted.
First create the socket to the proxy:
$sock = stream_socket_client(
"tcp://$proxy:$port",
$errno,
$errstr,30,
STREAM_CLIENT_CONNECT,
stream_context_create()
);
Second connect to the destination host you want:
$write = "CONNECT www.example.org HTTP/1.1\r\n";
$write .= "Proxy-Authorization: Basic ".base64_encode("$proxy_user:$proxy_pass)."\r\n";
$write .= "\r\n";
fwrite($sock, $write);
This should return a 200 code:
preg_match('/^HTTP\/\d\.\d 200/', fread($sock, 1024));
Now you can just issue GET (make sure you send all the HTTP header):
fwrite($sock, "GET / HTTP/1.1\r\n")
This has more details: https://stackoverflow.com/a/55010581/687976

PHP fsockopen error, connection refused(111), try to connect fingerprint device using TCP/IP

i was want to connect to my fingerprint device useing TCP/IP
i was setting ip address in device,
my php code:
<?php
$fp = fsockopen("192.168.1.211", 80, $errno, $errstr, 30);
if (!$fp) {
echo "$errstr ($errno)<br />\n";
} else {
$out = "GET / HTTP/1.1\r\n";
$out .= "Host: www.example.com\r\n";
$out .= "Connection: Close\r\n\r\n";
fwrite($fp, $out);
while (!feof($fp)) {
echo fgets($fp, 128);
}
fclose($fp);
}
?>
when i try to connect, i get error connection refused . but ping to device is work, i don't know where is the problem,
My fingerprint device specification:
Vendor :Solution
type : x101-c
i hope somebody can help and solve my problem,,
i really stack now....
but ping to device is work
Ping uses ICMP packets not TCP. If you're getting a connection refused then the (TCP) port is firewalled.

PHP UDP fsockopen fread (RCON)

I want to get a message back after succesfully connected with an UDP address via fsockopen. Connection with a RCON ModManager (game server).
What to expect?
If I use Telnet:
Telnet 31.204.131.9 15502 , I see:
ModManager Rcon v8.5
Digest seed: iJrrQAkv
Now in PHP:
<?php
$_ip = '31.204.131.9' ;
$_port = '15502';
if (($socket = fsockopen ('udp://'.$_ip, $_port, $errno, $errstr, 30))) {
// till here it works, got connected
// Digest seed?
if(fwrite($socket, "GET / HTTP/1.1\r\n")) { // writing works }
echo fread($socket, 1024); // NOTHING
fclose($socket);
}
?>
You can try it.. IP and Port valid. Thnx in advance!!
When you use telnet you use tcp protocol, not udp. Try
<?php
$_ip = '31.204.131.9' ;
$_port = '15502';
if (($socket = fsockopen ($_ip, $_port, $errno, $errstr, 30))) {
// till here it works, got connected
// Digest seed?
if(fwrite($socket, "GET / HTTP/1.1\r\n")) { echo "writing works\n"; }
echo fread($socket, 1024); // NOTHING
fclose($socket);
}

Is there a way to specify the source UDP port using PHP?

I need to send a message via UDP to a remote equipment. I know that if I use the same UDP port that it used while sending information to the server to write back to it the messages goes through.
I am currently using:
$fp = fsockopen( $destination, $port, $errno, $errstr);
if (!$fp) {
echo "ERROR: $errno - $errstr\n";
} else {
fwrite($fp, $m);
fclose($fp);
}
But in this way I have no control of which port is going to be used as the source port.
In Java have one can use:
client = new DatagramSocket(21000);
Is there a way to do something similar using PHP.
You could do it by creating a normal udp socket with socket_create() and using socket_bind() to bind it to a specific port. Then use e.g. socket_sendto for specifying the endpoint and port to send it to. Example code follows.
A simple server that spits out the port number and ip address of client using socket_stream_server():
<?php
set_time_limit (20);
$socket = stream_socket_server("udp://127.0.0.1:50000",
$errno, $errstr,
STREAM_SERVER_BIND);
if (!$socket) {
die("$errstr ($errno)");
}
do {
$packet = stream_socket_recvfrom($socket, 1, 0, $peer);
echo "$peer\n";
stream_socket_sendto($socket, date("D M j H:i:s Y\r\n"), 0, $peer);
} while ($packet !== false);
?>
and the client is like this:
<?php
$address = '127.0.0.1';
$port = 50001;
$dest_address = '127.0.0.1';
$dest_port = 50000;
$sock = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP);
if (socket_bind($sock, $address, $port) === false) {
echo "socket_bind() failed:" . socket_strerror(socket_last_error($sock)) . "\n";
}
$msg = "Ping !";
socket_sendto($sock, $msg, strlen($msg), 0, $dest_address, $dest_port);
socket_close($sock);
?>
Running the server (on the command line) gives this output when running the client multiple times:
<knuthaug#spider php>php server.php
127.0.0.1:50001
127.0.0.1:50001
127.0.0.1:50001
^C
<knuthaug#spider php>

Categories