Python SSLError: Client-side-error(EOF occurred in

2019-05-07 18:03发布

问题:

I'm having some difficulty attempting to create an SSL socket in Python to use a proxy that requires authentication. I am very sorry for the length, but I felt it was best to include as much detail as possible.

First, the server code looks like this:

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)

         <snipped out extra code>

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])

Second, this is the client code where I set up the information needed to connect via the proxy that requires authentication:

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'

Now, here's where I initially connect to the proxy, where I get no errors (I get a '200' status code):

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)

Here's where the client fails (I think). I try to take self.proxy and wrap it in SSL, like this:

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

This is the error that I see on the client:

Traceback (most recent call last):
    File "C:\Python27\pyrevshell.py", line 467, in <module>
        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

The client does connect, like shown from the output here:

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

But then it's immediately followed by an exception:

----------------------------------------
Exception happened during processing of request from ('x.x.x.x', 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
----------------------------------------

While I realize that this sounds like an obvious problem based on the Exceptions that were thrown, the interesting parts are that:

  • I successfully connect initially via the proxy as shown above
  • I can successfully connect with a web browser behind behind the same proxy, and no exceptions are thrown; I can pass data to the browser
  • I've tried different SSL Protocol versions on both the server and client side, as shown in the table here in the Python documentation; it errors on the client-side each time

I've used Wireshark on both ends of the connection. While using a normal browser and connecting to the server, I see the entire SSL handshake and negotiation process, and everything runs smoothly.

However, when I use the client shown above, as soon as I connect with it, I see the client send a Client Hello message, but then my server sends a RST packet to kill the connection (I haven't determined if this is before or after the Exception is thrown).

Again, I apologize for the length, but I am in dire need of expert advice.

回答1:

I've figured out the issue to my problem. I am sending the self.user_agent to the remote host when I connect via the proxy for the first time, which interferes with the SSL Handshake.

To solve this, I put an initial self.request.recv() in the def setup(self) function before I call ssl.wrap_socket on the socket.