2

I can't seem to get https through a proxy.

Example:

require LWP::UserAgent;

my $ua = LWP::UserAgent->new;
$ua->timeout(10);
$ua->proxy('https', 'https://proxy:8080');
# $ua->proxy(['https'], 'https://proxy:8080'); # Fails
# $ua->env_proxy; # This also fails.

my $response = $ua->get('https://aws.amazon.com/cloudwatch/');

if ($response->is_success) {
    print $response->decoded_content;  # or whatever
}
else {
    die $response->status_line;
}

Result:

500 Can't connect to aws.amazon.com:443 (timeout) at test.pl line 17.

But if I try the same proxy with curl (also wget) it works just fine.

$ curl --head --proxy https://proxy:8080 https://aws.amazon.com/cloudwatch/
HTTP/1.1 200 Connection established

HTTP/1.1 200 OK
Server: Server
Date: Thu, 08 Dec 2016 16:42:01 GMT
Content-Type: text/html;charset=UTF-8
Content-Length: 214187

Perl versions

$ perl -MLWP -le "print(LWP->VERSION)"
6.15
$ perl --version

This is perl, v5.10.1 (*) built for x86_64-linux-thread-multi

I also tried with and without these:

  export HTTPS_VERSION=3 
  export PERL_NET_HTTPS_SSL_SOCKET_CLASS="Net::SSL"
  export PERL_LWP_ENV_PROXY=1 
  export PERL_LWP_SSL_VERIFY_HOSTNAME=0 

My actual goal here is to get aws-scripts-mon working on a machine behind a proxy but it also uses LWP::UserAgent so if I get this working then that will probably also.

Added info

It turns out that if I change to http by $ua->proxy('http', 'http://proxy:8080'); and accesses a http url then it works just fine. The problem is that I need this to work with https.

The error from mon-put-instance-data.pl is:

./mon-put-instance-data.pl --mem-util --disk-space-util --disk-path=/

ERROR: Failed to call CloudWatch: HTTP 500. Message: Can't connect to monitoring.eu-west-1.amazonaws.com:443 (timeout)

