disable h2c prior knowledge connections

This commit is contained in:
Thomas Kriechbaumer 2017-03-09 19:40:42 +01:00
parent 98b5893855
commit 45bf1ff64d
5 changed files with 82 additions and 40 deletions

View File

@ -4,7 +4,7 @@ from mitmproxy.addons import check_alpn
from mitmproxy.addons import check_ca from mitmproxy.addons import check_ca
from mitmproxy.addons import clientplayback from mitmproxy.addons import clientplayback
from mitmproxy.addons import core_option_validation from mitmproxy.addons import core_option_validation
from mitmproxy.addons import disable_h2c_upgrade from mitmproxy.addons import disable_h2c
from mitmproxy.addons import onboarding from mitmproxy.addons import onboarding
from mitmproxy.addons import proxyauth from mitmproxy.addons import proxyauth
from mitmproxy.addons import replace from mitmproxy.addons import replace
@ -26,7 +26,7 @@ def default_addons():
check_alpn.CheckALPN(), check_alpn.CheckALPN(),
check_ca.CheckCA(), check_ca.CheckCA(),
clientplayback.ClientPlayback(), clientplayback.ClientPlayback(),
disable_h2c_upgrade.DisableH2CleartextUpgrade(), disable_h2c.DisableH2C(),
onboarding.Onboarding(), onboarding.Onboarding(),
proxyauth.ProxyAuth(), proxyauth.ProxyAuth(),
replace.Replace(), replace.Replace(),

View File

@ -0,0 +1,41 @@
import mitmproxy
class DisableH2C:
"""
We currently only support HTTP/2 over a TLS connection.
Some clients try to upgrade a connection from HTTP/1.1 to h2c. We need to
remove those headers to avoid protocol errors if one endpoints suddenly
starts sending HTTP/2 frames.
Some clients might use HTTP/2 Prior Knowledge to directly initiate a session
by sending the connection preface. We just kill those flows.
"""
def configure(self, options, updated):
pass
def process_flow(self, f):
if f.request.headers.get('upgrade', '') == 'h2c':
mitmproxy.ctx.log.warn("HTTP/2 cleartext connections (h2c upgrade requests) are currently not supported.")
del f.request.headers['upgrade']
if 'connection' in f.request.headers:
del f.request.headers['connection']
if 'http2-settings' in f.request.headers:
del f.request.headers['http2-settings']
is_connection_preface = (
f.request.method == 'PRI' and
f.request.path == '*' and
f.request.http_version == 'HTTP/2.0'
)
if is_connection_preface:
f.kill()
mitmproxy.ctx.log.warn("Initiating HTTP/2 connections with prior knowledge are currently not supported.")
# Handlers
def request(self, f):
self.process_flow(f)

View File

@ -1,21 +0,0 @@
class DisableH2CleartextUpgrade:
"""
We currently only support HTTP/2 over a TLS connection. Some clients try
to upgrade a connection from HTTP/1.1 to h2c, so we need to remove those
headers to avoid protocol errors if one endpoints suddenly starts sending
HTTP/2 frames.
"""
def process_flow(self, f):
if f.request.headers.get('upgrade', '') == 'h2c':
del f.request.headers['upgrade']
if 'connection' in f.request.headers:
del f.request.headers['connection']
if 'http2-settings' in f.request.headers:
del f.request.headers['http2-settings']
# Handlers
def request(self, f):
self.process_flow(f)

View File

@ -0,0 +1,39 @@
import io
from mitmproxy import http
from mitmproxy.addons import disable_h2c
from mitmproxy.net.http import http1
from mitmproxy.exceptions import Kill
from mitmproxy.test import tflow
from mitmproxy.test import taddons
class TestDisableH2CleartextUpgrade:
def test_upgrade(self):
with taddons.context() as tctx:
a = disable_h2c.DisableH2C()
tctx.configure(a)
f = tflow.tflow()
f.request.headers['upgrade'] = 'h2c'
f.request.headers['connection'] = 'foo'
f.request.headers['http2-settings'] = 'bar'
a.request(f)
assert 'upgrade' not in f.request.headers
assert 'connection' not in f.request.headers
assert 'http2-settings' not in f.request.headers
def test_prior_knowledge(self):
with taddons.context() as tctx:
a = disable_h2c.DisableH2C()
tctx.configure(a)
b = io.BytesIO(b"PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n")
f = tflow.tflow()
f.request = http.HTTPRequest.wrap(http1.read_request(b))
f.reply.handle()
f.intercept()
a.request(f)
assert not f.killable
assert f.reply.value == Kill

View File

@ -1,17 +0,0 @@
from mitmproxy.addons import disable_h2c_upgrade
from mitmproxy.test import tflow
class TestTermLog:
def test_simple(self):
a = disable_h2c_upgrade.DisableH2CleartextUpgrade()
f = tflow.tflow()
f.request.headers['upgrade'] = 'h2c'
f.request.headers['connection'] = 'foo'
f.request.headers['http2-settings'] = 'bar'
a.request(f)
assert 'upgrade' not in f.request.headers
assert 'connection' not in f.request.headers
assert 'http2-settings' not in f.request.headers