This commit is contained in:
Thomas Kriechbaumer 2017-01-19 20:55:19 +01:00
parent 86174eb6ad
commit 006eb39cc5
11 changed files with 133 additions and 42 deletions

View File

@ -1,35 +1,39 @@
from mitmproxy.addons import anticache
from mitmproxy.addons import anticomp
from mitmproxy.addons import check_alpn
from mitmproxy.addons import check_ca
from mitmproxy.addons import clientplayback
from mitmproxy.addons import streamfile
from mitmproxy.addons import disable_h2c_upgrade
from mitmproxy.addons import onboarding
from mitmproxy.addons import proxyauth
from mitmproxy.addons import replace
from mitmproxy.addons import script
from mitmproxy.addons import setheaders
from mitmproxy.addons import serverplayback
from mitmproxy.addons import setheaders
from mitmproxy.addons import stickyauth
from mitmproxy.addons import stickycookie
from mitmproxy.addons import streambodies
from mitmproxy.addons import streamfile
from mitmproxy.addons import upstream_auth
from mitmproxy.addons import disable_h2c_upgrade
def default_addons():
return [
onboarding.Onboarding(),
proxyauth.ProxyAuth(),
anticache.AntiCache(),
anticomp.AntiComp(),
check_alpn.CheckALPN(),
check_ca.CheckCA(),
clientplayback.ClientPlayback(),
disable_h2c_upgrade.DisableH2CleartextUpgrade(),
onboarding.Onboarding(),
proxyauth.ProxyAuth(),
replace.Replace(),
script.ScriptLoader(),
serverplayback.ServerPlayback(),
setheaders.SetHeaders(),
stickyauth.StickyAuth(),
stickycookie.StickyCookie(),
script.ScriptLoader(),
streamfile.StreamFile(),
streambodies.StreamBodies(),
replace.Replace(),
setheaders.SetHeaders(),
serverplayback.ServerPlayback(),
clientplayback.ClientPlayback(),
streamfile.StreamFile(),
upstream_auth.UpstreamAuth(),
disable_h2c_upgrade.DisableH2CleartextUpgrade(),
]

View File

@ -0,0 +1,17 @@
import mitmproxy
from mitmproxy.net import tcp
class CheckALPN:
def __init__(self):
self.failed = False
def configure(self, options, updated):
self.failed = mitmproxy.ctx.master.options.http2 and not tcp.HAS_ALPN
if self.failed:
mitmproxy.ctx.master.add_log(
"HTTP/2 is disabled because ALPN support missing!\n"
"OpenSSL 1.0.2+ required to support HTTP/2 connections.\n"
"Use --no-http2 to silence this warning.",
"warn",
)

View File

@ -0,0 +1,24 @@
import mitmproxy
class CheckCA:
def __init__(self):
self.failed = False
def configure(self, options, updated):
has_ca = (
mitmproxy.ctx.master.server and
mitmproxy.ctx.master.server.config and
mitmproxy.ctx.master.server.config.certstore and
mitmproxy.ctx.master.server.config.certstore.default_ca
)
if has_ca:
self.failed = mitmproxy.ctx.master.server.config.certstore.default_ca.has_expired()
if self.failed:
mitmproxy.ctx.master.add_log(
"The mitmproxy certificate authority has expired!\n"
"Please delete all CA-related files in your ~/.mitmproxy folder.\n"
"The CA will be regenerated automatically after restarting mitmproxy.\n"
"Then make sure all your clients have the new CA installed.",
"warn",
)

View File

@ -5,9 +5,9 @@ from mitmproxy import log
class TermLog:
def __init__(self, outfile=sys.stdout):
def __init__(self, outfile=None):
self.options = None
self.outfile = outfile
self.outfile = outfile or sys.stdout
def configure(self, options, updated):
self.options = options

View File

