1

サーバーを再起動すると、libcurl ハンドル (簡単なインターフェイス) を使用したクライアントからサーバーへの通信が失敗します。

プログラム (以下に貼り付けたコード) は、curl ハンドルを作成し、url、証明書、タイムアウト、要求などのオプションを初期化します。その後、2 秒ごとの無限ループで、curl ハンドルを使用してサーバーに要求を送信します。

所見は以下のとおりです。

  1. プログラムが開始されると、クライアントからサーバーへの通信が適切に確立され、エラーなしでメッセージが交換されます。
  2. その後、サーバー マシンの電源を切りました。サーバーの電源がオフになると、curl_easy_perform がエラー コード = 28、「タイムアウトに達しました (connect() タイムアウト!)」で失敗しました。
  3. 次に、マシンの電源を入れました。マシンの起動中に、curl_easy_perform がエラー コード = 7、「サーバーに接続できませんでした (ホストに接続できませんでした)」で失敗することがわかりました。
  4. curl ハンドルがサーバー ポートに接続できるようになると、ssl_read エラー、curl エラー コード = 56、"Failure when receive data from the peer (SSL read: error:14094412:SSL routines:SSL3_READ_BYTES:sslv3 alert bad certificate, errno 0) が観察されました。 "
  5. さらに、curl_easy_perform はエラー コード = 58、「ローカル SSL 証明書に問題があります (クライアント証明書を使用できません (キーが見つからないか、パス フレーズが間違っていますか?)」) で失敗し、その後回復することはありません。
  6. プログラムを停止して再起動すると、接続は正常に確立されます。証明書に変更はありません。

curl_easy_performssl_read エラーで失敗する理由と、さらに先にエラー コード =58 (クライアント証明書を使用できません) と表示される理由を見つけることができません。

通信は最初とプロセスの再起動後も同じ証明書で機能するため、証明書に問題はないと思います。

openssl コマンドを試して、証明書が正しいことを確認しました。

Linux# openssl x509 -noout -modulus -in /opt/certstore/VcCombined.pem | openssl md5
fe18e9f364d18eba9f39690563aca836

Linux# openssl rsa -noout -modulus -in /opt/certstore/default.key | openssl md5
fe18e9f364d18eba9f39690563aca836

Linux# openssl verify -CAfile /opt/certstore/sslca/CACertificate.pem /opt/certstore/VcCombined.pem
/opt/certstore/VcCombined.pem: OK

この問題をさらにデバッグする方法がわかりません。openssl、curl、または私のプログラムに問題がある場合。

クライアント側:

curl --version

curl 7.25.0 (i686-pc-linux-gnu) libcurl/7.25.0 OpenSSL/0.9.8f zlib/1.2.1.2 libidn/0.5.6
Protocols: dict file gopher http https imap imaps pop3 pop3s rtsp smtp smtps telnet
Features: IDN IPv6 Largefile NTLM NTLM_WB SSL libz

サーバ側:

curl --version

curl 7.25.0 (i686-pc-linux-gnu) libcurl/7.25.0 OpenSSL/1.0.0e zlib/1.2.1.2 libidn/0.5.6
Protocols: dict file gopher http https imap imaps pop3 pop3s rtsp smtp smtps telnet
Features: IDN IPv6 Largefile NTLM NTLM_WB SSL libz

プログラム:

using namespace std;

static std::string buffer;

static int writer(char *data, size_t size, size_t nmemb, std::string *buffer)
{
    int result = 0;

    if (buffer != NULL)
    {
        buffer->append(data, size * nmemb);
        result = size * nmemb;
    }

    return result;
}


int main(void)
{
    CURL *curl;
    CURLcode res;
    char request[4096];
    char curl_errbuf[CURL_ERROR_SIZE];
    int bytes_read = 0;

    FILE *lFile = fopen("/tmp/getguid.xml", "r");
    if (lFile == NULL)
    {
        printf("fopen Error: %s\n", strerror(res));
        return 1;
    }

    memset(request, 0, 4096);
    bytes_read = fread(request, sizeof(request), 1, lFile);
    fclose(lFile);

    curl = curl_easy_init();

    struct curl_slist* lcurlHeaders = NULL;
    lcurlHeaders = curl_slist_append(lcurlHeaders, "Content-Type: text/xml");
    curl_easy_setopt(curl, CURLOPT_HTTPHEADER, lcurlHeaders);
    curl_easy_setopt(curl, CURLOPT_URL, "https://10.65.124.221:443/xmlInternal/service-reg/forward");
    curl_easy_setopt(curl, CURLOPT_TIMEOUT, 10);
    char *lUCSInterfaceName = "eth0";
    curl_easy_setopt(curl, CURLOPT_INTERFACE, lUCSInterfaceName);
    curl_easy_setopt(curl, CURLOPT_SSLCERT, "/opt/certstore/VcCombined.pem");
    curl_easy_setopt(curl, CURLOPT_SSLKEY, "/opt/certstore/default.key");
    curl_easy_setopt(curl, CURLOPT_CAINFO, "/opt/certstore/sslca/CACertificate.pem");
    curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
    curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 1L);
    curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 1L);
    curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1L);
    curl_easy_setopt(curl, CURLOPT_POST, 1);
    curl_easy_setopt(curl, CURLOPT_POSTFIELDS, (char*)request);
    curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, strlen(request));
    curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, curl_errbuf);
    curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, writer);
    curl_easy_setopt(curl, CURLOPT_WRITEDATA, &buffer);

    while(1)
    {
        memset(curl_errbuf, 0, CURL_ERROR_SIZE);
        res = curl_easy_perform(curl);

        if(CURLE_OK != res)
            printf("curl_easy_perform Error: %s (%s)\n", curl_easy_strerror(res), curl_errbuf);
        else
            printf("curl_easy_perform succes\n");

        sleep(2);
    }

    curl_slist_free_all(lCurlHeaders);
    curl_easy_cleanup(curl);
    return 0;
}
4

0 に答える 0