LWP::Protocol::https::Socket: connect: timeout at /usr/local/share/perl5/LWP/Protocol/http.pm line 47.
Jonas Elfström
  • 30,834
  • 6
  • 70
  • 106
  • Why do you have `require` instead of `use`? Why do you *not* have `use strict` and `use warnings 'all'` at the top of your program? These are *essential* for any Perl program. – Borodin Dec 08 '16 at 18:11
  • I see your point but I simply did a quick copy & paste from CPAN and this is how the example of using LWP:Useragent looks [there](http://search.cpan.org/~ether/libwww-perl-6.15/lib/LWP/UserAgent.pm). – Jonas Elfström Dec 09 '16 at 08:21

2 Answers2

4

Try LWP::Protocol::connect found in https://stackoverflow.com/a/17787133/44620

  use LWP::UserAgent;

  $ua = LWP::UserAgent->new(); 
  $ua->proxy('https', 'connect://proxyhost.domain:3128/');

  $ua->get('https://www.somesslsite.com');
Community
  • 1
  • 1
David Verdin
  • 480
  • 6
  • 18
  • Sorry. Looking on the bug reports, there seems to be an opened bug regarding https through a proxy: https://rt.cpan.org/Public/Bug/Display.html?id=95671 – David Verdin Dec 08 '16 at 17:13
  • 1
    Though, in this answer (http://stackoverflow.com/a/17787133/6193608) somebody seems to have found a workaround. The post is dated 2013 but it might be worth a try. – David Verdin Dec 08 '16 at 17:20
  • Great! "There's more than one way to do it", isn't it? – David Verdin Dec 08 '16 at 17:33
  • 1
    ``Successfully reported metrics to CloudWatch.`` – Jonas Elfström Dec 08 '16 at 17:38
  • 2
    if the workaround worked, adding a comment to that effect in the bug report may be really helpful to others – ysth Dec 08 '16 at 17:39
  • 1
    good suggestion. I did it: https://rt.cpan.org/Ticket/Display.html?id=95671#txn-1689550 – David Verdin Dec 08 '16 at 18:34
  • LWP 6.15 as used by the OP supports proper use of a proxy for https and does not need the connect handler for this. The real problem is the wrong URL given to access the proxy: It should have been `http://` instead of `https://` to access the proxy itself because the connection to the proxy is not protected by SSL but only the connection from the client to the final target through the proxy. – Steffen Ullrich Dec 09 '16 at 06:01
  • Oh. But then the bug should be closed in the CPAN tracker? – David Verdin Dec 09 '16 at 07:00
  • @DavidVerdin: yes, the bug should be closed. The original issue is actually https://rt.cpan.org/Public/Bug/Display.html?id=1894 from 2002 which was fixed in 2014 with LWP 6.06. My guess is that there is some explicit use of `Net::SSL` in the program or environment which make LWP not use the default IO::Socket::SSL but the old Net::SSL/Crypt::SSLeay and there proxy handling is different. – Steffen Ullrich Dec 09 '16 at 16:17
1
  $ua->proxy('https', 'https://proxy:8080');

LWP does not support the use of HTTP proxies which are accessed using HTTPS. But my guess is that your proxy does not gets access with HTTPS at all, i.e. it gets accessed with HTTP even though it proxies HTTPS requests(*). Thus the code should instead use a http:// URL to access the proxy and not a https:// URL:

   $ua->proxy('https', 'http://proxy:8080/');

Note that this only works in the usual setup, i.e. with IO::Socket::SSL installed on the system and used by LWP. Especially with setting PERL_NET_HTTPS_SSL_SOCKET_CLASS to Net::SSL or explicitly importing Net::SSL into the program the obsolete Crypt::SSLeay will be used where proxy handling is completely different.

(*) Even though the proxy will be accessed by HTTP and not HTTPS the connection is still encrypted. This is done by the client requesting the proxy to create a tunnel to the original target using the CONNECT method and then doing end-to-end SSL inside this tunnel. While there are a some proxies and some clients which support to be accessed by HTTPS too this would essentially mean to build an SSL connection between client and proxy and inside this SSL connection another SSL connection between client and final target, i.e. double encryption.

Steffen Ullrich
  • 114,247
  • 10
  • 131
  • 172
  • The OP is using LWP 6.15 and said `$ua->proxy('https', 'http://proxyhost:proxyport/');` didn't work. – ThisSuitIsBlackNot Dec 08 '16 at 19:59
  • @ThisSuitIsBlackNot: actually, the OP said the use of `https://` for accessing the proxy did not work and exactly this (use of `https://` instead of `http://` to access the proxy) was the real problem. Thanks for pointing out which version the OP is using since I've missed this detail. – Steffen Ullrich Dec 09 '16 at 06:04
  • Your guess seems to be wrong. I tried `$ua->proxy('https', 'https://proxy:8080');` and still got `500 Can't connect to aws.amazon.com:443 (timeout) at test.pl line 16.` What you are suggesting also does not seem to explain why `curl --head --proxy https://proxy:8080 https://aws.amazon.com/cloudwatch/` works. – Jonas Elfström Dec 09 '16 at 08:28
  • @JonasElfström: according to your comment you again tried `https://` for the proxy instead of `http://`. Also, curl will ignore if you put `http://` or `https://` there because (from the documentation of `--proxy`): *No protocol specified, http:// and all others will be treated as HTTP proxies.*. This means `https://proxy`, `http://proxy`, `whatever://proxy` or `proxy` will all be treated the same. – Steffen Ullrich Dec 09 '16 at 09:05
  • @JonasElfström: then this is very strange because this does the same as the connect method from the other answer. – Steffen Ullrich Dec 09 '16 at 09:09
  • `500 Can't connect to aws.amazon.com:443 at test.pl line 16.` for `$ua->proxy('https', 'http://proxy:8080');` and works fine with `$ua->proxy('https', 'connect://proxy:8080');` – Jonas Elfström Dec 09 '16 at 09:12
  • @JonasElfström: very strange. I've tried it with same version of LWP and it works without problem for me. Do you have still any of these environment variables set you mention in your question? Especially the setting of PERL_NET_HTTPS_SSL_SOCKET_CLASS? Because if I have this still set I get the same problem you describe while connect:// still works. – Steffen Ullrich Dec 09 '16 at 09:16
  • @SteffenUllrich Yes I do. I tried to `unset PERL_NET_HTTPS_SSL_SOCKET_CLASS` but still got the same error. – Jonas Elfström Dec 09 '16 at 09:32
  • @JonasElfström: is that exactly the code you are using which you've published in your question? Because this is the code I've tried. And do you have IO::Socket::SSL installed so that it will use this instead of Crypt::SSLeay (which is considered obsolete)? – Steffen Ullrich Dec 09 '16 at 10:59