6

我已经阅读了许多网站上的许多主题,但仍然无法完成这项工作。

我有一台运行 perl 5.12.4 的 OpenSSL 0.9.8r 客户端机器(OSX),使用 LWP 6.0.4,更新了 Crypt::SSLeay,Net::SSL 等。我正在尝试连接到 HTTPS 站点(https:// /github.com在示例中)通过我在 Windows VM 上运行的 WinGate 代理。请注意,我的实际应用程序附加到我无法控制的 SSL Web 服务。

从 Firefox,指向代理一切都是 copacci。页面加载成功,我在代理软件活动监视器中看到了连接。如果我可以让它在 Perl 中工作,我会被诅咒的。我从这个堆栈溢出问题的代码开始:如何强制 LWP 使用 Crypt::SSLeay 进行 HTTPS 请求?并添加了一些调试和附加输出。这是我现在的立场:

#!/usr/bin/perl

use strict;
use warnings;
use Net::SSL (); # From Crypt-SSLeay

BEGIN {
  $Net::HTTPS::HTTPS_SSL_SOCKET_CLASS = "Net::SSL"; # Force use of Net::SSL
  $ENV{HTTPS_PROXY} = 'https://192.168.1.11:80';
#  $ENV{PERL_LWP_SSL_VERIFY_HOSTNAME} = 0;
  $ENV{HTTPS_DEBUG} = 1;  #Add debug output
}

use LWP::UserAgent;
my $ua = LWP::UserAgent->new();
my $req = HTTP::Request->new('GET','https://github.com/');
my $response = $ua->request($req);

print "--\n";
print "$_\n" for grep { $_ =~ /SSL/ } keys %INC;
print "--\n";

if ($response->is_success) {
     print $response->decoded_content;  # or whatever
     exit(0);
}
else {
 print "\nFail:\n";
     print $response->status_line ."\n";
     exit(1);
}

这是此代码的输出:

--
Crypt/SSLeay.pm
Crypt/SSLeay/X509.pm
Net/SSL.pm
--

Fail:
500 Can't connect to github.com:443 (Crypt-SSLeay can't verify hostnames)

如果我然后取消注释$ENV{PERL_LWP_SSL_VERIFY_HOSTNAME} = 0;,我确实在代理上看到了一个到 github.com:443 的连接,然后什么也没有。(请注意,它通过代理在 Web 浏览器中运行良好)。在挂了很多之后,我从脚本中得到以下输出:

SSL_connect:before/connect initialization
SSL_connect:SSLv2/v3 write client hello A
SSL_connect:before/connect initialization
SSL_connect:SSLv3 write client hello A
SSL_connect:failed in SSLv3 read server hello A
SSL_connect:before/connect initialization
SSL_connect:SSLv2 write client hello A
SSL_connect:failed in SSLv2 read server hello A
--
Crypt/SSLeay.pm
Crypt/SSLeay/X509.pm
Net/SSL.pm
Crypt/SSLeay/CTX.pm
Crypt/SSLeay/MainContext.pm
--

Fail:
500 SSL negotiation failed: 

如果有人可以在这里提供一些指导,我将不胜感激!

4

8 回答 8

7

我刚刚将LWP::Protocol::connect模块上传到 CPAN。此模块将缺少的 HTTP/CONNECT 方法支持添加到 LWP。

  use LWP::UserAgent;

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

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

使用此模块,您可以使用常规 IO::Socket::SSL 实现 LWP >=6.00。

于 2013-07-22T12:05:00.357 回答
3

为什么要“强制使用 Net::SSL”。尝试

#!/usr/bin/perl    
use strict;
use warnings;
use LWP::UserAgent;

BEGIN {
  $ENV{HTTPS_PROXY} = 'https://192.168.1.11:80';
#  $ENV{PERL_LWP_SSL_VERIFY_HOSTNAME} = 0;
  $ENV{HTTPS_DEBUG} = 1;  #Add debug output
}

