HTTPS-прокси
От: solvitz Украина  
Дата: 06.10.16 06:11
Оценка:
Добрый день!
Подскажите пожалуйста, у меня такая ситуация, написал свой HTTP\HTTPS прокси-сервер, добавил слушающий порт на адресе 127.0.0.1:8080 в системные настройки прокси Windows. Соответственно этот прокси по умолчанию используют IE, Chrome и Opera, только в FF надо прописывать его вручную. Сразу оговорюсь, HTTP работает нормально, а вот с HTTPS проблема. Кратко опишу алгоритм моих действий:
    Создаю слушающий сокет
    В цикле дожидаюсь коннекта от браузера
    Акцептирую коннект
    Создаю новый поток и передаю ему новый сокет в качестве параметра
    Принимаю в блокирующем режиме данные с браузера
CONNECT example.com:443 HTTP/1.1
Host: example.com:443
Connection: keep-alive
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.143 Safari/537.36

    Парсю этот пакет и вытаскиваю из него имя хоста и порт
    Создаю новый сокет и соединяюсь с этим сервером
    Отсылаю браузеру ответ
HTTP/1.1 200 Connection Established

    Перевожу два соединения в неблокирующий режим
    Начинаю гонять пакеты между брайзером и веб-сервером, при этом в зашифрованные данные не лезу, просто передаю пакеты от браузера к серверу и обратно.
Вся проблема в том, что когда я отсылаю браузеру ответ HTTP/1.1 200 Connection Established\r\n\r\n, то он обрывает соединение, а Chrome в частности выдает эту ошибку — ERR_TUNNEL_CONNECTION_FAILED. Думал может что с системой, но поставил тот же SmallProxy и он отлично работает. Смотрел сниффером его ответ, он передает то же самое что и я. Подскажите из-за чего браузер рвет коннект. Зараннее спасбо за помощь!
DWORD WINAPI session_thread(LPVOID session_connect)
{
    client_struct *conn = session_connect;
    request_struct *request = NULL;
    response_struct *response = NULL;
    proxy_struct *proxy = NULL;
    fd_set read_fds;
    LPVOID proxy_buffer = NULL;
    LPVOID request_buffer = NULL;
    LPVOID response_buffer = NULL;
    DWORD dwResult = 0;
    LONG from_timeout = BROWSER_TIMEOUT;
    LONG to_timeout = SERVER_TIMEOUT;
    LONG nbio = TRUE;
    LONG nRead = 0;
    LONG nSent = 0;
    LONG nProxySize = 0;
    LONG nReqSize = 0;
    LONG nRespSize = 0;
    BOOL bFlag = FALSE;
    BOOL is_ssl = FALSE;
    CHAR from_buff[MAX_PACKET_SIZE];
    CHAR to_buff[MAX_PACKET_SIZE];
    CHAR szResponse[] = "HTTP/1.1 200 Connection Established\r\n\r\n";

    if (setsockopt(conn->fsock, SOL_SOCKET, SO_RCVTIMEO, (PCHAR)&from_timeout, sizeof(LONG)))
    {
        goto cleanup;
    }

    ZeroMemory(&from_buff, sizeof(from_buff));

    do
    {
        nRead = recv(conn->fsock, &from_buff, MAX_PACKET_SIZE, 0);
        if (nRead > 0)
        {
            if (!bFlag)
            {
                proxy_buffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, nRead);
                if (proxy_buffer == NULL)
                {
                    goto cleanup;
                }
                bFlag = TRUE;
            }
            else
            {
                proxy_buffer = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, proxy_buffer, nRead + nProxySize);
                if (proxy_buffer == NULL)
                {
                    goto cleanup;
                }
            }

            CopyMemory(proxy_buffer + nProxySize, &from_buff, nRead);
            nProxySize = nProxySize + nRead;
        }
    } while (nRead > 0);

    if (nRead)
    {
        proxy = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(proxy_struct));

        proxy->header = proxy_buffer;
        proxy->header_size = nProxySize;

        dwResult = proxy_handler(proxy);
        if (!dwResult)
        {
            goto cleanup;
        }
    }
    else
    {
        goto cleanup;
    }

    CopyMemory(&conn->to, &proxy->sa, sizeof(struct sockaddr_in));

    if ((conn->tsock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET)
    {
        goto cleanup;
    }

    if (connect(conn->tsock, (struct sockaddr*)&conn->to, sizeof(struct sockaddr_in)) ==  SOCKET_ERROR)
    {
        goto cleanup;
    }

    if (ntohs(conn->to.sin_port)%2 != 0)
    {
        is_ssl = TRUE;
    }

    if (is_ssl)
    {
        send(conn->fsock, &szResponse, sizeof(szResponse), 0);
    }
    else
    {
        send(conn->tsock, proxy_buffer, nProxySize, 0);
    }

    if (ioctlsocket(conn->tsock, FIONBIO, &nbio) == SOCKET_ERROR)
    {
        goto cleanup;
    }

    if (ioctlsocket(conn->fsock, FIONBIO, &nbio) == SOCKET_ERROR)
    {
        goto cleanup;
    }

    for (;;)
    {
        FD_ZERO(&read_fds);

        FD_SET(conn->tsock, &read_fds);
        FD_SET(conn->fsock, &read_fds);

        if (select(0, &read_fds, NULL, NULL, NULL) == SOCKET_ERROR)
        {
            goto cleanup;
        }

        if (FD_ISSET(conn->fsock, &read_fds))
        {
            if ((nRead = recv(conn->fsock, &from_buff, MAX_PACKET_SIZE, 0)) > 0)
            {
                nSent = send(conn->tsock, &from_buff, nRead, 0);
                if (nSent < 0 && ((WSAGetLastError() != WSAEWOULDBLOCK)))
                {
                    goto cleanup;
                }
            }
            else
            {
                goto cleanup;
            }
        }

        if (FD_ISSET(conn->tsock, &read_fds))
        {
            if ((nRead = recv(conn->tsock, &to_buff, MAX_PACKET_SIZE, 0)) > 0)
            {
                nSent = send(conn->fsock, &to_buff, nRead, 0);
                if (nSent < 0 && ((WSAGetLastError() != WSAEWOULDBLOCK)))
                {
                    goto cleanup;
                }
            }
            else
            {
                goto cleanup;
            }
        }
    }

cleanup:
    if (conn->fsock) shutdown(conn->fsock, SD_BOTH);
    if (conn->fsock) closesocket(conn->fsock);
    if (conn->tsock) shutdown(conn->tsock, SD_BOTH);
    if (conn->tsock) closesocket(conn->tsock);
    if (request_buffer) HeapFree(GetProcessHeap(), 0, request_buffer);
    if (response_buffer) HeapFree(GetProcessHeap(), 0, response_buffer);
    if (proxy_buffer) HeapFree(GetProcessHeap(), 0, proxy_buffer);
    if (request) HeapFree(GetProcessHeap(), 0, request);
    if (response) HeapFree(GetProcessHeap(), 0, response);
    if (proxy) HeapFree(GetProcessHeap(), 0, proxy);
    if (session_connect) HeapFree(GetProcessHeap(), 0, session_connect);

    return 0;
}
https proxy
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.