php HTTP tunnel to IMAP/POP3 using SSL - php

My code should check email boxes via proxy with PHP using SSL.
Zend\Mail package provides implementation of both protocols without php extention and fits fine.
I partially override connect() method by code:
$this->socket = fsockopen($proxy, $proxy_port, $errno, $errstr, self::TIMEOUT_CONNECTION);
$this->sendRequest("CONNECT {$host}:{$port} HTTP/1.1");
$this->sendRequest("Host: {$host}:{$port}");
$this->sendRequest($userAgent);
$this->sendRequest("Proxy-Authorization: basic " . base64_encode("$user:$pass") . "\r\n");
// Remove 2 lines with proxy response
fgets($this->socket);
fgets($this->socket);
With unsecure connection everything works fine, but not works for secured port.
Connections on 110 port rejected by server with "please use SSL/TLS", when script tries to connect on secure port 995, nothing happend, no any response from mail server.
Probably, I missed one more HTTP header or so.
Anybody knows which command need send to end server through HTTP tunnel to start SSL connection?

Related

FTPS with CURL PHP

I'm busy with a curl php library which needs to connect to an FTPS server.
I have this semi working... If I connect to ftp://domain.com then it does work. If I watch the comms on the server with tcpflow I see it logging in with AUTH TLS and and all the comms is encrypted. The file is uploaded so all's good..
What I'm unsure of is if its valid to try connecting instead to ftps://domain.com?
The reason I'm asking is because if I change the protocol from ftp to ftps in curl then the login fails and the server (watching tcpflow comms) says that the login has failed:
191.101.002.204.00021-088.099.012.154.51630: 530 Please login with USER and PASS.
Also, when I watch the comms when trying to connect to ftps:// I don't see the client issuing the AUTH TLS command as it does with plain ftp://
The problem I have is that it seems that my client's FTP server we have to ultimately connect to doesn't seem to allow connections without the ftps:// protocol.
If I connect using lftp I can do so using ftps:// but then I have to disable ssl:
set ftp://ssl-allow no
If I try the lftp connection using ftp:// it just hangs on the login command...
I'm not really that experienced with FTP or TLS / SSL so I don't know if its maybe because the client's server doesn't have the certificates set up correctly..
Here is a portion of my curl code which works with ftp:// but not ftps://
// Works
$url = "ftp://proxy.plettretreat.co.za/";
// Does not work
$url = "ftps://proxy.plettretreat.co.za/";
$port = 990;
$username = "ftpuser";
$password = "pass";
$filename = "/test.php";
$file = dirname(__FILE__)."/test.php";
$c = curl_init();
// check for successful connection
if ( ! $c)
throw new Exception( 'Could not initialize cURL.' );
$options = array(
CURLOPT_USERPWD => $username.':'.$password,
CURLOPT_SSL_VERIFYPEER => 0,
CURLOPT_SSL_VERIFYHOST => 0,
CURLOPT_RETURNTRANSFER => 1,
CURLOPT_BINARYTRANSFER => 1,
CURLOPT_FTP_SSL => CURLFTPSSL_ALL, // require SSL For both control and data connections
CURLOPT_FTPSSLAUTH => CURLFTPAUTH_TLS, // let cURL choose the FTP authentication method (either SSL or TLS)
CURLOPT_UPLOAD => true,
CURLOPT_PORT => $port,
CURLOPT_TIMEOUT => 30,
);
Another thing I'm unsure of is that my client has given me an IP address to connect to.. Can an IP address be used in ftps? I would have thought that certificates are mostly certifying a domain name?
tl;dr
1) Can I use ftps://domain.com to connect using CURL PHP?
2) If I can use ftps:// in curl, then how do I get curl to log in (issue auth tls command)?
3) Can an FTP server use SSL / TLS with only an IP address?
Thanks...
John
Many many hours of struggling led me to an eventual answer.
Part of the answer was that the client server and the FTP server had "overly" strict firewall rules blocking the passive ports.
I was getting the following error:
Error no: 35; Error: SSL connect error.
Error 35 was because of the firewall rules. Once those were relaxed that error went away, but as a note, you will also see this error if the client machine is NAT'ed. If it is you need to set the curl option:
curl_setopt($c, CURLOPT_FTPPORT, '1.2.4.5' ); // change to your actual IP.
This tells the FTP server where to open up its data channel (instead of trying to open it to the client server's internal address).
Anyway, once the firewall and FTPPORT options were set I got:
Error no: 30; Error: bind(port=0) failed: Cannot assign requested address
This one baffled me for quite a while as everything looked correct.
I eventually stumbled upon a few thread here and elsewhere which talk about an issue with older versions of Curl using NSS for its encryption. I checked and I was using libcurl version 7.19.7 (about 8 years old) and sure enough it uses NSS...
I updated my Curl using this guide: https://www.digitalocean.com/community/questions/how-to-upgrade-curl-in-centos6.
That updated me to libcurl 7.52.1 which uses OpenSSL and lo and behold, my app started working...
So, if you're having issues connecting curl-ftp to a FTPS server, check the FTPPORT (passive IP) if you're NAT'ed, check your firewall, but most importantly, check your curl:
<?php
print print_r(curl_version());
?>
I hope this helps someone..

Send request to 127.0.0.1 via HTTP which is forwarded on via HTTPS

I am using WampServer (Windows) and PHP pgsql, and apparently something wasn't compiled with SSL support, because I get this error:
Unable to connect to PostgreSQL server: sslmode value "require" invalid when SSL support is not compiled
This got me thinking... I wonder if I can ask pg_connect() to look for 127.0.0.1 on port 12345 (or something like that) using HTTP, and then some middle service could be run on my local system that would pass that on to the server using SSL.
Does anyone know how to do that?
NOTE
I'm trying to connect to the Heroku PostgreSQL server (which uses an Amazon Web Service URL) and requires an SSL connection. I had better luck Googling "amazonws.com postgresql stunnel" for relevant bulletin board messages.
UPDATE
Here is the stunnel.conf file that I used:
;See: https://medium.com/what-i-learned-building/580fdd492119
cert = stunnel.pem
options = NO_SSLv2
options = SINGLE_ECDH_USE
options = SINGLE_DH_USE
socket = r:TCP_NODELAY=1
options = NO_SSLv3
ciphers = HIGH:!ADH:!AECDH:!LOW:!EXP:!MD5:!3DES:!SRP:!PSK:#STRENGTH
[heroku-postgres]
client=yes
accept = 127.0.0.1:YOUR-CHOSEN-PORT
connect = THE-HOST-GOES-HERE:PORT
protocol=pgsql
retry = yes
Reference: https://medium.com/what-i-learned-building/580fdd492119
postgresql does neither use http nor https for its connection, but has its own protocol. But you could use something like stunnel to tunnel a normal tcp connection inside ssl, e.g. if your local pg_client library is not ssl-aware you could create an stunnel on localhost which then forwards the data via ssl to the remote postgresql server.

how to use php sockets to write string

So Im trying to get my head wrapped around this....
I open the port
$remip = $_SERVER['SERVER_ADDR']; //Grab my server address
$fp = fsockopen($remip, 80, $errno, $errstr, 10);//Godaddy hosting only 80 and 443 ports work
//fsockopen(ip address , port, IDK, IDK, timeout delay)
so now the ports open or if not maybe some error checking to be sure
if (!$fp) { echo "$errstr ($errno)<br>\n"; exit; } //Not sure what this echos out but its clear how it stops errors
So now that the port is open any ip/client can connect on this port????
Ill assume I can now connect....
So on my client I open a socket to my server ip address port tcp connection.....
The php file includes something like
else {$out = "hello, 80\r\n"; //out specifies the string to be written , bytes to write
fwrite($fp, $out); //$fp is the handle
fclose($fp)}//close the connection
at this point ill assume that my client gets the hello written to it ..
finish up by closing the connection
Im entirely new to this so Im attempting to understand some sample code here...
So how long is this socket open for? If i want to keep this port open do i need to do a cron job to launch this file periodically.
Im 100% sure that I have got something wrong here so please set me straight.
I think you have a misconception of what fsockopen does. In your example your fsockopen does not actually open port 80 (as in opening a server socket), but it opens a client socket that connects to port 80 on the server itself. It actually does open a (client) port which gets a (not completely) random number.
After you connected using fsockopen you can send HTTP commands to the webserver such as GET /index.php
What you need to use is socket_listen() and socket_bind(). There are a few places in the docs that show you how to get PHP listening on a socket: http://www.php.net/manual/en/function.socket-listen.php
I suggest you read and try them out by simply testing then with a unix tool called netcat (nc <ip_address> <port> command normally)

PHP fsocketopen Though Proxy

I am currently using PHP to open up a port 43 connection to get whois information directly from a registry using this code.
// connecting to the whois server.
$handle = fsockopen($server, 43);
if (!$handle)
return false; // connection failure
//asking the server
fwrite($handle, $domain_name."\r\n");
// getting response
$response = '';
while (!feof($handle))
$response .= fgets($handle, 1024);
fclose($handle);
It works great however I want to connect though a proxy server so I route my intertent connection through it. If this were able to use cURL I would use curl_setopt($curl_handle, CURLOPT_PROXY, $ip_address . ':4040'); but i can not find a way to do this using fsocketopen. How can I accomplish this either with cURL or fsocketopen()?
Sockets dont have proxy. Just gateways and routers are in-the-middle (if any). You were talking about cURL, that it has proxy - it only uses http/s proxy service. For example, if you have http proxy service on server example.com:8080 you first need to open connection to server example.com (socket) on port 8080 and then send your request, proxy will forward your request and return response. In your case, you just open tcp connection on port 43 on specific host and exchange data directly with target server. If you dont want to do this directly and reveal your ip (or something) you'll need some service too. If you have access to other machine you could use it to do the job. If you want to do it manually you could use ssh or something like that, if you want to make it automatized, you'll probably need to write service on your middle server because you probably wont find any public proxy servers with other protocols than popular http, ftp, ...
Hope this helps.
By the way I see no reason why you should use proxy on whois service.
You could use a SOCKS proxy to relay the TCP connection from your machine to the SOCKS server to the WHOIS server but you would have to implement the SOCKS communication protocol over fsockopen.
Another method would be to use ProxyChains on the server and execute it via PHP. I've answered a similar question here ( How to capture and feed telnet using php and shell scripting? ) which shows how to invoke proxychains from PHP to execute a WHOIS command on a remote server and read the response.

Fetch file from https only server

I have a small script which uses curl and retrives specific contents from a defined url. I had this tested on my localhost and it worked.
Now I have to retrive data from a HTTPS-only website (plus, the certificate is invalid, but I know the owners) from my free hosting, but the myserver neither supports CURL nor file_get_contents("https://other-server.com") function. By the way, http://other-server.com isn't accesible.
Is there any method to fetch a file from this server using the HTTPS port, but with HTTP protocol? Or is there some method to use HTTPS, altough my server doesn't support it? (It isn't my server, I haven't access to its configuration)
Try this:
<?php
$fp = fsockopen("ssl://other-server.com", 443, $errno, $errstr);
if(!$fp) die($errno. " : " . $errstr);
$send =
"GET / HTTP/1.0\r\n".
"Host:other-server.com\r\n".
"Accept:text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n".
"\r\n";
fwrite($fp, $send);
while(!feof($fp)) {
echo fread($fp, 512);
}
?>
Should you run into 'ssl transport not available error message', see Socket transport "ssl" in PHP not enabled
If your host is external and perhaps a free webhosting service, you are fresh out of luck.. Best option would be to figure out which webhosts has the SSL transport enabled - otherwise the working with HTTPS protocol simply will not comply.
Your last 'out' is to try to load extension into PHP language dynamically. You will need the excact extension (dll/so) which matches
the PHP version on host (see phpinfo).
the CPU architechture of host (unix, see passthru("cat /proc/cpuinfo");), e.g. amd64,i386..
the OS 'layout', .dll is for a windows host (IIS etc) and .so for UNIX.
Funcition to use is dl aka dynamic-link to load the library. For windows host, you will need php_openssl.dll and php_sockets.dll - and in turn for UNIX, OOops - you would need to recompile php core..
Happy hacking :)
php-man-pages

Categories