my $ua = LWP::UserAgent->new();
my $req = HTTP::Request->new('GET','https://github.com/');
my $response = $ua->request($req);
print $response->code ."\n";

输出200应该意味着没有错误。

我的以下示例代码完美地工作

#!/usr/bin/perl
use warnings;
use LWP::UserAgent;

BEGIN {
  $ENV{HTTPS_PROXY} = 'https://176.9.209.113:8080'; #Valid HTTPS proxy taken from http://hidemyass.com/proxy-list/
  $ENV{HTTPS_DEBUG} = 1;
}

my $ua = new LWP::UserAgent;
my $req = new HTTP::Request('GET', 'https://www.nodeworks.com');
my $res = $ua->request($req);
print $res->code, "\n";

输出-

200
SSL_connect:before/connect initialization
SSL_connect:SSLv2/v3 write client hello A
SSL_connect:SSLv3 read server hello A
SSL_connect:SSLv3 read server certificate A
SSL_connect:SSLv3 read server key exchange A
SSL_connect:SSLv3 read server done A
SSL_connect:SSLv3 write client key exchange A
SSL_connect:SSLv3 write change cipher spec A
SSL_connect:SSLv3 write finished A
SSL_connect:SSLv3 flush data
SSL_connect:SSLv3 read finished A
SSL_connect:before/connect initialization
SSL_connect:SSLv2/v3 write client hello A
SSL_connect:SSLv3 read server hello A
SSL_connect:SSLv3 read server certificate A
SSL_connect:SSLv3 read server key exchange A
SSL_connect:SSLv3 read server done A
SSL_connect:SSLv3 write client key exchange A
SSL_connect:SSLv3 write change cipher spec A
SSL_connect:SSLv3 write finished A
SSL_connect:SSLv3 flush data
SSL_connect:SSLv3 read finished A

Tool completed successfully

输出https://github.com/是-

200
SSL_connect:before/connect initialization
SSL_connect:SSLv2/v3 write client hello A
SSL_connect:SSLv3 read server hello A
SSL_connect:SSLv3 read server certificate A
SSL_connect:SSLv3 read server done A
SSL_connect:SSLv3 write client key exchange A
SSL_connect:SSLv3 write change cipher spec A
SSL_connect:SSLv3 write finished A
SSL_connect:SSLv3 flush data
SSL_connect:SSLv3 read finished A

Tool completed successfully

说了这么多。您的代码版本(如下)应该可以正常工作-

use warnings;
use LWP::UserAgent;

BEGIN {
  $ENV{HTTPS_PROXY} = 'https://176.9.209.113:8080';
  $ENV{PERL_LWP_SSL_VERIFY_HOSTNAME} = 0; #works even with this
  $ENV{HTTPS_DEBUG} = 1;  #Add debug output
}

my $ua = new LWP::UserAgent;
my $req = new HTTP::Request('GET', 'https://github.com/');
my $res = $ua->request($req);
print $res->code, "\n";

if ($res->is_success) {
     print $res->decoded_content;  # or whatever
     exit(0);
}
else {
 print "\nFail:\n";
     print $res->status_line ."\n";
     exit(1);
}
于 2012-08-24T21:16:31.007 回答
1

您可以使用 Net::SSLGlue::LWP,而不是使用不提供太多主机验证(也没有 SNI)的 Net::SSL。这个猴子补丁 LWP 以便 https_proxy 可以与默认的 SSL 后端 IO::Socket::SSL 一起使用:

use Net::SSLGlue::LWP; # do this first
use LWP::Simple;
... continue with normal LWP stuff..
于 2013-11-04T20:21:47.523 回答
1

我几乎遇到了同样的问题。以下是为我解决的问题:

于 2012-09-27T15:47:36.853 回答
0

我知道这可能是一个死问题,但如果其他人碰到它,我有另一个角度......我不能保证任何答案,但我们在这个领域的 $work 面临一个长期存在的问题,但是Squid 代理,并且可能特定于 X509 客户端证书的使用。

