PHP FTP through SOCKS5 proxy - php

I'm trying to connect to an FTP server through a SOCKS5 proxy in PHP. But I am unable to figure it out. On the internet I do find posts telling me it is possible but in the examples I've found calls like file_get_contents are used but I want to use the (native) FTP methods to get all the files in a dir etc.
Is there any way to achieve this? I did found this extension but I want this to work on all hosts. A composer package would be fine.
Stuff like this does work but this does not allow me to do FTP calls
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, "ftp://somehost/somefile.txt");
curl_setopt($ch, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4);
curl_setopt($ch, CURLOPT_PROXYTYPE, CURLPROXY_SOCKS5);
curl_setopt($ch, CURLOPT_PROXYUSERPWD, $proxy_userpass);
curl_setopt($ch, CURLOPT_PROXY, $proxy_server);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
echo "FTP Transfer: ".curl_exec($ch).PHP_EOL;
curl_close($ch);
Just to make it clear: the code listed above works but I'm looking for a way to use the PHP calls like ftp_get() and ftp_put() through an proxy.

Related

PHP how to connect to FTP using Implicit FTP over TLS

Apparently the native FTP functionality of FTP does not support implicit FTP over TLS
I tried this using Curl but doesn't work:
$ftp_server = 'data.example.com/file.csv';
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $ftp_server);
curl_setopt($ch, CURLOPT_USERPWD,'abcde'.':'.'123456');
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
curl_setopt($ch, CURLOPT_FTP_SSL, CURLFTPSSL_TRY);
curl_setopt($ch, CURLOPT_FTPSSLAUTH, CURLFTPAUTH_TLS);
curl_setopt($ch, CURLOPT_VERBOSE, TRUE);
$file = fopen('local_file.csv', "w+");
curl_setopt($ch, CURLOPT_FILE, $file);
$data = curl_exec($ch);
$error_no = curl_errno($ch);
curl_close($ch);
If I try without a file name in the URL I appear to reach the server as I get an IIS welcome page. If I try with the file, I get a 404 error. I know the file is accurate as I can access via Filezilla.
Thank you
Your URL should include the scheme, e.g.:
$ftp_server = 'ftps://data.example.com/file.csv';
From CURLOPT_URL explained:
If the given URL is missing a scheme name (such as "http://" or "ftp://" etc) then libcurl will make a guess based on the host. If the outermost sub-domain name matches DICT, FTP, IMAP, LDAP, POP3 or SMTP then that protocol will be used, otherwise HTTP will be used.
You're hitting the IIS welcome page and 404 errors because you're making an http request rather than connecting via ftps.

send multiple .crt certificate with curl in php

