C++ SSL\u接受失败,SSL\u获取\u错误返回1

C++ SSL\u接受失败,SSL\u获取\u错误返回1,c++,security,ssl,openssl,C++,Security,Ssl,Openssl,我是OpenSSL编程新手。我的任务是编写一个工作的SSL代理 但是,当我在Explore中启动代理时,ssl\u accept()失败,错误代码为1 为什么ssl\u accept()失败了 int main(int argc, char **argv){ checkArguments(argc, argv); initWSA(); int port = atoi(argv[1]); struct sockaddr_in serverAddr = initAdd

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

但是,当我在Explore中启动代理时,
ssl\u accept()
失败,错误代码为1

为什么
ssl\u 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);
}
int main(int argc,char**argv){
校验参数(argc、argv);
initWSA();
int port=atoi(argv[1]);
serverAddr=initAddr(端口,std::string(“”)中的struct sockaddr_;
SOCKET客户端、服务器;
SSL_CTX*服务器_CTX=清除方法((SSL_方法*)TLSv1_1_服务器_方法());
如果(!服务器_ctx)
{
错误打印错误fp(stderr);

std::cout
main()
正在使用
TLSv1\u server\u方法()
,这意味着客户端必须使用
TLSv1\u client\u方法()
进行匹配。如果要允许版本协商,请改用
SSLv23\u server\u方法()
。但更重要的是,在调用
ssl\u accept()之前,您正在调用
recv()
,因此您可能正在阅读
SSL_accept()
期望的SSL握手部分,这就是它失败的原因。根本不要调用
recv()
。很明显,您不了解TCP流是如何工作的,或者HTTPS代理是如何工作的(这种方法不是HTTPS代理的实现方式)@RemyLebeau首先非常感谢你的建议。我查看了它,但找不到我需要的信息。你知道在哪里可以找到https代理的示例代码吗?再次感谢。请阅读HTTP
CONNECT
方法。这是web浏览器通过HTTP代理建立https连接的方法。它不涉及SSL/TLS,因为SSL/TLS握手必须在建立代理连接后与目标服务器进行。代理只是来回传递原始数据,可能是SSL/TLS加密数据。@RemyLebeau谢谢。我正在听取您的建议并重新创建逻辑。在收到HTTP连接后,我们发送了HTTP/1.0 200使用发送功能建立连接。是否必须将接收的连接替换为recv()使用GET方法并将其发送到服务器?否。浏览器连接到代理并发送
CONNECT
。然后代理连接到指定的主机/端口,如果成功,则将200发送回浏览器。然后,浏览器发送到代理的任何原始数据必须按原样发送到服务器,服务器发送到代理的任何原始数据都必须按原样发送y必须按原样发送到浏览器。一旦
CONNECT
成功,从代理的角度来看,连接不再是HTTP,从客户端+服务器的角度来看,它可能是HTTP。