Pyleon SSLError: Error del lado del cliente (EOF ocurrió en violación del protocolo), Error del lado del servidor (SSL3_GET_RECORD: número de versión incorrecto)

Tengo algunas dificultades para intentar crear un socket SSL en Python para usar un proxy que requiera autenticación. Lo siento mucho por la longitud, pero sentí que era mejor incluir tantos detalles como fuera posible.

Primero, el código del servidor se ve así:

class ThreadedTCPServer(SocketServer.ThreadingMixIn, SocketServer.TCPServer): def __init__(self, server_address, RequestHandlerClass, client_manager, recv_queue): SocketServer.TCPServer.__init__(self, server_address, RequestHandlerClass, bind_and_activate=True)  class ThreadedTCPRequestHandler(SocketServer.BaseRequestHandler): def setup(self): while True: try: print 'trying to wrap in ssl' self.request = ssl.wrap_socket(self.request, certfile=(os.getcwd() + '/ssl_certs/newcert.pem'), keyfile=(os.getcwd() + '/ssl_certs/webserver.nopass.key'), server_side=True, cert_reqs=ssl.CERT_NONE, ssl_version=ssl.PROTOCOL_TLSv1, do_handshake_on_connect=False, suppress_ragged_eofs=True) break except Exception, ex: print 'error trying to wrap in ssl %s' % ex def handle(self): # Display message that client has connected print '\r[*] Received connection from %s:%s\r' % (self.client_address[0], self.client_address[1]) while self.stopped() == False: recv_msg = self.request.read(1024) if recv_msg == '': self.stop.set() server.recv_queue.put(recv_msg) break else: server.recv_queue.put(recv_msg) if self.stopped(): print '[!] Received STOP signal from %s:%s; Exiting!' % (self.client_address[0], self.client_address[1]) 

Segundo, este es el código del cliente donde configuro la información necesaria para conectarse a través del proxy que requiere autenticación:

 class proxyCommsHandler(): def __init__(self, user, password, remote_host, remote_port, list_of_proxies): # information needed to connect self.user = 'username' self.passwd = 'password' self.remote_host = 'remote_host_ip' self.remote_port = 8008 self.list_of_proxies = [['proxyserver.hostname.com', 8080]] # setup basic authentication to send to the proxy when we try to connect self.user_pass = base64.encodestring(self.user + ':' + self.passwd) self.proxy_authorization = 'Proxy-authorization: Basic ' + self.user_pass + '\r\n' self.proxy_connect = 'CONNECT %s:%s HTTP/1.1\r\n' % (self.remote_host, self.remote_port) self.user_agent = "User-Agent: Mozilla/5.0 (Windows NT 6.1; rv:7.0.1) Gecko/20100101 Firefox/7.0.1\r\n" self.proxy_pieces = self.proxy_connect + self.proxy_authorization + self.user_agent + '\r\n' 

Ahora, aquí es donde inicialmente me conecto al proxy, donde no obtengo errores (obtengo un código de estado ‘200’):

 self.proxy = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self.proxy.connect( (proxy_host, proxy_port) ) self.proxy.sendall(self.proxy_pieces) self.response = proxy.recv(1024) 

Aquí es donde el cliente falla (creo). Intento tomar self.proxy y envolverlo en SSL, como esto:

 sslsock = ssl.wrap_socket(self.proxy, server_side=False, do_handshake_on_connect=True, ssl_version=ssl.PROTOCOL_TLSv1) 

Este es el error que veo en el cliente:

 Traceback (most recent call last): File "C:\Python27\pyrevshell.py", line 467, in  proxyCommsHandler(None, None, None, None, list_of_proxies).run() File "C:\Python27\pyrevshell.py", line 300, in run ssl_version=ssl.PROTOCOL_TLSv1) File "C:\Python27\lib\ssl.py", line 372, in wrap_socket ciphers=ciphers) File "C:\Python27\lib\ssl.py", line 134, in __init__ self.do_handshake() File "C:\Python27\lib\ssl.py", line 296, in do_handshake self._sslobj.do_handshake() SSLError: [Errno 8] _ssl.c:503: EOF occurred in violation of protocol 

El cliente se conecta, como se muestra en la salida aquí:

 trying to wrap in ssl [*] Received connection from xxxx:47144 [*] xxxx:47144 added to the client list 

Pero luego es seguido inmediatamente por una excepción:

 ---------------------------------------- Exception happened during processing of request from ('xxxx', 47144) Traceback (most recent call last): File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/SocketServer.py", line 582, in process_request_thread self.finish_request(request, client_address) File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/SocketServer.py", line 323, in finish_request self.RequestHandlerClass(request, client_address, self) File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/SocketServer.py", line 639, in __init__ self.handle() File "shell_server.py", line 324, in handle recv_msg = self.request.read(1024) File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/ssl.py", line 138, in read return self._sslobj.read(len) SSLError: [Errno 1] _ssl.c:1348: error:1408F10B:SSL routines:SSL3_GET_RECORD:wrong version number ---------------------------------------- 

Aunque me doy cuenta de que esto suena como un problema obvio basado en las Excepciones que se lanzaron, las partes interesantes son las siguientes:

  • Me conecto con éxito inicialmente a través del proxy como se muestra arriba
  • Puedo conectarme con éxito con un navegador web detrás del mismo proxy , y no se producen excepciones; Puedo pasar datos al navegador
  • He probado diferentes versiones del Protocolo SSL tanto en el servidor como en el lado del cliente, como se muestra en la tabla aquí en la documentación de Python ; errores en el lado del cliente cada vez

He utilizado Wireshark en ambos extremos de la conexión. Al usar un navegador normal y conectarme al servidor, veo todo el proceso de negociación y negociación de SSL, y todo funciona sin problemas.

Sin embargo, cuando uso el cliente que se muestra arriba, tan pronto como me conecto con él, veo que el cliente envía un mensaje de Client Hello , pero luego mi servidor envía un paquete RST para cancelar la conexión (no he determinado si esto es antes) o después de que se lanza la excepción).

Nuevamente, pido disculpas por la extensión, pero necesito un consejo experto.

He resuelto el problema a mi problema. Estoy enviando el self.user_agent al host remoto cuando me conecto a través del proxy por primera vez, lo que interfiere con el protocolo de enlace SSL.

Para resolver esto, puse un self.request.recv() inicial en la función def setup(self) antes de llamar a ssl.wrap_socket en el socket.