1

マルチスレッドのクライアント サーバー アプリケーションを C で実装しようとしています。接続固有のコードは次のとおりです。

サーバ:

SSL_load_error_strings();
SSL_library_init();
OpenSSL_add_all_ciphers();
if((ctx->ssl_ctx = SSL_CTX_new(TLSv1_server_method())) == NULL) {
  tproxy_error_die("unable to initialize SSLv3 methods", 1);
}
SSL_CTX_set_options(ctx->ssl_ctx, SSL_OP_ALL);
SSL_CTX_set_timeout(ctx->ssl_ctx, 300);
if(!SSL_CTX_use_certificate_chain_file(ctx->ssl_ctx, ctx->cert_bundle)) {
  tproxy_error_die("unable to read certificate bundle file", 1);
}
if(strlen(ctx->key_file_pw)) {
  SSL_CTX_set_default_passwd_cb(ctx->ssl_ctx, private_key_pass_callback);
  SSL_CTX_set_default_passwd_cb_userdata(ctx->ssl_ctx, (void *)ctx);
}
if(!SSL_CTX_use_RSAPrivateKey_file(ctx->ssl_ctx, ctx->key_file, SSL_FILETYPE_PEM)) {
  tproxy_error_die("unable to read key file", 1);
}
SSL_CTX_set_verify(ctx->ssl_ctx, SSL_VERIFY_NONE, NULL);
SSL_CTX_set_info_callback(ctx->ssl_ctx, apps_ssl_info_callback);
[...]
con->sock = accept(ctx->socket[i], (struct sockaddr *)&in_socket, &s_size);
/* make the accepted socket non-blocking */
if(ioctl(con->sock, FIONBIO, (char *)&enable) < 0) {
  tproxy_error_die("cannot set socket flags", 1);
}
/* create a new SSL context to handle the connection with the peer */
con->ssl = SSL_new(ctx->ssl_ctx);
SSL_set_mode(con->ssl, SSL_MODE_AUTO_RETRY | SSL_MODE_ENABLE_PARTIAL_WRITE);

/* complete ssl connection */
con->sbio = BIO_new_socket(con->sock, BIO_NOCLOSE);
SSL_set_bio(con->ssl, con->sbio, con->sbio);
/* set chipher */
if (SSL_set_cipher_list(con->ssl,"AES128-SHA") <= 0) {
  tproxy_error_die("unable to set chipher", 1);
}
/* do not require a valid client certificate */
SSL_set_verify(con->ssl, SSL_VERIFY_NONE, NULL);

後で、SSL_read() と SSL_write() を使用して読み書きします (戻りコードとして -1 を使用すると、SSL_get_error() が評価され、その結果、コード内で同じ関数が繰り返されます)。

ただし、アプリケーション ハンドシェイク (クライアントとサーバー間で交換される数バイト) は魅力的に機能します。しかし、サーバーが (アプリケーション ハンドシェイク後に) 4 バイト以上をクライアントに送信すると、サーバーの SSL_write が送信した正確なバイト数を返したとしても (SSL_ERROR_SYSCALL がSSL エラーおよびシステム errno は 0 のままです)。ソケットが閉じられていませんでした。

誰も手がかりを持っていますか?opensslアプリケーションをさらにデバッグする方法はありますか?

クライアントからの msg_callback の出力は次のとおりです。

SSL_connect:before/connect initialization
SSL_connect:SSLv3 write client hello A
SSL_connect:error in SSLv3 read server hello A
SSL_connect:SSLv3 read server hello A
SSL_connect:SSLv3 read server certificate A
SSL_connect:SSLv3 read server done A
SSL_connect:SSLv3 write client key exchange A
SSL_connect:SSLv3 write change cipher spec A
SSL_connect:SSLv3 write finished A
SSL_connect:SSLv3 flush data
SSL_connect:error in SSLv3 read server session ticket A
SSL_connect:SSLv3 read server session ticket A
SSL_connect:SSLv3 read finished A

--->ここで閉じます

サーバーからの msg_callback の出力は次のとおりです。

SSL_accept:before/accept initialization
SSL_accept:error in SSLv3 read client hello B
SSL_accept:SSLv3 read client hello B
SSL_accept:SSLv3 write server hello A
SSL_accept:SSLv3 write certificate A
SSL_accept:SSLv3 write server done A
SSL_accept:SSLv3 flush data
SSL_accept:error in SSLv3 read client certificate A
SSL_accept:error in SSLv3 read client certificate A
SSL_accept:error in SSLv3 read client certificate A
SSL_accept:error in SSLv3 read client certificate A
SSL_accept:error in SSLv3 read client certificate A
SSL_accept:error in SSLv3 read client certificate A
SSL_accept:error in SSLv3 read client certificate A
SSL_accept:error in SSLv3 read client certificate A
SSL_accept:error in SSLv3 read client certificate A
SSL_accept:error in SSLv3 read client certificate A
SSL_accept:SSLv3 read client key exchange A
SSL_accept:SSLv3 read finished A
SSL_accept:SSLv3 write session ticket A
SSL_accept:SSLv3 write change cipher spec A
SSL_accept:SSLv3 write finished A
SSL_accept:SSLv3 flush data

--->ここで閉じます

tcpdump は、che tcp-fin が最初にクライアントから送信されることを示しています。しかし、サーバーが「killing」の 5 バイトを送信しない場合、クライアントは SSL リンクを介してアプリケーション キープアライブ メッセージを無限に送信できます。

SSL_write がそのような方法で相手側に警告できるのはどのような状況ですか? また、この動作をどのようにデバッグできますか?

4

0 に答える 0