better exception handling

This commit is contained in:
Maximilian Hils 2015-09-11 01:39:33 +02:00
parent c159c8ca13
commit ffdf143be4
5 changed files with 58 additions and 17 deletions

View File

@ -33,6 +33,11 @@ class TlsException(ProtocolException):
pass pass
class ClientHandshakeException(TlsException):
# This subclass is quite useful to give hints about cert errors.
pass
class Socks5Exception(ProtocolException): class Socks5Exception(ProtocolException):
pass pass

View File

@ -1,4 +1,6 @@
from __future__ import (absolute_import, print_function, division) from __future__ import (absolute_import, print_function, division)
import six
import sys
from netlib import tcp from netlib import tcp
from ..models import ServerConnection from ..models import ServerConnection
from ..exceptions import ProtocolException from ..exceptions import ProtocolException
@ -172,8 +174,12 @@ class ServerConnectionMixin(object):
try: try:
self.server_conn.connect() self.server_conn.connect()
except tcp.NetLibError as e: except tcp.NetLibError as e:
raise ProtocolException( six.reraise(
"Server connection to %s failed: %s" % (repr(self.server_conn.address), e), e) ProtocolException,
ProtocolException("Server connection to %s failed: %s" %
(repr(self.server_conn.address), e), e),
sys.exc_info()[2]
)
class Kill(Exception): class Kill(Exception):

View File

@ -1,6 +1,8 @@
from __future__ import (absolute_import, print_function, division) from __future__ import (absolute_import, print_function, division)
import socket import socket
import select import select
import six
import sys
from OpenSSL import SSL from OpenSSL import SSL
@ -63,4 +65,8 @@ class RawTCPLayer(Layer):
) )
except (socket.error, NetLibError, SSL.Error) as e: except (socket.error, NetLibError, SSL.Error) as e:
raise ProtocolException("TCP connection closed unexpectedly: {}".format(repr(e)), e) six.reraise(
ProtocolException,
ProtocolException("TCP connection closed unexpectedly: {}".format(repr(e)), e),
sys.exc_info()[2]
)

View File

@ -1,18 +1,19 @@
from __future__ import (absolute_import, print_function, division) from __future__ import (absolute_import, print_function, division)
import struct import struct
import sys
from construct import ConstructError from construct import ConstructError
import six import six
import sys
from netlib.tcp import NetLibError, NetLibInvalidCertificateError from netlib.tcp import NetLibError, NetLibInvalidCertificateError
from netlib.http.http1 import HTTP1Protocol from netlib.http.http1 import HTTP1Protocol
from ..contrib.tls._constructs import ClientHello from ..contrib.tls._constructs import ClientHello
from ..exceptions import ProtocolException, TlsException from ..exceptions import ProtocolException, TlsException, ClientHandshakeException
from .base import Layer from .base import Layer
# taken from https://testssl.sh/openssl-rfc.mappping.html # taken from https://testssl.sh/openssl-rfc.mappping.html
CIPHER_ID_NAME_MAP = { CIPHER_ID_NAME_MAP = {
0x00: 'NULL-MD5', 0x00: 'NULL-MD5',
@ -407,8 +408,17 @@ class TlsLayer(Layer):
chain_file=chain_file, chain_file=chain_file,
alpn_select_callback=self.__alpn_select_callback, alpn_select_callback=self.__alpn_select_callback,
) )
# Some TLS clients will not fail the handshake,
# but will immediately throw an "unexpected eof" error on the first read.
# The reason for this might be difficult to find, so we try to peek here to see if it
# raises ann error.
self.client_conn.rfile.peek(0)
except NetLibError as e: except NetLibError as e:
raise TlsException("Cannot establish TLS with client: %s" % repr(e), e) six.reraise(
ClientHandshakeException,
ClientHandshakeException("Cannot establish TLS with client: %s" % repr(e), e),
sys.exc_info()[2]
)
def _establish_tls_with_server(self): def _establish_tls_with_server(self):
self.log("Establish TLS with server", "debug") self.log("Establish TLS with server", "debug")
@ -457,17 +467,25 @@ class TlsLayer(Layer):
(tls_cert_err['depth'], tls_cert_err['errno']), (tls_cert_err['depth'], tls_cert_err['errno']),
"error") "error")
self.log("Aborting connection attempt", "error") self.log("Aborting connection attempt", "error")
raise TlsException("Cannot establish TLS with {address} (sni: {sni}): {e}".format( six.reraise(
address=repr(self.server_conn.address), TlsException,
sni=self.sni_for_server_connection, TlsException("Cannot establish TLS with {address} (sni: {sni}): {e}".format(
e=repr(e), address=repr(self.server_conn.address),
), e) sni=self.sni_for_server_connection,
e=repr(e),
), e),
sys.exc_info()[2]
)
except NetLibError as e: except NetLibError as e:
raise TlsException("Cannot establish TLS with {address} (sni: {sni}): {e}".format( six.reraise(
address=repr(self.server_conn.address), TlsException,
sni=self.sni_for_server_connection, TlsException("Cannot establish TLS with {address} (sni: {sni}): {e}".format(
e=repr(e), address=repr(self.server_conn.address),
), e) sni=self.sni_for_server_connection,
e=repr(e),
), e),
sys.exc_info()[2]
)
self.log("ALPN selected by server: %s" % self.alpn_for_client_connection, "debug") self.log("ALPN selected by server: %s" % self.alpn_for_client_connection, "debug")

View File

@ -3,6 +3,7 @@ from __future__ import (absolute_import, print_function, division)
import traceback import traceback
import sys import sys
import socket import socket
import six
from netlib import tcp from netlib import tcp
from netlib.http.http1 import HTTP1Protocol from netlib.http.http1 import HTTP1Protocol
@ -39,7 +40,11 @@ class ProxyServer(tcp.TCPServer):
try: try:
super(ProxyServer, self).__init__((config.host, config.port)) super(ProxyServer, self).__init__((config.host, config.port))
except socket.error as e: except socket.error as e:
raise ServerException('Error starting proxy server: ' + repr(e), e) six.reraise(
ServerException,
ServerException('Error starting proxy server: ' + repr(e), e),
sys.exc_info()[2]
)
self.channel = None self.channel = None
def start_slave(self, klass, channel): def start_slave(self, klass, channel):
@ -117,6 +122,7 @@ class ConnectionHandler(object):
self.log("Connection killed", "info") self.log("Connection killed", "info")
except ProtocolException as e: except ProtocolException as e:
self.log(repr(e), "info") self.log(repr(e), "info")
self.log(traceback.format_exc(), "debug")
# If an error propagates to the topmost level, # If an error propagates to the topmost level,
# we send an HTTP error response, which is both # we send an HTTP error response, which is both
# understandable by HTTP clients and humans. # understandable by HTTP clients and humans.