2016-09-19 28 views
0

opensslサーバー/クライアントアプリケーションを作成できません。今のところ単純なC++バージョンを作成しました。これは基本的にC言語のサンプルからコピーされています。
問題は、メソッドとしてSSLv23を使用するかTLSv1_2を使用するかによって、常にSSL23_GET_SERVER_HELLO:unknown protocolまたはSSL3_GET_RECORD:wrong version numberのいずれかになります。私はここで読む:Check Server security protocol using openssl、私はそうのようなオプションを除くとSSLv23を使用するsuposedてること:エラー "SSL23_GET_SERVER_HELLO:不明なプロトコル"

SSL_library_init(); 
SSL_METHOD *method; 
SSL_CTX *ctx; 
OpenSSL_add_all_algorithms();  /* load & register all cryptos, etc. */ 
SSL_load_error_strings();   /* load all error messages */ 
method = const_cast<SSL_METHOD*>(TLSv1_2_server_method());  /* create new server-method instance */ 
if (method == NULL){ 
    exit(0); 
} 
ctx = SSL_CTX_new(method);   /* create new context from method */ 

const long flags = SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_NO_COMPRESSION; 
SSL_CTX_set_options(ctx, flags); 

if (ctx == NULL) 
{ 
    ERR_print_errors_fp(stderr); 
    abort(); 
} 

これが説明するように、私はunknown protocolエラーを取得していますので、しかし、動作するようには思えません。私はそれをテストするには、次のコマンドを使用しています:

openssl s_client -connect localhost:5002 -tls1_2 
openssl s_client -connect localhost:5002 -tls1_1 
openssl s_client -connect localhost:5002 -tls1 

応答が常にある:

二行目は、メソッド、変数の状態に応じて、2件の名前付きのエラーメッセージが切り替わり
CONNECTED(00000003) 
140310636811928:error:1408F10B:SSL routines:SSL3_GET_RECORD:wrong 

version number:s3_pkt.c:362: 
--- 
no peer certificate available 
--- 
No client certificate CA names sent 
--- 
SSL handshake has read 5 bytes and written 7 bytes 
--- 
New, (NONE), Cipher is (NONE) 
Secure Renegotiation IS NOT supported 
Compression: NONE 
Expansion: NONE 
No ALPN negotiated 
SSL-Session: 
    Protocol : TLSv1 
    Cipher : 0000 
    Session-ID: 
    Session-ID-ctx: 
    Master-Key: 
    Key-Arg : None 
    PSK identity: None 
    PSK identity hint: None 
    SRP username: None 
    Start Time: 1474320796 
    Timeout : 7200 (sec) 
    Verify return code: 0 (ok) 
--- 

何かありますか、私は完全に間違っているか、まったく異なる場所にある問題ですか?

EDIT: サーバーコードの残り:接続を使用することができますポート、certfileにしてキーファイル

  • 実行start()
  • 実行accept_con()、と

    #include <stdio.h> 
    #include <unistd.h> 
    #include <malloc.h> 
    #include <string.h> 
    #include <sys/socket.h> 
    #include <resolv.h> 
    #include <openssl/ssl.h> 
    #include <openssl/err.h> 
    
    
    
    // Own libs 
    #include "SSLServer.h" 
    #include "Logger.h" 
    #include "Connection.h" 
    
    
    #define SERVER_LOG "./log/server.log" 
    #define CONNECTION_LOG "./log/server.log" 
    
    #define FATAL 0 
    #define ERROR 1 
    #define WARNING 2 
    #define INFO 3 
    #define DEBUG 4 
    #define LOG_LEVEL 5 
    
    using namespace std; 
    
    #ifndef CLI_STRUCT 
    #define CLI_STRUCT 
    struct cli{ 
        int fdsock; 
        struct sockaddr *cli_addr; 
        socklen_t clilen; 
    }; 
    #endif 
    
    // name is program 
    string SSLServer::convert_int_to_string(int n){ 
        std::ostringstream ss; 
        int num = n; 
        ss << num; 
        return ss.str(); 
    } 
    
    
    SSL_CTX* SSLServer::InitServerCTX(void){ 
        SSL_library_init(); 
        SSL_METHOD *method; 
        SSL_CTX *ctx; 
        OpenSSL_add_all_algorithms();  /* load & register all cryptos, etc. */ 
        SSL_load_error_strings();   /* load all error messages */ 
        method = const_cast<SSL_METHOD*>(SSLv23_server_method());  /* create new server-method instance */ 
        if (method == NULL){ 
         exit(0); 
        } 
        ctx = SSL_CTX_new(method);   /* create new context from method */ 
    
        const long flags = SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_NO_COMPRESSION; 
        SSL_CTX_set_options(ctx, flags); 
    
        if (ctx == NULL) 
        { 
         ERR_print_errors_fp(stderr); 
         abort(); 
        } 
        return ctx; 
    } 
    
    void SSLServer::LoadCertificates(SSL_CTX* ctx, const char* CertFile, const char* KeyFile) 
    { 
        /* set the local certificate from CertFile */ 
        if (SSL_CTX_use_certificate_file(ctx, CertFile, SSL_FILETYPE_PEM) <= 0) 
        { 
         ERR_print_errors_fp(stderr); 
         abort(); 
        } 
        /* set the private key from KeyFile (may be the same as CertFile) */ 
        if (SSL_CTX_use_PrivateKey_file(ctx, KeyFile, SSL_FILETYPE_PEM) <= 0) 
        { 
         ERR_print_errors_fp(stderr); 
         abort(); 
        } 
        /* verify private key */ 
        if (!SSL_CTX_check_private_key(ctx)) 
        { 
         fprintf(stderr, "Private key does not match the public certificate\n"); 
         abort(); 
        } 
    } 
    
    // Constructor which takes a portno 
    SSLServer::SSLServer(unsigned short port, string CertFile, string KeyFile):logger(Logger{SERVER_LOG}){ 
        bzero((char *) &serv_addr, sizeof(serv_addr)); 
        setFamily(AF_INET); 
        serv_addr.sin_addr.s_addr = INADDR_ANY; 
        setPort(port); 
        backlog = 3; 
        logger.setLogLevel(LOG_LEVEL); 
        ctx = InitServerCTX(); 
        LoadCertificates(ctx, CertFile.c_str(), KeyFile.c_str()); 
        reload(); 
    } 
    
    // Reload all important information in case something changed 
    void SSLServer::reload(){ 
        this->sockfd = socket(AF_INET, SOCK_STREAM, 0); 
        int yes = 1; 
        // lose the pesky "Address already in use" error message 
        if (setsockopt(sockfd,SOL_SOCKET,SO_REUSEADDR,&yes,sizeof(int)) == -1) { 
         perror("setsockopt"); 
         exit(1); 
        } 
        if (bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0) 
        { 
         string error = "FATAL: could not bind socket! "; 
         error.append(strerror(errno)); 
         logger.log(FATAL, error); 
    
         exit(1); 
        } 
        state = READY; 
    } 
    void SSLServer::setLogLevel(int level){ 
        logger.setLogLevel(level); 
    } 
    // Setter 
    void SSLServer::setPort(unsigned short port){ 
        this->portno = port; 
    
        // Convert portno to needed endian format 
        serv_addr.sin_port = htons(portno); 
    } 
    void SSLServer::setFamily(short fam){ 
        this->serv_addr.sin_family = fam; 
    } 
    void SSLServer::setAddr(struct in_addr sin_addr){ 
        this->serv_addr.sin_addr = sin_addr; 
    } 
    
    // Start listening to given Port 
    void SSLServer::start(){ 
        string start = "start server on port "; 
        if(state == RUNNING){ 
         logger.log(WARNING, "Already running."); 
         return; 
        } 
    
        // message start port at No 
        start = start.append(convert_int_to_string(portno)); 
        logger.log(2, start); 
        if (listen(sockfd, backlog) < 0){ 
         logger.log(FATAL, "could not start server!"); 
        } 
        logger.log(DEBUG, "server started."); 
        state = RUNNING; 
    } 
    
    // Stop Server (may be restarted) 
    int SSLServer::stop(){ 
        int fd = sockfd; 
        if (state != RUNNING) { 
         logger.log(WARNING, "Already stopped"); 
         perror("Already stopped"); 
         return 1; 
        } 
        if (fd >= 0) { 
         int err = 1; 
         socklen_t len = sizeof err; 
         if (-1 == getsockopt(fd, SOL_SOCKET, SO_ERROR, (char *)&err, &len)){ 
          perror("getsocketopt"); 
          return 1; 
         } 
         if (err) errno = err; 
         if (shutdown(fd, SHUT_RDWR) < 0) // secondly, terminate the 'reliable' delivery 
          if (errno != ENOTCONN && errno != EINVAL){ // SGI causes EINVAL 
           perror("shutdown"); 
           return 1; 
          } 
    
         if (::close(fd) < 0){ // finally call close() 
          perror("close"); 
          return 1; 
         } 
    
         SSL_CTX_free(ctx); 
         state = STOPPED; 
         return 0; 
        } 
        perror("wrong socket"); 
        return 1; 
    } 
    
    void SSLServer::ShowCerts(SSL* ssl) 
    { X509 *cert; 
        char *line; 
    
        cert = SSL_get_peer_certificate(ssl); /* Get certificates (if available) */ 
        if (cert != NULL) 
        { 
         printf("Server certificates:\n"); 
         line = X509_NAME_oneline(X509_get_subject_name(cert), 0, 0); 
         printf("Subject: %s\n", line); 
         free(line); 
         line = X509_NAME_oneline(X509_get_issuer_name(cert), 0, 0); 
         printf("Issuer: %s\n", line); 
         free(line); 
         X509_free(cert); 
        } 
        else 
         printf("No certificates.\n"); 
    } 
    
    void SSLServer::Servlet(SSL* ssl) { /* Serve the connection -- threadable */ 
        char buf[1024]; 
        char reply[1024]; 
        int sd, bytes; 
        const char* HTMLecho="<html><body><pre>%s</pre></body></html>\n\n"; 
    
        if (SSL_accept(ssl) <= 0)     /* do SSL-protocol accept */ 
         ERR_print_errors_fp(stderr); 
        else 
        { 
         ShowCerts(ssl);        /* get any certificates */ 
         bytes = SSL_read(ssl, buf, sizeof(buf)); /* get request */ 
         if (bytes > 0) 
         { 
          buf[bytes] = 0; 
          printf("Client msg: \"%s\"\n", buf); 
          sprintf(reply, HTMLecho, buf);   /* construct reply */ 
          SSL_write(ssl, reply, strlen(reply)); /* send reply */ 
         } 
         else 
          ERR_print_errors_fp(stderr); 
        } 
        sd = SSL_get_fd(ssl);       /* get socket connection */ 
        SSL_free(ssl);         /* release SSL state */ 
        close(sd);          /* close connection */ 
    } 
    
    // accept a connection and return struct cli (in definition; used for accept_con) 
    cli SSLServer::accept_cli(){ 
        if(state != RUNNING){ 
         logger.log(FATAL, "Server not running"); 
         exit(1); 
        } 
        struct sockaddr_in addr; 
        socklen_t clilen = sizeof(addr); 
        struct cli ret; 
        logger.log(DEBUG, "wait for client..."); 
        ret.fdsock = accept(sockfd, (struct sockaddr *)&addr, &clilen); 
        if (ret.fdsock == -1){ 
         string msg = "FATAL: "; 
         msg.append(strerror(errno)); 
         logger.log(FATAL, msg); 
         exit(1); 
        } 
        ret.cli_addr = (struct sockaddr *)&addr; 
        ret.clilen = clilen; 
        SSL *ssl = SSL_new(ctx); 
        SSL_set_fd(ssl, ret.fdsock); 
    
        logger.log(DEBUG, "client added."); 
        return ret; 
    } 
    
    
    // accept a connection an return Connection object 
    Connection SSLServer::accept_con(){ 
        fflush(stdout); 
        Connection con(accept_cli()); 
        string msg = con.getIp(); 
        logger.log(DEBUG, msg); 
        return con; 
    
    } 
    
    1. コールコンストラクタものを送るには
    ここ

    私の基本的な主(あなたは成功した作成された接続のように、上記のコードとParsedConnectionとしてAdvancedServerを見ることができます):

    #include <stdlib.h> 
    #include <stdio.h> 
    #include <string.h> 
    #include <thread> 
    #include <unistd.h> 
    #include <signal.h> 
    
    #include "SSLServer.h" 
    #include "AdvancedServer.h" 
    #include "Connection.h" 
    #include "ParsedConnection.h" 
    #include "ConnectionThread.h" 
    #include "SomeClientTest.h" 
    
    static char* cert = "cert.pem"; 
    static char* key = "key.pem"; 
    AdvancedServer se(5002, cert,key); 
    void run(ParsedConnection &con){ 
        sleep(10); 
        con.send("Hi there"); 
        con.close(); 
    } 
    
    void ctrl_c(int s){ 
    
          std::cout << "server returns: " << se.stop() << std::endl; 
          exit(1); 
    
    } 
    
    
    
    int main(int argc, char *argv[]){ 
        // The actual server 
        if (argc >= 2){ 
         se = AdvancedServer(atoi(argv[1]), cert, key); 
        } else { 
         std::cout << "usage: " << argv[0] << " <port> <cert> <key> [loglevel]" << std::endl; 
        } 
    
        if (argc >= 3){ 
         se.setLogLevel(atoi(argv[2])); 
        } 
    
    
    
        struct sigaction sigIntHandler; 
    
        sigIntHandler.sa_handler = ctrl_c; 
        sigemptyset(&sigIntHandler.sa_mask); 
        sigIntHandler.sa_flags = 0; 
    
        sigaction(SIGINT, &sigIntHandler, NULL); 
    
        se.start(); 
        //Test ends 
    
    
        while(1){ 
         ParsedConnection con = se.accept_con(); 
         ConnectionThread tt; 
         std::thread t(&ConnectionThread::run, &tt, con); 
         t.detach(); 
        } 
        return 0; 
    } 
    

    EDIT 私はダンプがあるTCP、そのクライアントとサーバでから見ることができるすべての少なくとも1つの接続試行の出力です。

    14:23:30.734757 IP localhost.57954 > localhost.rfe: Flags [S], seq 3307815845, win 43690, options [mss 65495,sackOK,TS val 230050 ecr 0,nop,wscale 7], length 0 
    14:23:30.734771 IP localhost.rfe > localhost.57954: Flags [S.], seq 347842069, ack 3307815846, win 43690, options [mss 65495,sackOK,TS val 230050 ecr 230050,nop,wscale 7], length 0 
    14:23:30.734784 IP localhost.57954 > localhost.rfe: Flags [.], ack 1, win 342, options [nop,nop,TS val 230050 ecr 230050], length 0 
    14:23:30.734907 IP localhost.57954 > localhost.rfe: Flags [P.], seq 1:198, ack 1, win 342, options [nop,nop,TS val 230050 ecr 230050], length 197 
    14:23:30.735318 IP localhost.rfe > localhost.57954: Flags [P.], seq 1:25, ack 198, win 350, options [nop,nop,TS val 230050 ecr 230050], length 24 
    14:23:30.735334 IP localhost.57954 > localhost.rfe: Flags [.], ack 25, win 342, options [nop,nop,TS val 230050 ecr 230050], length 0 
    14:23:30.735359 IP localhost.57954 > localhost.rfe: Flags [P.], seq 198:205, ack 25, win 342, options [nop,nop,TS val 230050 ecr 230050], length 7 
    14:23:30.735392 IP localhost.rfe > localhost.57954: Flags [F.], seq 25, ack 205, win 350, options [nop,nop,TS val 230050 ecr 230050], length 0 
    14:23:30.735407 IP localhost.rfe > localhost.57954: Flags [R.], seq 26, ack 205, win 350, options [nop,nop,TS val 230050 ecr 230050], length 0 
    
  • +0

    おそらくHTTPSではなくHTTPを提供しています。あなたは、受け入れられるまで、秘密鍵と証明書の読み込みを含む、より多くのサーバーコードを表示する必要があります。また、使用されているOpenSSLのバージョンを記述する必要があります。あなたが使っているものを見るには 'netcat'を使います。プレーンテキストまたはランダムな文字です。 OpenSSL wikiの[SSL/TLS Client](https://wiki.openssl.org/index.php/SSL/TLS_Client)も参照してください。彼らにはwiki上のサーバ例もあります。しかしそれは印象的ではありません。 – jww

    +0

    tcpdumpを入手してみてください。それは何かを示すはずです。 – Prabhu

    答えて

    関連する問題