使用 Net::SSL 覆盖是解决方案的一部分,但我担心 WinGate 可能是问题(而不是我可以帮助解决的问题),尽管在我们的例子中我们通过 http 联系代理(不确定 LWP 如何处理使用代理+https)。

作为记录,这是我们使用的代码的精确形式的示例:

use Net::SSL;
$ENV{PERL_NET_HTTPS_SSL_SOCKET_CLASS}="Net::SSL";
use LWP::UserAgent;
use LWP::Protocol::https;
my $ua = LWP::UserAgent->new;
$ENV{HTTPS_PROXY} = 'http://cache.local.employer.co.uk:80';
$ua->get("https://example.com/");

这是最近安装了 CPAN 的 Perl 5.8.8(因此分离了 L:P:https),所以我们有一个新的 Net::HTTP。

我要提到 Net::HTTP 的某些版本被破坏了,但我刚刚意识到这是我在 Martin 的回复中的 CPAN 错误 :)

抱歉,如果这没有添加任何内容。

于 2013-03-21T13:17:51.327 回答
0

我已经在 libwww-perl 存储库上发送了一个拉取请求来修复(或者可能是解决方法......)这个问题。

这个 PR 的注释显示了一个简单的程序,它通过代理连接 https 到 github.com。有了这个补丁,你就不需要在你的程序中弄乱 %ENV 了。

另一个优点是您可以重复使用通常的 https_proxy 设置。

于 2013-11-01T18:48:22.703 回答
0

在早期 5.8 和其他一些模块中存在错误,其中环境变量 HTTP_PROXY 没有适当地设置代理连接。

您的案例有一个问题,即此处提到的错误报告https://bugzilla.redhat.com/show_bug.cgi?id=1094440

更好的使用方法是没有环境变量并使用 LWP UserAgent

 `use LWP::UserAgent;
  $ua = LWP::UserAgent->new(); 
  $ua->proxy('https', 'connect://proxyhost.domain:3128/');`
于 2016-12-31T02:46:30.090 回答
-1

#!/usr/bin/env perl 
# 
# mimvp.com
# 2017-03-28

use CGI;
use strict;
use LWP::UserAgent;


our %proxy_https = ("https", "connect://173.233.55.118:443");
our $mimvp_url = "https://proxy.mimvp.com/exist.php";

## https
## 1. download LWP-Protocol-connect (wget http://search.cpan.org/CPAN/authors/id/B/BE/BENNING/LWP-Protocol-connect-6.09.tar.gz)
## 2. tar zxvf LWP-Protocol-connect-6.09.tar.gz 
##    cd LWP-Protocol-connect-6.09
##    perl Makefile.PL
##    make
##    sudo make install
sub test_connect {
	my ($url, %proxy) = @_;
	
	print "proxy  : $proxy{'http'}\n";
	print "https  : $proxy{'https'}\n";
	print "socks4 : $proxy{'socks4'}\n";
	print "socks5 : $proxy{'socks5'}\n";
	print "url : $url\n";
	
	my $browser = LWP::UserAgent->new();
	$browser->env_proxy();
	
# 	# 设置的代理格式
	$browser->proxy(%proxy);
	$browser->timeout(30);
	$browser->agent('Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.115 Safari/537.36');
	
# 	my $req = new HTTP::Request('GET', $url);
# 	my $response = $browser->request($req);
	my $response = $browser->get($url);  				# 爬取的网址
	my $is_success = $response->is_success();			# 1
	my $content_type = $response->content_type();		# text/html
	my $content = $response->content();					# 网页正文
	my $content_length = length($content);				# 网页正文长度
	
	print "$is_success\n";
	print "$content_type\n";
	print "$content_length\n";
	print "$content\n";
}

test_connect($mimvp_url, %proxy_https);		# https

## perl mimvp-proxy-perl.pl

于 2017-07-29T16:21:23.380 回答