【问题标题】:Perl https proxy problemsPerl https代理问题
【发布时间】:2016-12-08 16:52:17
【问题描述】:

我似乎无法通过代理获取 https。

例子:

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;
}

结果:

500 无法在 test.pl 第 17 行连接到 aws.amazon.com:443(超时)。

但如果我尝试使用 curl(也是 wget)使用相同的代理,它就可以正常工作。

$ 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 版本

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

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

我也试过有和没有这些:

  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 

我的实际目标是让aws-scripts-mon 在代理后面的机器上工作,但它也使用LWP::UserAgent,所以如果我让它工作,那么它可能也会。

添加信息

事实证明,如果我通过以下方式更改为 http $ua->proxy('http', 'http://proxy:8080'); 并访问一个 http url 然后它工作得很好。问题是我需要它来使用 https。

mon-put-instance-data.pl 的错误是:

./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.

【问题讨论】:

  • 为什么你有require而不是use?为什么你没有在你的程序顶部有use strictuse warnings 'all'?这些对于任何 Perl 程序都是必不可少的
  • 我明白你的意思,但我只是从 CPAN 快速复制和粘贴,这就是使用 LWP:Useragent 的示例的样子 there

标签: perl lwp lwp-useragent


【解决方案1】:

试试https://stackoverflow.com/a/17787133/44620中的LWP::Protocol::connect

  use LWP::UserAgent;

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

  $ua->get('https://www.somesslsite.com');

【讨论】:

【解决方案2】:
  $ua->proxy('https', 'https://proxy:8080');

LWP 不支持使用通过 HTTPS 访问的 HTTP 代理。但我的猜测是,您的代理根本无法通过 HTTPS 访问,即即使它代理 HTTPS 请求(*),它也可以通过 HTTP 访问。因此代码应该改用http:// URL 来访问代理而不是https:// URL:

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

请注意,这只适用于通常的设置,即安装在系统上并由 LWP 使用的 IO::Socket::SSL。特别是在将 PERL_NET_HTTPS_SSL_SOCKET_CLASS 设置为 Net::SSL 或将 Net::SSL 显式导入程序时,将在代理处理完全不同的情况下使用过时的 Crypt::SSLeay

(*) 即使代理将通过 HTTP 而不是 HTTPS 访问,连接仍然是加密的。这是通过客户端请求代理使用CONNECT 方法创建到原始目标的隧道,然后在此隧道内执行端到端 SSL 来完成的。虽然有一些代理和一些客户端也支持通过 HTTPS 访问,但这本质上意味着在客户端和代理之间建立一个 SSL 连接,并在这个 SSL 连接中在客户端和最终目标之间建立另一个 SSL 连接,即双重加密。

【讨论】:

  • OP 正在使用 LWP 6.15 并说 $ua->proxy('https', 'http://proxyhost:proxyport/'); 不起作用。
  • @ThisSuitIsBlackNot:实际上,OP 说使用https:// 访问代理不起作用,而正是这个(使用https:// 而不是http:// 访问代理)是真正的问题。感谢您指出 OP 使用的是哪个版本,因为我错过了这个细节。
  • 您的猜测似乎是错误的。我试过$ua->proxy('https', 'https://proxy:8080'); 仍然得到500 Can't connect to aws.amazon.com:443 (timeout) at test.pl line 16. 你的建议似乎也不能解释为什么curl --head --proxy https://proxy:8080 https://aws.amazon.com/cloudwatch/ 有效。
  • @JonasElfström:根据您的评论,您再次尝试使用https:// 代替http:// 作为代理。此外,如果您将http://https:// 放在那里,curl 将忽略,因为(来自--proxy 的文档):未指定协议,http:// 和所有其他协议将被视为 HTTP 代理。我>。这意味着 https://proxyhttp://proxywhatever://proxyproxy 都将被同等对待。
  • @JonasElfström:那么这很奇怪,因为这与其他答案中的 connect 方法相同。
猜你喜欢
  • 2018-03-20
  • 1970-01-01
  • 1970-01-01
  • 2015-06-20
  • 1970-01-01
  • 2016-10-18
  • 2018-08-02
  • 1970-01-01
  • 2021-01-03
相关资源
最近更新 更多