mirror of
https://github.com/Grasscutters/mitmproxy.git
synced 2024-11-23 08:11:00 +00:00
add ALPN to proxy connections
This commit is contained in:
parent
2a15479cdb
commit
1e40d34e94
@ -1,7 +1,6 @@
|
|||||||
from __future__ import (absolute_import, print_function, division)
|
from __future__ import (absolute_import, print_function, division)
|
||||||
|
|
||||||
from .layer import Layer, ServerConnectionMixin
|
from .layer import Layer, ServerConnectionMixin
|
||||||
from .http import HttpLayer
|
|
||||||
|
|
||||||
|
|
||||||
class HttpProxy(Layer, ServerConnectionMixin):
|
class HttpProxy(Layer, ServerConnectionMixin):
|
||||||
@ -22,3 +21,5 @@ class HttpUpstreamProxy(Layer, ServerConnectionMixin):
|
|||||||
for message in layer():
|
for message in layer():
|
||||||
if not self._handle_server_message(message):
|
if not self._handle_server_message(message):
|
||||||
yield message
|
yield message
|
||||||
|
|
||||||
|
from .http import HttpLayer
|
||||||
|
@ -208,4 +208,4 @@ def yield_from_callback(fun):
|
|||||||
|
|
||||||
self.yield_from_callback = None
|
self.yield_from_callback = None
|
||||||
|
|
||||||
return wrapper
|
return wrapper
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
from __future__ import (absolute_import, print_function, division)
|
from __future__ import (absolute_import, print_function, division)
|
||||||
|
|
||||||
import traceback
|
import traceback
|
||||||
|
|
||||||
from netlib import tcp
|
from netlib import tcp
|
||||||
|
import netlib.http.http2
|
||||||
|
|
||||||
from ..exceptions import ProtocolException
|
from ..exceptions import ProtocolException
|
||||||
from .layer import Layer, yield_from_callback
|
from .layer import Layer, yield_from_callback
|
||||||
@ -15,6 +17,9 @@ class TlsLayer(Layer):
|
|||||||
self._server_tls = server_tls
|
self._server_tls = server_tls
|
||||||
self.client_sni = None
|
self.client_sni = None
|
||||||
self._sni_from_server_change = None
|
self._sni_from_server_change = None
|
||||||
|
self.client_alpn_protos = None
|
||||||
|
|
||||||
|
# foo alpn protos = [netlib.http.http1.HTTP1Protocol.ALPN_PROTO_HTTP1, netlib.http.http2.HTTP2Protocol.ALPN_PROTO_H2], # TODO: read this from client_conn first
|
||||||
|
|
||||||
def __call__(self):
|
def __call__(self):
|
||||||
"""
|
"""
|
||||||
@ -131,7 +136,8 @@ class TlsLayer(Layer):
|
|||||||
options=self.config.openssl_options_client,
|
options=self.config.openssl_options_client,
|
||||||
cipher_list=self.config.ciphers_client,
|
cipher_list=self.config.ciphers_client,
|
||||||
dhparams=self.config.certstore.dhparams,
|
dhparams=self.config.certstore.dhparams,
|
||||||
chain_file=chain_file
|
chain_file=chain_file,
|
||||||
|
alpn_select_callback=self.__handle_alpn_select,
|
||||||
)
|
)
|
||||||
connection.set_context(new_context)
|
connection.set_context(new_context)
|
||||||
# An unhandled exception in this method will core dump PyOpenSSL, so
|
# An unhandled exception in this method will core dump PyOpenSSL, so
|
||||||
@ -139,10 +145,30 @@ class TlsLayer(Layer):
|
|||||||
except: # pragma: no cover
|
except: # pragma: no cover
|
||||||
self.log("Error in handle_sni:\r\n" + traceback.format_exc(), "error")
|
self.log("Error in handle_sni:\r\n" + traceback.format_exc(), "error")
|
||||||
|
|
||||||
|
def __handle_alpn_select(self, conn_, options):
|
||||||
|
# TODO: change to something meaningful?
|
||||||
|
alpn_preference = netlib.http.http1.HTTP1Protocol.ALPN_PROTO_HTTP1
|
||||||
|
alpn_preference = netlib.http.http2.HTTP2Protocol.ALPN_PROTO_H2
|
||||||
|
###
|
||||||
|
|
||||||
|
if self.client_alpn_protos != options:
|
||||||
|
# Perform reconnect
|
||||||
|
if self._server_tls:
|
||||||
|
self.yield_from_callback(Reconnect())
|
||||||
|
|
||||||
|
self.client_alpn_protos = options
|
||||||
|
print("foo: %s" % options)
|
||||||
|
|
||||||
|
if alpn_preference in options:
|
||||||
|
return bytes(alpn_preference)
|
||||||
|
else: # pragma no cover
|
||||||
|
return options[0]
|
||||||
|
|
||||||
@yield_from_callback
|
@yield_from_callback
|
||||||
def _establish_tls_with_client(self):
|
def _establish_tls_with_client(self):
|
||||||
self.log("Establish TLS with client", "debug")
|
self.log("Establish TLS with client", "debug")
|
||||||
cert, key, chain_file = self._find_cert()
|
cert, key, chain_file = self._find_cert()
|
||||||
|
|
||||||
try:
|
try:
|
||||||
self.client_conn.convert_to_ssl(
|
self.client_conn.convert_to_ssl(
|
||||||
cert, key,
|
cert, key,
|
||||||
@ -151,9 +177,11 @@ class TlsLayer(Layer):
|
|||||||
handle_sni=self.__handle_sni,
|
handle_sni=self.__handle_sni,
|
||||||
cipher_list=self.config.ciphers_client,
|
cipher_list=self.config.ciphers_client,
|
||||||
dhparams=self.config.certstore.dhparams,
|
dhparams=self.config.certstore.dhparams,
|
||||||
chain_file=chain_file
|
chain_file=chain_file,
|
||||||
|
alpn_select_callback=self.__handle_alpn_select,
|
||||||
)
|
)
|
||||||
except tcp.NetLibError as e:
|
except tcp.NetLibError as e:
|
||||||
|
print("alpn: %s" % self.client_alpn_protos)
|
||||||
raise ProtocolException(repr(e), e)
|
raise ProtocolException(repr(e), e)
|
||||||
|
|
||||||
def _establish_tls_with_server(self):
|
def _establish_tls_with_server(self):
|
||||||
@ -168,6 +196,7 @@ class TlsLayer(Layer):
|
|||||||
ca_path=self.config.openssl_trusted_cadir_server,
|
ca_path=self.config.openssl_trusted_cadir_server,
|
||||||
ca_pemfile=self.config.openssl_trusted_ca_server,
|
ca_pemfile=self.config.openssl_trusted_ca_server,
|
||||||
cipher_list=self.config.ciphers_server,
|
cipher_list=self.config.ciphers_server,
|
||||||
|
alpn_protos=self.client_alpn_protos,
|
||||||
)
|
)
|
||||||
tls_cert_err = self.server_conn.ssl_verification_error
|
tls_cert_err = self.server_conn.ssl_verification_error
|
||||||
if tls_cert_err is not None:
|
if tls_cert_err is not None:
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
from __future__ import absolute_import
|
from __future__ import absolute_import
|
||||||
|
|
||||||
import copy
|
import copy
|
||||||
import os
|
import os
|
||||||
|
|
||||||
from netlib import tcp, certutils
|
from netlib import tcp, certutils
|
||||||
from .. import stateobject, utils
|
from .. import stateobject, utils
|
||||||
|
|
||||||
@ -75,15 +77,6 @@ class ClientConnection(tcp.BaseHandler, stateobject.StateObject):
|
|||||||
return f
|
return f
|
||||||
|
|
||||||
def convert_to_ssl(self, *args, **kwargs):
|
def convert_to_ssl(self, *args, **kwargs):
|
||||||
# TODO: read ALPN from server and select same proto for client conn
|
|
||||||
# alpn_select = 'h2'
|
|
||||||
# def alpn_select_callback(conn_, options):
|
|
||||||
# if alpn_select in options:
|
|
||||||
# return bytes(alpn_select)
|
|
||||||
# else: # pragma no cover
|
|
||||||
# return options[0]
|
|
||||||
# tcp.BaseHandler.convert_to_ssl(self, alpn_select=alpn_select_callback, *args, **kwargs)
|
|
||||||
|
|
||||||
tcp.BaseHandler.convert_to_ssl(self, *args, **kwargs)
|
tcp.BaseHandler.convert_to_ssl(self, *args, **kwargs)
|
||||||
self.timestamp_ssl_setup = utils.timestamp()
|
self.timestamp_ssl_setup = utils.timestamp()
|
||||||
|
|
||||||
@ -184,9 +177,6 @@ class ServerConnection(tcp.TCPClient, stateobject.StateObject):
|
|||||||
if os.path.exists(path):
|
if os.path.exists(path):
|
||||||
clientcert = path
|
clientcert = path
|
||||||
|
|
||||||
# TODO: read ALPN from client and use same list for server conn
|
|
||||||
# self.convert_to_ssl(cert=clientcert, sni=sni, alpn_protos=[netlib.http.http2.HTTP2Protocol.ALPN_PROTO_H2], **kwargs)
|
|
||||||
|
|
||||||
self.convert_to_ssl(cert=clientcert, sni=sni, **kwargs)
|
self.convert_to_ssl(cert=clientcert, sni=sni, **kwargs)
|
||||||
self.sni = sni
|
self.sni = sni
|
||||||
self.timestamp_ssl_setup = utils.timestamp()
|
self.timestamp_ssl_setup = utils.timestamp()
|
||||||
|
Loading…
Reference in New Issue
Block a user