I want to send two .crt certificates with curl in php.
I am using this code.
$firstcalldata = "csv file data";
$target_url = www.example.com;
$ch = curl_init($target_url);
curl_setopt($ch, CURLOPT_VERBOSE, '1');
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_CAINFO,"C:/Users/admin/Desktop/CERT/PSCERT.pem");
curl_setopt($ch, CURLOPT_CAINFO, getcwd() . "C:/Users/admin/Desktop/CERT/PSCERT-C.crt");
curl_setopt($ch,CURLOPT_POST, 1);
curl_setopt($ch,CURLOPT_POSTFIELDS, $firstcalldata);
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: application/csv'));
$result = curl_exec($ch);
echo $result;
curl_close($ch);`
I am sending also a csv file to $target_url.
But all time I am getting 403 - Forbidden: Access is denied.
You're not really saying what you want to accomplish, you're just asking a very weird question with no answer. You example doesn't send the .crt at all, it uses it to verify the server's certificate. And CAINFO is meant to point to a file holding a full bundle (like one of those you can get at curl's caextract page)
But you disable both VERIFYPEER and VERIFYHOST so you don't actually need any CA cert!?
What exactly do you want to do? Note also how getting a 403 back means that you already communicate fine over the TLS layer.

PHP connect to HTTPS site through proxy

I've got the following problem: there is an HTTPS web site, and I need to connect to it through a proxy. Here are my cURL setopts:
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_PROXY, '100.100.100.100:8080');
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
curl_setopt($ch, CURLOPT_HEADER, 1);
curl_setopt($ch, CURLOPT_USERAGENT, $ua);
curl_setopt($ch, CURLOPT_TIMEOUT, 10);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER,false);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
echo curl_error($ch);
outputs Failed connect to ######.com:8080; No error
Where 100.100.100.100:8080 is a placeholder for a valid HTTPS proxy. This doesn't work. How do I make cURL connect to an HTTPS website through a proxy? I would really like a soultion that would work through not only HTTPS proxies. Also, I would best prefer a method using cURL, but if there is a better way to do it, without cURL, I could use it instead.
Update:
Add
curl_setopt($ch, CURLOPT_HTTPPROXYTUNNEL, 1);
It will prevent your HTTP proxy to parse your request headers and to act more transparently - like a tunnel.
initial answer, not interesting
Your code looks OK, and I assume you checked the trivial issues, so the problem is probably that the SSL certificate verification fails. It's the case if the certificate is self signed by example.
Try
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
to allow a request that allows using a self signed certificate.

cURL request using socks5 proxy fails when using PHP, but it works through the command line

cURL + proxy noob here, having a hard time. I'm having trouble trying to retrieve a web page from a remote secure server via a proxy. Everything has apparently been set up correctly by a remote dev, such that the following command line instruction works and returns what we're looking for:
curl -k --socks5-hostname localhost:xxxx https://hostname/
However, the following PHP does not echo the requested webpage. Instead it echoes the error 'Couldn't resolve host name':
$proxy = 'localhost:xxxx';
$url = 'https://hostname/';
//$proxyauth = 'user:password';
$ch = curl_init();
curl_setopt($ch, CURLOPT_PROXY, $proxy);
curl_setopt($ch, CURLOPT_PROXYTYPE, CURLPROXY_SOCKS5);
//curl_setopt($ch, CURLOPT_PROXYUSERPWD, $proxyauth);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_HEADER, 1);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($ch, CURLOPT_URL, $url);
$curl_scraped_page = curl_exec($ch);
$error = curl_error($ch);
curl_close($ch);
if ($error)
echo $error;
elseif ($curl_scraped_page)
echo $curl_scraped_page;
If the $url is changed to a public page, such as Google, the request is successful and everyone is happy.
The connection requires an SSH tunnel if that changes anything at all. The tunnel is open and functioning, as proven by the command line request succeeding.
Is there something obvious that is being missed here?
You need to set option CURLOPT_PROXYTYPE to CURLPROXY_SOCKS5_HOSTNAME, which sadly wasn't defined in old PHP versions, circa pre-5.6; if you have earlier in but you can explicitly use its value, which is equal to 7:
curl_setopt($ch, CURLOPT_PROXYTYPE, 7);
In the option CURLOPT_PROXYTYPE you need to set CURLPROXY_SOCKS5_HOSTNAME option instead of CURLPROXY_SOCKS5.
In this case, the DNS query (for hostname resolving) will be sent to SOCKS proxy and not resolved in the local network.
curl_setopt($ch, CURLOPT_PROXYTYPE, CURLPROXY_SOCKS5_HOSTNAME);
This constant available since PHP 5.5.23 and PHP 5.6.7 and cURL 7.18.0, so you can simply use it.

Joomla site on LAMP server behind proxy cannot access HTTP resource stream

Setup:
1. Joomla 1.5 website on a LAMP server (CentOS 5.2/Apache 2.2/PHP 5.2.9/mysql 5)
2. Joomla module for currency conversion added. Module uses google finance to convert currency
3. LAMP stack resides in the intranet behind a proxy. The server environment variables for http_proxy, yum.conf proxy have been setup, and kernel successfully updated.
4. phpinfo() clearly shows curl is installed
5. module mentioned in '2.' allows 3 methods to connect to google finance, fread(), file_get_contents() and using the cURL libraries. As the box is behind a proxy, only the cURL libraries method should work.
Problem:
on a WAMP stack, the curl library method works fine. On the lamp stack, however, the module is unable to communicate with google finance, and throws an error mentioning connect timed out. Here's some code to make it clearer.
if (isset($_GET['process'])) {
$url = "http://finance.google.com/finance/converter?a={
$_GET['a']}&from={$_GET['from']}&to={$_GET['to']}";
$app->get_page($url);
$data = $app->process();
}
function get_page($url) {
if ($url!='') {
echo $url;
$ch = curl_init ();
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($ch, CURLOPT_BINARYTRANSFER, $this->binary);
$this->html = curl_exec($ch);
curl_close($ch);
}
}
I even tried adding a curl_setopt($ch, CURLOPT_PROXY,'10.x.xx.xx:8080'); after curl_init(), to no avail. I've compiled apache with libcurl and php enabled, and I need to know the following:
1. How to instruct php to route outgoing requests(streams) through the proxy?
2. Do I need to configure cURL (libcurl) with the proxyname and port?
3. I've switched iptables off, so the linux firewall is not in the picture anymore, is there anything else I need to do to allow outgoing requests?
4. I've setup the proxy so that my LAMP stack is unblocked for all content, cURL works off the command line, but not from php/apache. What am I missing? Any environment variables? Any switches?
Thanks in advance for your time.
Shrinivas
Here's an example using a local SOCKS5 proxy on port 1090:
<?php
$url = 'www.whatismyip.com/automation/<your unique whatismyip hash>';
function get_page($url, $proxy=true) {
if ($url!='') {
$ch = curl_init ();
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
if ($proxy) {
curl_setopt($ch, CURLOPT_PROXY, 'localhost');
curl_setopt($ch, CURLOPT_PROXYTYPE, CURLPROXY_SOCKS5);
curl_setopt($ch, CURLOPT_PROXYPORT, 1090);
}
$html = curl_exec($ch);
curl_close($ch);
return $html;
}
}
var_dump(get_page($url));
var_dump(get_page($url, false));
You'd probably want to use curl_setopt($ch, CURLOPT_PROXYTYPE, CURLPROXY_HTTP); and curl_setopt($ch, CURLOPT_PROXYPORT, 8080); instead.

Categories