Skip to content

Fix for proxy handling in SSLSocketHttpTransport and CurlHttpTransport#25

Closed
patzerr wants to merge 4 commits into
xp-framework:masterfrom
patzerr:fix/proxy_handling
Closed

Fix for proxy handling in SSLSocketHttpTransport and CurlHttpTransport#25
patzerr wants to merge 4 commits into
xp-framework:masterfrom
patzerr:fix/proxy_handling

Conversation

@patzerr

@patzerr patzerr commented Dec 4, 2019

Copy link
Copy Markdown

Hi,
we needed the proxy functionality and realized there were some bugs:

  • CurlHttpTransport
    • curl-handle management was broken
  • SSLSocketHttpTransport
    • encryption algorithm check needed a new connection for each try (foreach in "enable" didn't work)
    • that's why SSLSocketHttpTransport::proxy may return a new peer.Socket

Other things i missed:

  • gitignore file missing
    • exclude vendor-folder
    • excluded the IDEs folders
    • excluded composer.lock as it is dependent on the developing system
  • composer.json: added "suggest" section as the note in the README.md seems like too little if there is tool support for that

hth

@thekid thekid left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not happy making all these changes in the absence of any tests. I'll look into a test suite, or at least a test script including some pointers how a local proxy setup should be made.

Comment thread .gitignore
.idea/
composer.lock
vendor/

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We usually don't have .gitignore files in any of the XP modules. I use https://help.github.com/en/github/using-git/ignoring-files#create-a-global-gitignore

Comment thread composer.json
"suggest": {
"ext-openssl": "Allows to use SSL/TLS, e.g. for https-connections",
"ext-curl": "Alternative to ext-openssl for SSL-/TLS connections"
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like this.

*/
public function send(HttpRequest $request, $timeout= 60, $connecttimeout= 2.0) {
$curl= curl_copy_handle($this->handle);
$curl= curl_init();

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why was this change made? Why can't the handle be reused?

];
}

if (xp::errorAt(__FILE__)) xp::gc(__FILE__); // reset error stack for openssl error detection

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This cannot work, because xp::gc() would resolve to peer\http\xp, which definitely does not exist. It would need to be written as \xp::gc() with a leading backslash. Have you actually tested this code?

@thekid

thekid commented Dec 24, 2019

Copy link
Copy Markdown
Member

Environment setup

Step 1: Installed local Squid proxy ✅
Step 2: Verified it via curl ✅ :

$ https_proxy=localhost:3128 curl -iI https://thekid.de/
HTTP/1.1 200 Connection established

HTTP/1.1 200 OK
Content-Type: text/html
Content-Length: 6113
Connection: keep-alive
Keep-Alive: timeout=15
Date: Tue, 24 Dec 2019 11:42:54 GMT
Server: Apache
Last-Modified: Wed, 10 Jan 2018 17:16:51 GMT
ETag: "17e1-5626f327566c0"
Accept-Ranges: bytes

Test script

head.script.php:

<?php

use peer\http\HttpConnection;
use util\cmd\Console;
use util\log\Logging;

$c= new HttpConnection($argv[1]);
$c->setTrace(Logging::all()->toConsole());
$c->head();

Run with ext/openssl:

$ https_proxy=localhost:3128 xp -m ../logging/ head.script.php https://thekid.de/
[12:47:34 13200  info] >>> CONNECT thekid.de:443 HTTP/1.1
[12:47:34 13200  info] <<< HTTP/1.1 200 Connection established

[12:47:34 13200 debug] @@@ Enabling tls:// cryptography
[12:47:34 13200  info] >>> HEAD / HTTP/1.1
Connection: close
Host: thekid.de


[12:47:34 13200  info] <<< HTTP/1.1 200 OK
Content-Type: text/html
Content-Length: 6113
Connection: close
Date: Tue, 24 Dec 2019 11:47:31 GMT
Server: Apache
Last-Modified: Wed, 10 Jan 2018 17:16:51 GMT
ETag: "17e1-5626f327566c0"
Accept-Ranges: bytes

Run with ext/curl:

$ https_proxy=localhost:3128 xp -m ../logging/ head.script.php https://thekid.de/
[12:49:17 13284  info] >>> HEAD / HTTP/1.1
Connection: close
Host: thekid.de


Uncaught exception: Exception lang.FormatException ("" is not a valid HTTP response [-1])
  at peer.http.CurlHttpTransport::send() [line 122 of CurlHttpTransport.class.php] 
  Undefined property: peer\http\CurlHttpTransport::$handle
# ...

Okay, I see why you used curl_init() above.

@thekid

thekid commented Dec 24, 2019

Copy link
Copy Markdown
Member

Okay, I see why you used curl_init() above.

Fixed in 91e84d9

@thekid

thekid commented Dec 24, 2019

Copy link
Copy Markdown
Member

✅ Released the CURL fixes in https://github.com/xp-framework/http/releases/tag/v9.1.3

@thekid

thekid commented Dec 24, 2019

Copy link
Copy Markdown
Member

@patzerr - could you please explain with an example script how to reproduce this:

SSLSocketHttpTransport
encryption algorithm check needed a new connection for each try (foreach in "enable" didn't work)
that's why SSLSocketHttpTransport::proxy may return a new peer.Socket

@thekid

thekid commented Dec 24, 2019

Copy link
Copy Markdown
Member

Okay, the "flags" parameter to stream_socket_enable_crypto() is meant to be used as a bitfield, see https://github.com/php/php-src/blob/PHP-7.4.0/main/streams/php_stream_transport.h#L166. Rewrote code base to adapt to this in 387d48f

@thekid

thekid commented Dec 24, 2019

Copy link
Copy Markdown
Member

curl.script.php:

<?php

use peer\http\HttpConnection;
use util\cmd\Console;
use util\log\Logging;

$c= new HttpConnection($argv[2]);
$c->setTrace(Logging::all()->toConsole());
$c->request($argv[1]);

Run with ext/openssl:

$ https_proxy=localhost:3128 xp -m ../logging/ curl.script.php head https://thekid.de/
[16:54:56 11028  info] >>> CONNECT thekid.de:443 HTTP/1.1
[16:54:56 11028  info] <<< HTTP/1.1 200 Connection established

[16:54:56 11028 debug] @@@ Enabled cryptography: [
  protocol => "TLSv1.2"
  cipher_name => "ECDHE-RSA-AES256-GCM-SHA384"
  cipher_bits => 256
  cipher_version => "TLSv1.2"
]
[16:54:56 11028  info] >>> HEAD / HTTP/1.1
Connection: close
Host: thekid.de


[16:54:56 11028  info] <<< HTTP/1.1 200 OK
Content-Type: text/html
Content-Length: 6113
Connection: close
Date: Tue, 24 Dec 2019 15:54:53 GMT
Server: Apache
Last-Modified: Wed, 10 Jan 2018 17:16:51 GMT
ETag: "17e1-5626f327566c0"
Accept-Ranges: bytes

Run with ext/openssl and a specific crypto method which the server does not support:

$ https_proxy=localhost:3128 xp -m ../logging/ curl.script.php head https+sslv3://thekid.de/
[16:56:46  1148  info] >>> CONNECT thekid.de:443 HTTP/1.1
[16:56:46  1148  info] <<< HTTP/1.1 200 Connection established

Uncaught exception: Exception io.IOException (Cannot establish secure connection, tried sslv3)
  at <main>::stream_socket_enable_crypto() [line 86 of SSLSocketHttpTransport.class.php]
  stream_socket_enable_crypto(): SSL operation failed with code 1. OpenSSL Error messages:
  error:14094410:SSL routines:ssl3_read_bytes:sslv3 alert handshake failure
  # ...

@thekid

thekid commented Dec 24, 2019

Copy link
Copy Markdown
Member

@thekid thekid closed this Dec 24, 2019
@patzerr

patzerr commented Jan 8, 2020

Copy link
Copy Markdown
Author

Hi,
first of all, sorry for the late reply.
Second, thanks for the hint about the global gitignore.

My testing was done manually in an environment where the use of a proxy is enforced.
That is where the need to use this feature originated from.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants