SSL_Accept失败,SSL_get_error返回1

时间:2017-04-11 19:59:41

标签: c++ security ssl openssl

我是OpenSSL编程的新手。我的任务是编写一个可用的SSL代理。

但是,当我在Explore中启动代理时,ssl_accept()失败,错误代码为1。

为什么ssl_accept()失败?

int main(int argc, char **argv){
    checkArguments(argc, argv);
    initWSA();
    int port = atoi(argv[1]);
    struct sockaddr_in serverAddr = initAddr(port, std::string(""));
    SOCKET Client, Server;
    SSL_CTX *server_ctx = clear_method((SSL_METHOD *)TLSv1_1_server_method());

    if (!server_ctx)
    {
        ERR_print_errors_fp(stderr);
        std::cout << "ctx error";
    }
    load_certificate(server_ctx, "C:/Program Files/SnoopSpy/certificate/default.pem", "C:/Program Files/SnoopSpy/certificate/default.pem");
    open_socket(Server, serverAddr); //소켓 생성 함수
    SSL *server_ssl;

    while (true)
    {
        if ((Client = accept(Server, NULL, NULL)) == INVALID_SOCKET)
        {
            printf("error : accept\n");
            continue;
        }
        server_ssl = SSL_new(server_ctx); //설정된 Contexxt를 이용하여 SSL 세션의 초기화 작업을 수행한다.

        SSL_set_fd(server_ssl, Client);
        certificate(server_ssl, 0);
        char buf[BUFFER];
        memset(buf, NULL, BUFFER);
        recv(Client, buf, BUFFER, 0);
        cout << buf << endl;

        if (server_ssl == NULL)
        {
            std::cout << "SSL NULL" << std::endl;
        }
        std::cout << "Connection" << std::endl;
        std::cout << "암호키 얻음 : " << SSL_get_cipher(server_ssl) << std::endl;
        std::thread(forward, serverAddr, Client, server_ssl).detach();
    }
}

void forward(struct sockaddr_in serverAddr, SOCKET Client, SSL *server_ssl)
{
    int port = 443;
    char buf[BUFFER];
    char *recvbuf;
    int recvbuflen;
    std::string hostAddr, domainip;
    SOCKET RemoteSocket;
    struct sockaddr_in remoteAddr;
    SSL *client_ssl;
    int r;

    if ((r = SSL_accept(server_ssl)) == -1)
    {
        int err_SSL_get_error = SSL_get_error(server_ssl, r);
        int err_GetLastError = GetLastError();
        int err_WSAGetLastError = WSAGetLastError();
        int err_ERR_get_error = ERR_get_error();

        std::cout << "[DEBUG] SSL_accept() : Failed with return "
            << r << std::endl;
        std::cout << "[DEBUG] SSL_get_error() returned : "
            << err_SSL_get_error << std::endl;
        std::cout << "[DEBUG] Error string : "
            << ERR_error_string(err_SSL_get_error, NULL)
            << std::endl;
        std::cout << "[DEBUG] WSAGetLastError() returned : "
            << err_WSAGetLastError << std::endl;
        std::cout << "[DEBUG] GetLastError() returned : "
            << err_GetLastError << std::endl;
        std::cout << "[DEBUG] ERR_get_error() returned : "
            << err_ERR_get_error << std::endl;
        std::cout << "[DEBUG] GetLastError() returned : "
            << GetLastError << std::endl;
        std::cout << "+--------------------------------------------------+"
            << std::endl;

        return;
    }

    while ((recvbuflen = SSL_read(server_ssl, buf, BUFFER)) > 0)
    {

        SSL_CTX *client_ctx = clear_method((SSL_METHOD *)SSLv23_client_method());
        if (client_ctx == NULL)
        {
            cout << "client ctx error";
            break;
        }
        load_certificate(client_ctx, "C:/Program Files/SnoopSpy/certificate/default.crt", "C:/Program Files/SnoopSpy/certificate/default.key");

        recvbuf = (char *)calloc(recvbuflen, sizeof(char));
        memcpy(recvbuf, buf, recvbuflen);
        hostAddr = getAddr(recvbuf); //여기서 443 포트 번호 확인해야한다.
        std::cout << "site : " << hostAddr << endl;
        std::cout << "=============================================" << endl;
        std::cout << "클라이언트 => 프록시으로 전송 \n";
        std::cout << "=============================================" << endl;
        std::cout << "포트번호 :" << port << endl;
        std::cout << recvbuf << endl;

        if (hostAddr == "")
        {
            printf("Empty Host Address..\n");
            break;
        }
        else
            domainip = URLToAddrStr(hostAddr);

        if (domainip == "")
        {
            break;
        }

        remoteAddr = initAddr(port, domainip); //포트와 도메인 소켓에 넣기
        if ((RemoteSocket = socket(PF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET)
        {
            errorHandle("ERROR : Create a Socket for conneting to server\n", NULL);
        }
        std::cout << "remote 소켓생성 완료" << endl;
        if (connect(RemoteSocket, (struct sockaddr*) &remoteAddr, sizeof(remoteAddr)) == SOCKET_ERROR)
        {
            std::cout << "연결실패" << endl;
            break;
        }
        if ((client_ssl = SSL_new(client_ctx)) == NULL)
        {
            cout << "ssl is empty" << endl;
            break;
        }//자원 할당

        SSL_set_fd(client_ssl, RemoteSocket);
        if (SSL_connect(client_ssl) == NULL)
        {
            cout << " ssl not connect" << endl;
            break;
        }
        printf("SSL connection using %s\n", SSL_get_cipher(client_ssl));
        std::cout << "remote 연결" << endl;
        certificate(client_ssl, 1);
        cout << "Success server certificate" << endl;
        //다른 쓰레드 function
        std::thread(ssl_backward, server_ssl, client_ssl).detach();
        if (SSL_write(client_ssl, recvbuf, recvbuflen) == SOCKET_ERROR) //remote
        {
            printf("send to webserver failed.");
            continue;
        }
        std::cout << "프록시로 보냄\n" << endl;
    }
    memset(buf, NULL, BUFFER); //NULL 초기화
    //closesocket(Client);
    //SSL_free(server_ssl);
}

这是我的完整代码:

https://raw.githubusercontent.com/joongbu/OPENSSL_proxy/master/%EC%86%8C%EC%8A%A4.cpp

0 个答案:

没有答案