Python Сокет [WinError 10054] Существующее соединение было принудительно закрыто удаленным хостом - PullRequest
0 голосов
/ 04 мая 2020

В настоящее время я кодирую прокси-сервер только из сокета и модуля ssl. Я следовал различным исходным кодам, в результате чего получился следующий код.

def main():
global listen_port, buffer_size, max_conn

try:
    listen_port = int(input("Enter a listening port: "))
except KeyboardInterrupt:
    sys.exit(0)

max_conn = 5
buffer_size = 1024

try:
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    print("[*] Intializing socket... Done")
    s.bind(('', listen_port))
    print("[*] Socket binded sucessfully...")
    s.listen(max_conn)
    print("[*] Socket started successfully [{}]".format(listen_port))
except Exception as e:
    print(e)
    sys.exit(2)

while True:
    try:
        conn, addr = s.accept()
        conn.settimeout(10)
        print("[*] New connection established")
        try:
            data = conn.recv(buffer_size)
        except socket.timeout as e:
            print('[*] Client Timeout')
        start_new_thread(conn_string, (conn, data, addr))
    except KeyboardInterrupt:
        s.close()
        print("\n[*] Shutting down...")
        sys.exit(1)

s.close()

def conn_string(conn, data, addr):
try:
    data_str = data.decode("utf-8")

    first_line = data_str.split("\n")[0]
    url = first_line.split(" ")[1]

    http_pos = url.find("://")
    if http_pos == -1:
        temp = url
    else:
        temp = url[(http_pos + 3):]

    port_pos = temp.find(":")

    webserver_pos = temp.find("/")
    if webserver_pos == -1:
        webserver_pos = len(temp)
    webserver = ""
    port = -1

    if port_pos == -1 or webserver_pos < port_pos:
        port = 80
        webserver = temp[:webserver_pos]
    else:
        port = int(temp[(port_pos + 1):][:webserver_pos - port_pos - 1])
        webserver = temp[:port_pos]

    proxy_server(webserver, port, conn, data, addr)
except Exception as e:
    print(e)

def access_control(webserver):
access_control_list = ['sing.cse.ust.hk']
access_flag = False

for i in range(0, len(access_control_list)):
    if(access_control_list[i] in webserver):
        access_flag = False
        break
    else:
        access_flag = True

return access_flag

def proxy_server(webserver, port, conn, data, addr):
try:
    access = access_control(webserver)
    if(access):

        print("[*] Connecting to " + webserver + ' with port ' + str(port))

        s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        s.settimeout(5)

        if(port == 80):
            s.connect((webserver, port))
            s.send(data)
        elif(port == 443):
            request = "GET / HTTP/1.1\r\nHost: " + webserver + "\r\nProxy-Connection: Keep-Alive\r\n\r\n"
            #print(request)
            wrapped_s = ssl.create_default_context().wrap_socket(s, server_hostname=webserver)
            #wrapped_s = ssl.wrap_socket(s, ssl_version=ssl.PROTOCOL_TLSv1_2)
            wrapped_s.connect((webserver, port))
            wrapped_s.send(request.encode('utf-8'))

        while True:
            try:
                if(port == 80):
                    reply = s.recv(buffer_size)
                elif(port == 443):
                    reply = wrapped_s.recv(buffer_size)
            except socket.timeout as e:
                print('[*] Server Timeout')
                break

            if len(reply) > 0:
                #print(reply.decode("utf-8"))
                conn.send(reply)

                print("[*] Request done: " + webserver + " with port " + str(port))
            else:
                print(webserver + ' ' + 'Fail')
                break
        if(port == 443):
            wrapped_s.close()
        s.close()
    else:
        conn.send(str.encode("HTTP/1.1 404 Not Found\n"+"Content-Type: text/html\n"+"\n"+"<html><body>404 Page Not Found</body></html>\n"))
        print("access Deny")

    conn.close()
    print("Connection Closed")
except socket.error as e:
    print(e)
    s.close()
    conn.close()
    sys.exit(1) 

Цель этого кода - запустить локальный прокси-сервер, обрабатывающий запросы HTTP и HTTPS, и немного контроля доступа.

Компонент HTTP и контроля доступа выполнен и протестирован, и HTTPS-запросы успешно переписываются и отправляются адресату.

Я попытался распечатать ответ, полученный с веб-сервера, содержимое там и код состояния - 200.

Но когда код пытается записать данные в клиентский сокет. Ошибка [WinError 10054] Существующее соединение было принудительно закрыто приглашением удаленного хоста и остановило программу.

Пример вывода для подключения к https://www.example.com:

  Enter a listening port: 4444
[*] Intializing socket... Done
[*] Socket binded sucessfully...
[*] Socket started successfully [4444]
[*] New connection established
[*] Connecting to example.com with port 443
[*] Request done: example.com with port 443
[*] Request done: example.com with port 443
[WinError 10054] An existing connection was forcibly closed by the remote host

Я проверил поведение в Microsoft Edge и Firefox, оба не могут показать веб-страницу. Сообщение об ошибке, отображаемое в Firefox, является Код ошибки: SSL_ERROR_RX_RECORD_TOO_LONG

Я изменил MAX_TLS_VERSION в Firefox на TLS 1.2, но не повезло.

Любая идея, почему соединение внезапно прекращается?

...