@ -3,8 +3,8 @@ import ssl
import time
import datetime
import ipaddress
import sys
from pyasn1.type import univ, constraint, char, namedtype, tag
from pyasn1.codec.der.decoder import decode
from pyasn1.error import PyAsn1Error
@ -13,8 +13,8 @@ import OpenSSL
from mitmproxy.types import serializable
# Default expiry must not be too long: https://github.com/mitmproxy/mitmproxy/issues/815
DEFAULT_EXP = 94608000 # = 24 * 60 * 60 * 365 * 3
# Generated with "openssl dhparam". It's too slow to generate this on startup.
DEFAULT_DHPARAM = b"""
-----BEGIN DH PARAMETERS-----

View File

@ -33,8 +33,6 @@ from mitmproxy.tools.console import statusbar
from mitmproxy.tools.console import window
from mitmproxy.utils import strutils
from mitmproxy.net import tcp
EVENTLOG_SIZE = 10000
@ -272,16 +270,6 @@ class ConsoleMaster(master.Master):
print("Could not load file: {}".format(ret), file=sys.stderr)
sys.exit(1)
self.loop.set_alarm_in(0.01, self.ticker)
if self.options.http2 and not tcp.HAS_ALPN: # pragma: no cover
def http2err(*args, **kwargs):
signals.status_message.send(
message = "HTTP/2 disabled - OpenSSL 1.0.2+ required."
" Use --no-http2 to silence this warning.",
expire=5
)
self.loop.set_alarm_in(0.01, http2err)
self.loop.set_alarm_in(
0.0001,
lambda *args: self.view_flowlist()

View File

@ -6,7 +6,6 @@ from mitmproxy import addons
from mitmproxy import options
from mitmproxy import master
from mitmproxy.addons import dumper, termlog
from mitmproxy.net import tcp
class DumpError(Exception):
@ -30,7 +29,13 @@ class Options(options.Options):
class DumpMaster(master.Master):
def __init__(self, options, server, with_termlog=True, with_dumper=True):
def __init__(
self,
options: Options,
server,
with_termlog=True,
with_dumper=True,
) -> None:
master.Master.__init__(self, options, server)
self.has_errored = False
if with_termlog:
@ -38,8 +43,6 @@ class DumpMaster(master.Master):
self.addons.add(*addons.default_addons())
if with_dumper:
self.addons.add(dumper.Dumper())
# This line is just for type hinting
self.options = self.options # type: Options
if not self.options.no_server:
self.add_log(
@ -47,13 +50,6 @@ class DumpMaster(master.Master):
"info"
)
if self.server and self.options.http2 and not tcp.HAS_ALPN: # pragma: no cover
self.add_log(
"ALPN support missing (OpenSSL 1.0.2+ required)!\n"
"HTTP/2 is disabled. Use --no-http2 to silence this warning.",
"error"
)
if options.rfile:
try:
self.load_flows_file(options.rfile)

View File

@ -0,0 +1,23 @@
from mitmproxy.addons import check_alpn
from mitmproxy.test import taddons
from ...conftest import requires_alpn
class TestCheckALPN:
@requires_alpn
def test_check_alpn(self):
msg = 'ALPN support missing'
with taddons.context() as tctx:
a = check_alpn.CheckALPN()
tctx.configure(a)
assert not any(msg in m for l, m in tctx.master.event_log)
def test_check_no_alpn(self, disable_alpn):
msg = 'ALPN support missing'
with taddons.context() as tctx:
a = check_alpn.CheckALPN()
tctx.configure(a)
assert any(msg in m for l, m in tctx.master.event_log)

View File

@ -0,0 +1,19 @@
import pytest
from unittest import mock
from mitmproxy.addons import check_ca
from mitmproxy.test import taddons
class TestCheckCA:
@pytest.mark.parametrize('expired', [False, True])
def test_check_ca(self, expired):
msg = 'The mitmproxy certificate authority has expired!'
with taddons.context() as tctx:
tctx.master.server = mock.MagicMock()
tctx.master.server.config.certstore.default_ca.has_expired = mock.MagicMock(return_value=expired)
a = check_ca.CheckCA()
tctx.configure(a)
assert any(msg in m for l, m in tctx.master.event_log) is expired

View File

@ -1,10 +1,13 @@
import os
import pytest
from unittest import mock
from mitmproxy.tools import dump
from mitmproxy import proxy
from mitmproxy.test import tutils
from mitmproxy import log
from mitmproxy import controller
from mitmproxy.tools import dump
from mitmproxy.test import tutils
from . import mastertest
@ -37,3 +40,17 @@ class TestDumpMaster(mastertest.MasterTest):
ent.reply = controller.DummyReply()
m.log(ent)
assert m.has_errored
@pytest.mark.parametrize("termlog", [False, True])
def test_addons_termlog(self, termlog):
with mock.patch('sys.stdout'):
o = dump.Options()
m = dump.DumpMaster(o, proxy.DummyServer(), with_termlog=termlog)
assert (m.addons.get('termlog') is not None) == termlog
@pytest.mark.parametrize("dumper", [False, True])
def test_addons_dumper(self, dumper):
with mock.patch('sys.stdout'):
o = dump.Options()
m = dump.DumpMaster(o, proxy.DummyServer(), with_dumper=dumper)
assert (m.addons.get('dumper') is not None) == dumper

View File

@ -1,13 +1,16 @@
from mitmproxy.tools.web import master
from mitmproxy import proxy
from mitmproxy import options
from mitmproxy.proxy.config import ProxyConfig
from . import mastertest
class TestWebMaster(mastertest.MasterTest):
def mkmaster(self, **opts):
o = options.Options(**opts)
return master.WebMaster(o, proxy.DummyServer(o))
c = ProxyConfig(o)
return master.WebMaster(o, proxy.DummyServer(c))
def test_basic(self):
m = self.mkmaster()