2016-09-06 3 views
4

リモートSSLサーバーにメッセージを送信する方法があります。クラスは、コマンドラインから呼び出すことができるプログラムに埋め込まれているか、プログラムをデーモンとして起動し、要求に応じてクラスメソッドを呼び出すことができます。私はデーモンを起動するNet::Server::Forkを使用:IO ::ソケット:ソケットに印刷するときにSSLが改行を追加することがある

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が実行されているときに、ソケット上の各印刷が送信される内容に改行を追加することが分かりました。そこで、サーバは、ダイレクトコールとNet::Serverランニングとのコールに

[packet length in binary] 
Line 1 
Line 2 

--- [Received announced length + 6 bytes] 

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

を受けます。もちろん、これにより外部サーバーとの通信が切断されます。

私はNet::Serverがへの後の呼び出しを混乱させるIO::Socket::SSLのグローバル設定変数を設定していると思われますが、どの変数があるかわかりません。

注:私は自分のcommunicatorクラスに加えて、他のサーバーに接続するために外部ライブラリを使用しています。そのライブラリではIO::Socket::SSLも使用されており、同じ問題が発生しているので、IO::Socket::SSL$socket->print以外のものに置き換えることをお勧めします。

私は外部ライブラリにパッチを当てることができますが、アップデートがあるたびにそれを行う必要があります。

私のシステムはPerlの5.14、IO ::ソケット:: SSL 2.020とネットとDebianの7です:: IO ::ソケット:: SSLハンドル上のサーバー2.006

+0

あなたのパッケージ(およびモジュールのファイル名)大文字にする必要がありますので、 'MyServer.pm'と' Communicator.pm'には影響しません。また、これらのハッシュキーはすべて引用符を必要としないことを認識していますか? 'reverse_lookups => 1'は問題ありません。 – Borodin

+0

実際には、パッケージ名は大文字で始まります。混乱して申し訳ありません。私は、しかし、より良い構文ハイライトのためにハッシュキーの周りに引用符を持っていることを好む。 – Marcus

+0

ヒント: 'print(pack(" N "、bytes($ msg))、bytes($ msg)、print(pack(" N "、bytes ($ msg)); '(これはまた' bytes'への呼び出しがないことを明白にします!) – ikegami

答えて

3

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); 
}; 
+0

これは不正行為の根本的な理由のようです。 : – Borodin

+0

または、 ' - > printf("%s "、...)を使用してください。 – ikegami

+0

@ikegami:または単に' - > syswrite(...) ' –

関連する問題