IO ::套接字:SSL有时会在套接字上打印时添加换行符

时间:2016-09-06 15:10:02

标签: perl ssl server newline

我有一个向远程SSL服务器发送消息的方法。该类嵌入在可以从命令行调用的程序中,或者程序可以作为守护程序启动,并可以根据请求调用类方法。我使用Net::Server::Fork启动守护进程:

package myserver;

use 5.10.1;
use strict;
use warnings;

use parent 'Net::Server::Fork';

myserver->run(
    'port'            => $main::config{'backend.ssl.host'} . '/ssl',
    'ipv'             => '*',
    'log_level'       => $main::config{'backend.loglevel'},
    'log_file'        => $main::config{'backend.logfile'},
    'pid_file'        => $main::config{'backend.pidfile'},
    'user'            => $main::config{'backend.user'},
    'group'           => $main::config{'backend.group'},
    'max_servers'     => $main::config{'backend.maxconnections'},
    'background'      => !$main::config{'backend.foreground'},
    'leave_children_open_on_hup' => 1,
    'allow'           => $main::config{'ip'},
    'reverse_lookups' => 1,
    'SSL_key_file'    => $main::config{'backend.ssl.key'},
    'SSL_cert_file'   => $main::config{'backend.ssl.crt'},
    'SSL_ca_file'     => $main::config{'backend.ssl.bundle'},
);

sub process_request {
    # call connect and sendframe if requested
};

外部通信类与IO::Socket::SSL连接,并通过将数据包长度作为4字节标头添加前发送数据,然后按原样发送消息:

package communicator;

use 5.10.1;
use strict;
use warnings;

use IO::Socket::SSL;

sub connect {
    my $self   = shift @_;
    my $server = shift @_;
    my @field    = split /\:/, $server;

    my $socket;

    $socket = IO::Socket::SSL->new(
        'PeerAddr' => $field[0],
        'PeerPort' => $field[1],
        'Blocking' => 1,
    );

    if ( $socket ) {
        binmode $socket;
    }
    else {
        # error handling
    };

    $self->{'SOCK'} = $socket;
};

sub sendframe {
    my $self = shift @_;
    my $msg  = shift @_;

    if ($self->{'SOCK'}) {
        my $length = pack("N", bytes($msg));
        ($self->{'SOCK'})->print($length);
        ($self->{'SOCK'})->print($msg);
    };
};

从命令行调用时可以正常工作,但在作为Net::Server进程运行时失败。我已经尝试记录发送到远程服务器的内容,但两种方法的日志文件都是相同的。

我编写了一个最小的SSL服务器来捕获内容,并发现当Net::Server运行时,套接字上的每个打印都会为正在发送的内容添加换行符。所以服务器收到

[packet length in binary]Line 1
Line 2
--- [Received announced length + 4 bytes]

直接通话

[packet length in binary]
Line 1
Line 2

--- [Received announced length + 6 bytes]

Net::Server正在运行的通话中。当然这会破坏与外部服务器的通信。

我怀疑Net::ServerIO::Socket::SSL中设置了一个全局配置变量,混淆了对sendframe的后续调用,但我无法确定它可能是哪个变量。

请注意我正在使用外部库连接到我自己的communicator类之外的其他服务器。该库也使用IO::Socket::SSL并遇到同样的问题,因此我更倾向于使用IO::Socket::SSL以外的其他内容修复$socket->print

我可以修补外部库,但每次有更新时都可能必须这样做。

我的系统是Debian 7,包含Perl 5.14,IO :: Socket :: SSL 2.020和Net :: Server 2.006

1 个答案:

答案 0 :(得分:3)

IO :: Socket :: SSL句柄上的

print在其他文件句柄上的行为类似print,因为它尊重$\的设置。来自perldoc perlvar

  $\      The output record separator for the print operator.  
          If defined, this value is printed after the last of print's
          arguments.  Default is "undef".

由于默认情况下此变量为undef,因此只有有人明确设置此变量时才会发生变化。我看不到Net :: Server在任何地方设置这个变量。也许它在您自己的代码或您使用的其他模块中?如果您不会影响其他代码,您可以对变量进行本地化,即

if ($self->{'SOCK'}) {
    local $\ = undef; ### make sure to disable side effects
    my $length = pack("N", bytes($msg));
    ($self->{'SOCK'})->print($length);
    ($self->{'SOCK'})->print($msg);
};