IO :: Socket :: SSL-建立客户端连接

时间:2019-01-21 04:01:25

标签: perl ssl

根据IO :: Socket :: SSL(PERL)的文档,我了解到,如果我只想向主机上端口9999上运行的特定服务器程序发送命令,我可以这样做:

my $cl=IO::Socket::SSL->new("localhost:9999"); # locallost is my real case, anyway
if($cl) {
    $cl->connect_SSL or die $@;
    # Something about certificates?
    $cl->syswrite("Command");
    close($cl);
}

但是我得到的错误是:“ SSL连接尝试失败,出现未知错误错误:140770FC:SSL例程:SSL23_GET_SERVER_HELLO:blabla.cgi行888处的未知协议”

服务器通过这种方式初始化(​​在另一个pl程序中):

use IO::Socket::SSL;
use Net::WebSocket::Server;
my $CON={};
my @crt=&SSLCerts(); die 'E101' if(@crt==0);
my $ssl=IO::Socket::SSL->new(
    Listen        => 10000,
    Timeout       => 45,
    LocalPort     => 9999,
    Proto         => 'tcp',
    SSL_cert_file => "$EF::Base/ssl/certs/$crt[0][0].crt",
    SSL_key_file  => "$EF::Base/ssl/keys/$crt[1][0].key"
) or die "E102: $!";

Net::WebSocket::Server->new(
    listen => $ssl,
    silence_max=> 3600,
    tick_period => 5,
    on_tick => sub {
         # Empty for now
    },
    on_connect => sub {
        my($serv,$conn)=@_; my($cid,$sid);
        $conn->on(
            handshake => sub {
                my($cnc,$hdk)=@_;
                my $nsn=$hdk->req->resource_name;
                $cid=substr($nsn,4,index($nsn,'&L=')-4);
                $CON->{$cid}=$cnc; # Register incomming connection
            },
            binary => sub {
                # Handle incomming message from the client
            },
            disconnect => sub {
                delete $CON->{$cid};
            }
        );
    }
)->start;

通过浏览器通过“ wss://”进行连接的典型Websocket客户端可以正常连接。...服务器必须为SSL ...

在这里,我只是想在perl中做同样的事情。

我做错了什么?没有提及客户端中的证书,仅涉及服务器中的证书-服务器工作正常。也许配置?我已经购买了SSL证书,并将它们用于在该端口上运行正常的服务器。 主机是Linux(如果需要的话,是CentOS)。

1 个答案:

答案 0 :(得分:2)

  

... SSL23_GET_SERVER_HELLO:未知协议

如果客户端尝试进行SSL握手并且服务器以非SSL的方式响应,则会出现这种错误。通常,如果您连接到未(正确)启用SSL(至少不在此端口上)或需要一些纯文本才能升级到SSL(例如SMTP STARTTLS等)的服务器,就会发生这种情况。

这种错误通常与证书无关。

仅当您尝试在已建立的SSL套接字上进行SSL握手但服务器不希望这样做时,才会发生此类错误。这种情况似乎发生在您的情况下:

my $cl=IO::Socket::SSL->new("localhost:9999"); # locallost is my real case, anyway
if($cl) {
    $cl->connect_SSL or die $@;
    ...

IO::Socket::SSL->new已建立SSL连接。这与IO :: Socket :: INET或类似的情况相同:如果已指定目标,则该目标将已经连接在new内部,并且不应执行附加的connectconnect_SSLin the documentation和示例也反映了这一点。

自2.045版(发布于02/2017)以来,如果SSL握手已完成,则IO :: Socket :: SSL将仅忽略connect_SSL。您可能使用的是IO :: Socket :: SSL的旧版本,其中connect_SSL将开始新的握手,即使TLS握手已经完成。 TLS连接内部的这种握手将导致您看到奇怪的错误。