mirror of
https://github.com/Grasscutters/mitmproxy.git
synced 2025-01-30 23:09:44 +00:00
parent
e44493bda5
commit
47196e8676
@ -1,4 +0,0 @@
|
||||
# This file is dual licensed under the terms of the Apache License, Version
|
||||
# 2.0, and the BSD License. See the LICENSE file in the root of this repository
|
||||
# for complete details.
|
||||
|
@ -1,3 +1,6 @@
|
||||
# This file originally comes from https://github.com/pyca/tls/blob/master/tls/_constructs.py.
|
||||
# Modified by the mitmproxy team.
|
||||
|
||||
# This file is dual licensed under the terms of the Apache License, Version
|
||||
# 2.0, and the BSD License. See the LICENSE file in the root of this repository
|
||||
# for complete details.
|
||||
@ -113,9 +116,11 @@ Extension = "Extension" / Struct(
|
||||
)
|
||||
)
|
||||
|
||||
extensions = "extensions" / Struct(
|
||||
Int16ub,
|
||||
"extensions" / GreedyRange(Extension)
|
||||
extensions = "extensions" / Optional(
|
||||
Struct(
|
||||
Int16ub,
|
||||
"extensions" / GreedyRange(Extension)
|
||||
)
|
||||
)
|
||||
|
||||
ClientHello = "ClientHello" / Struct(
|
@ -4,7 +4,7 @@ from typing import Union
|
||||
|
||||
import construct
|
||||
from mitmproxy import exceptions
|
||||
from mitmproxy.contrib.tls import _constructs
|
||||
from mitmproxy.contrib import tls_parser
|
||||
from mitmproxy.proxy.protocol import base
|
||||
from mitmproxy.net import check
|
||||
|
||||
@ -248,7 +248,7 @@ def get_client_hello(client_conn):
|
||||
class TlsClientHello:
|
||||
|
||||
def __init__(self, raw_client_hello):
|
||||
self._client_hello = _constructs.ClientHello.parse(raw_client_hello)
|
||||
self._client_hello = tls_parser.ClientHello.parse(raw_client_hello)
|
||||
|
||||
def raw(self):
|
||||
return self._client_hello
|
||||
@ -259,21 +259,25 @@ class TlsClientHello:
|
||||
|
||||
@property
|
||||
def sni(self):
|
||||
for extension in self._client_hello.extensions.extensions:
|
||||
is_valid_sni_extension = (
|
||||
extension.type == 0x00 and
|
||||
len(extension.server_names) == 1 and
|
||||
extension.server_names[0].name_type == 0 and
|
||||
check.is_valid_host(extension.server_names[0].host_name)
|
||||
)
|
||||
if is_valid_sni_extension:
|
||||
return extension.server_names[0].host_name.decode("idna")
|
||||
if self._client_hello.extensions:
|
||||
for extension in self._client_hello.extensions.extensions:
|
||||
is_valid_sni_extension = (
|
||||
extension.type == 0x00 and
|
||||
len(extension.server_names) == 1 and
|
||||
extension.server_names[0].name_type == 0 and
|
||||
check.is_valid_host(extension.server_names[0].host_name)
|
||||
)
|
||||
if is_valid_sni_extension:
|
||||
return extension.server_names[0].host_name.decode("idna")
|
||||
return None
|
||||
|
||||
@property
|
||||
def alpn_protocols(self):
|
||||
for extension in self._client_hello.extensions.extensions:
|
||||
if extension.type == 0x10:
|
||||
return list(extension.alpn_protocols)
|
||||
if self._client_hello.extensions:
|
||||
for extension in self._client_hello.extensions.extensions:
|
||||
if extension.type == 0x10:
|
||||
return list(extension.alpn_protocols)
|
||||
return []
|
||||
|
||||
@classmethod
|
||||
def from_client_conn(cls, client_conn):
|
||||
|
38
test/mitmproxy/contrib/test_tls_parser.py
Normal file
38
test/mitmproxy/contrib/test_tls_parser.py
Normal file
@ -0,0 +1,38 @@
|
||||
from mitmproxy.contrib import tls_parser
|
||||
|
||||
|
||||
def test_parse_chrome():
|
||||
"""
|
||||
Test if we properly parse a ClientHello sent by Chrome 54.
|
||||
"""
|
||||
data = bytes.fromhex(
|
||||
"03033b70638d2523e1cba15f8364868295305e9c52aceabda4b5147210abc783e6e1000022c02bc02fc02cc030"
|
||||
"cca9cca8cc14cc13c009c013c00ac014009c009d002f0035000a0100006cff0100010000000010000e00000b65"
|
||||
"78616d706c652e636f6d0017000000230000000d00120010060106030501050304010403020102030005000501"
|
||||
"00000000001200000010000e000c02683208687474702f312e3175500000000b00020100000a00080006001d00"
|
||||
"170018"
|
||||
)
|
||||
c = tls_parser.ClientHello.parse(data)
|
||||
assert c.version.major == 3
|
||||
assert c.version.minor == 3
|
||||
|
||||
alpn = [a for a in c.extensions.extensions if a.type == 16]
|
||||
assert len(alpn) == 1
|
||||
assert alpn[0].alpn_protocols == [b"h2", b"http/1.1"]
|
||||
|
||||
sni = [a for a in c.extensions.extensions if a.type == 0]
|
||||
assert len(sni) == 1
|
||||
assert sni[0].server_names[0].name_type == 0
|
||||
assert sni[0].server_names[0].host_name == b"example.com"
|
||||
|
||||
|
||||
def test_parse_no_extensions():
|
||||
data = bytes.fromhex(
|
||||
"03015658a756ab2c2bff55f636814deac086b7ca56b65058c7893ffc6074f5245f70205658a75475103a152637"
|
||||
"78e1bb6d22e8bbd5b6b0a3a59760ad354e91ba20d353001a0035002f000a000500040009000300060008006000"
|
||||
"61006200640100"
|
||||
)
|
||||
c = tls_parser.ClientHello.parse(data)
|
||||
assert c.version.major == 3
|
||||
assert c.version.minor == 1
|
||||
assert c.extensions is None
|
26
test/mitmproxy/protocol/test_tls.py
Normal file
26
test/mitmproxy/protocol/test_tls.py
Normal file
@ -0,0 +1,26 @@
|
||||
from mitmproxy.proxy.protocol.tls import TlsClientHello
|
||||
|
||||
|
||||
class TestClientHello:
|
||||
|
||||
def test_no_extensions(self):
|
||||
data = bytes.fromhex(
|
||||
"03015658a756ab2c2bff55f636814deac086b7ca56b65058c7893ffc6074f5245f70205658a75475103a152637"
|
||||
"78e1bb6d22e8bbd5b6b0a3a59760ad354e91ba20d353001a0035002f000a000500040009000300060008006000"
|
||||
"61006200640100"
|
||||
)
|
||||
c = TlsClientHello(data)
|
||||
assert c.sni is None
|
||||
assert c.alpn_protocols == []
|
||||
|
||||
def test_extensions(self):
|
||||
data = bytes.fromhex(
|
||||
"03033b70638d2523e1cba15f8364868295305e9c52aceabda4b5147210abc783e6e1000022c02bc02fc02cc030"
|
||||
"cca9cca8cc14cc13c009c013c00ac014009c009d002f0035000a0100006cff0100010000000010000e00000b65"
|
||||
"78616d706c652e636f6d0017000000230000000d00120010060106030501050304010403020102030005000501"
|
||||
"00000000001200000010000e000c02683208687474702f312e3175500000000b00020100000a00080006001d00"
|
||||
"170018"
|
||||
)
|
||||
c = TlsClientHello(data)
|
||||
assert c.sni == 'example.com'
|
||||
assert c.alpn_protocols == [b'h2', b'http/1.1']
|
Loading…
Reference in New Issue
Block a user