【问题标题】:IO::Socket::SSL - establishing client connectionIO::Socket::SSL - 建立客户端连接
【发布时间】:2019-01-21 04:01:25
【问题描述】:

根据 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 - 如果重要的话)。

【问题讨论】:

  • 您确定服务器是 SSL 服务器吗?
  • 您的“与连接管理有关的员工”是否包括'listen' => $ssl
  • 请提供一个足够完整的示例,该示例实际上显示了 SSL 在服务器端的使用方式(即 # Staff to do with connections management 中的魔法)。除此之外:WebSockets 不是相同的套接字,即要与 WebSockets 服务器通信,您需要使用 WebSockets 协议,而不仅仅是普通的 TCP 或 SSL。
  • 我在连接管理器中添加了这些东西 - 但我认为它不会影响连接客户端。

标签: perl ssl


【解决方案1】:

... 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_SSL。这也反映在in the documentation 和示例中。

从版本 2.045(2017 年 2 月发布)开始,如果 SSL 握手已经完成,IO::Socket::SSL 将简单地忽略 connect_SSL。您可能使用的是旧版本的 IO::Socket::SSL,即使 TLS 握手已经完成,connect_SSL 也会开始新的握手。 TLS 连接中的这种握手会导致您看到的奇怪错误。

【讨论】:

  • 我编辑了这个问题,提到服务器假设在该特定端口上运行 SSL,除非我错过了什么......
  • 关于预配置:这不是SMTP,还需要一些配置吗?
  • @Xerix: SMTP 不是唯一的协议,其中只有在一些纯文本命令到 TLS 之后才会升级连接。
  • 我删除了“connect_SSL”,没有错误:)
  • @Xerix:这很奇怪。如果 SSL 握手已经完成,它应该简单地忽略 connect_SSL。但也许您的实际程序比您展示的示例更复杂。
猜你喜欢
  • 1970-01-01
  • 2021-09-14
  • 2022-09-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-02-29
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多