通过ip地址测试SNI https服务

时间:2017-01-28 01:22:05

标签: perl ssl lwp-useragent

我正在编写一个perl脚本来测试服务器,然后再从旧服务器切换DNS(用于支持服务器迁移)。我宁愿不破解/ etc / hosts来覆盖DNS进行测试,而是让脚本能够正常工作。

非ssl连接很容易,但我遇到SSL问题 - 它适用于大多数网站,因为大多数网站仍将网站绑定到IP地址,但是一个特定客户的网站太聪明了(这无论如何应该是方向的方向),我需要告诉LWP :: UserAgent连接到IP地址,但在请求中使用服务器名称(SSL SNI和HTTP主机:)。

我正在使用ssl_opts设置SNI主机名(并且SSLeay跟踪显示正确设置),并强制将Host HTTP标头添加到servername(打印出请求显示应该设置为正确),但是LWP使用url来决定连接到哪个主机,并且url正在进入哪个地方(我希望实际的“GET”只是“GET /”,所以请求“as_string”不是这里完全准确),导致错误:

#!/usr/bin/perl

#
#  ht
#
#  https test
#  see if I can force a Host: header
#  while using an ip address to connect
#

use strict;

use Net::SSLeay;
use LWP::UserAgent;
$Net::SSLeay::trace = 2;

my $ip = '1.2.3.4';
my $server_name = 'server.name';
my $url = "https://$ip/";
#my $url = "https://$server_name/";

print "connecting to $ip for $server_name\n";

my $h = HTTP::Headers->new;
$h->header('Host' => $server_name);

my %options = (
    'ssl_opts' => { SSL_hostname => $server_name }
);

my $ua = LWP::UserAgent->new(%options);
$ua->agent("perl-mpchk/0.1 ");

# Create a request
my $req;
$req = HTTP::Request->new('GET', $url, $h);
print $req->as_string, "\n";

# Send request to the user agent and get a response back
my $res = $ua->request($req);
if (!defined($res)) {
    die "connect to $url failed\n";
}

print $res->status_line, "\n";

exit 0;

主机名:

connecting to 1.2.3.4 for server.name
GET https://server.name/
Host: server.name

DEBUG: .../IO/Socket/SSL.pm:562: socket not yet connected
DEBUG: .../IO/Socket/SSL.pm:564: socket connected
DEBUG: .../IO/Socket/SSL.pm:586: ssl handshake not started
DEBUG: .../IO/Socket/SSL.pm:619: using SNI with hostname server.name
DEBUG: .../IO/Socket/SSL.pm:654: request OCSP stapling
DEBUG: .../IO/Socket/SSL.pm:673: set socket to non-blocking to enforce timeout=180
DEBUG: .../IO/Socket/SSL.pm:699: ssl handshake in progress
DEBUG: .../IO/Socket/SSL.pm:709: waiting for fd to become ready: SSL wants a read first
DEBUG: .../IO/Socket/SSL.pm:729: socket ready, retrying connect
DEBUG: .../IO/Socket/SSL.pm:744: ssl handshake done
200 OK

使用ip地址

connecting to 1.2.3.4 for server.name
GET https://1.2.3.4/
Host: server.name

DEBUG: .../IO/Socket/SSL.pm:562: socket not yet connected
DEBUG: .../IO/Socket/SSL.pm:564: socket connected
DEBUG: .../IO/Socket/SSL.pm:586: ssl handshake not started
DEBUG: .../IO/Socket/SSL.pm:619: using SNI with hostname server.name
DEBUG: .../IO/Socket/SSL.pm:654: request OCSP stapling
DEBUG: .../IO/Socket/SSL.pm:673: set socket to non-blocking to enforce timeout=180
DEBUG: .../IO/Socket/SSL.pm:699: ssl handshake in progress
DEBUG: .../IO/Socket/SSL.pm:709: waiting for fd to become ready: SSL wants a read first
DEBUG: .../IO/Socket/SSL.pm:729: socket ready, retrying connect
DEBUG: .../IO/Socket/SSL.pm:744: ssl handshake done
500 Unknown Domain

2 个答案:

答案 0 :(得分:2)

您可以跳过LWP并直接使用套接字:

use IO::Socket::SSL;

my $ip_address = ...;
my $server_name = ...;

my $cl = IO::Socket::SSL->new(
    PeerAddr => $ip_address,
    PeerPort => 443,
    SSL_hostname => $server_name,
    SSL_verifycn_name => $server_name,
    SSL_verifycn_scheme => 'http',
);
print $cl "GET / HTTP/1.0\r\nHost: $server_name\r\n\r\n";
print scalar(<$cl>);  # status line

答案 1 :(得分:-1)

问题原来是转换为IP地址网址表单的中间代理。已更正正确使用该名称并开始工作。