mirror of
https://github.com/Grasscutters/mitmproxy.git
synced 2024-11-27 02:24:18 +00:00
fix #939
This commit is contained in:
parent
86174eb6ad
commit
006eb39cc5
@ -1,35 +1,39 @@
|
|||||||
from mitmproxy.addons import anticache
|
from mitmproxy.addons import anticache
|
||||||
from mitmproxy.addons import anticomp
|
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 clientplayback
|
||||||
from mitmproxy.addons import streamfile
|
from mitmproxy.addons import disable_h2c_upgrade
|
||||||
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
|
||||||
from mitmproxy.addons import script
|
from mitmproxy.addons import script
|
||||||
from mitmproxy.addons import setheaders
|
|
||||||
from mitmproxy.addons import serverplayback
|
from mitmproxy.addons import serverplayback
|
||||||
|
from mitmproxy.addons import setheaders
|
||||||
from mitmproxy.addons import stickyauth
|
from mitmproxy.addons import stickyauth
|
||||||
from mitmproxy.addons import stickycookie
|
from mitmproxy.addons import stickycookie
|
||||||
from mitmproxy.addons import streambodies
|
from mitmproxy.addons import streambodies
|
||||||
|
from mitmproxy.addons import streamfile
|
||||||
from mitmproxy.addons import upstream_auth
|
from mitmproxy.addons import upstream_auth
|
||||||
from mitmproxy.addons import disable_h2c_upgrade
|
|
||||||
|
|
||||||
|
|
||||||
def default_addons():
|
def default_addons():
|
||||||
return [
|
return [
|
||||||
onboarding.Onboarding(),
|
|
||||||
proxyauth.ProxyAuth(),
|
|
||||||
anticache.AntiCache(),
|
anticache.AntiCache(),
|
||||||
anticomp.AntiComp(),
|
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(),
|
stickyauth.StickyAuth(),
|
||||||
stickycookie.StickyCookie(),
|
stickycookie.StickyCookie(),
|
||||||
script.ScriptLoader(),
|
|
||||||
streamfile.StreamFile(),
|
|
||||||
streambodies.StreamBodies(),
|
streambodies.StreamBodies(),
|
||||||
replace.Replace(),
|
streamfile.StreamFile(),
|
||||||
setheaders.SetHeaders(),
|
|
||||||
serverplayback.ServerPlayback(),
|
|
||||||
clientplayback.ClientPlayback(),
|
|
||||||
upstream_auth.UpstreamAuth(),
|
upstream_auth.UpstreamAuth(),
|
||||||
disable_h2c_upgrade.DisableH2CleartextUpgrade(),
|
|
||||||
]
|
]
|
||||||
|
17
mitmproxy/addons/check_alpn.py
Normal file
17
mitmproxy/addons/check_alpn.py
Normal 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",
|
||||||
|
)
|
24
mitmproxy/addons/check_ca.py
Normal file
24
mitmproxy/addons/check_ca.py
Normal 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",
|
||||||
|
)
|
@ -5,9 +5,9 @@ from mitmproxy import log
|
|||||||
|
|
||||||
|
|
||||||
class TermLog:
|
class TermLog:
|
||||||
def __init__(self, outfile=sys.stdout):
|
def __init__(self, outfile=None):
|
||||||
self.options = None
|
self.options = None
|
||||||
self.outfile = outfile
|
self.outfile = outfile or sys.stdout
|
||||||
|
|
||||||
def configure(self, options, updated):
|
def configure(self, options, updated):
|
||||||
self.options = options
|
self.options = options
|
||||||
|
@ -3,8 +3,8 @@ import ssl
|
|||||||
import time
|
import time
|
||||||
import datetime
|
import datetime
|
||||||
import ipaddress
|
import ipaddress
|
||||||
|
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
from pyasn1.type import univ, constraint, char, namedtype, tag
|
from pyasn1.type import univ, constraint, char, namedtype, tag
|
||||||
from pyasn1.codec.der.decoder import decode
|
from pyasn1.codec.der.decoder import decode
|
||||||
from pyasn1.error import PyAsn1Error
|
from pyasn1.error import PyAsn1Error
|
||||||
@ -13,8 +13,8 @@ import OpenSSL
|
|||||||
from mitmproxy.types import serializable
|
from mitmproxy.types import serializable
|
||||||
|
|
||||||
# Default expiry must not be too long: https://github.com/mitmproxy/mitmproxy/issues/815
|
# Default expiry must not be too long: https://github.com/mitmproxy/mitmproxy/issues/815
|
||||||
|
|
||||||
DEFAULT_EXP = 94608000 # = 24 * 60 * 60 * 365 * 3
|
DEFAULT_EXP = 94608000 # = 24 * 60 * 60 * 365 * 3
|
||||||
|
|
||||||
# Generated with "openssl dhparam". It's too slow to generate this on startup.
|
# Generated with "openssl dhparam". It's too slow to generate this on startup.
|
||||||
DEFAULT_DHPARAM = b"""
|
DEFAULT_DHPARAM = b"""
|
||||||
-----BEGIN DH PARAMETERS-----
|
-----BEGIN DH PARAMETERS-----
|
||||||
|
@ -33,8 +33,6 @@ from mitmproxy.tools.console import statusbar
|
|||||||
from mitmproxy.tools.console import window
|
from mitmproxy.tools.console import window
|
||||||
from mitmproxy.utils import strutils
|
from mitmproxy.utils import strutils
|
||||||
|
|
||||||
from mitmproxy.net import tcp
|
|
||||||
|
|
||||||
EVENTLOG_SIZE = 10000
|
EVENTLOG_SIZE = 10000
|
||||||
|
|
||||||
|
|
||||||
@ -272,16 +270,6 @@ class ConsoleMaster(master.Master):
|
|||||||
print("Could not load file: {}".format(ret), file=sys.stderr)
|
print("Could not load file: {}".format(ret), file=sys.stderr)
|
||||||
sys.exit(1)
|
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(
|
self.loop.set_alarm_in(
|
||||||
0.0001,
|
0.0001,
|
||||||
lambda *args: self.view_flowlist()
|
lambda *args: self.view_flowlist()
|
||||||
|
@ -6,7 +6,6 @@ from mitmproxy import addons
|
|||||||
from mitmproxy import options
|
from mitmproxy import options
|
||||||
from mitmproxy import master
|
from mitmproxy import master
|
||||||
from mitmproxy.addons import dumper, termlog
|
from mitmproxy.addons import dumper, termlog
|
||||||
from mitmproxy.net import tcp
|
|
||||||
|
|
||||||
|
|
||||||
class DumpError(Exception):
|
class DumpError(Exception):
|
||||||
@ -30,7 +29,13 @@ class Options(options.Options):
|
|||||||
|
|
||||||
class DumpMaster(master.Master):
|
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)
|
master.Master.__init__(self, options, server)
|
||||||
self.has_errored = False
|
self.has_errored = False
|
||||||
if with_termlog:
|
if with_termlog:
|
||||||
@ -38,8 +43,6 @@ class DumpMaster(master.Master):
|
|||||||
self.addons.add(*addons.default_addons())
|
self.addons.add(*addons.default_addons())
|
||||||
if with_dumper:
|
if with_dumper:
|
||||||
self.addons.add(dumper.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:
|
if not self.options.no_server:
|
||||||
self.add_log(
|
self.add_log(
|
||||||
@ -47,13 +50,6 @@ class DumpMaster(master.Master):
|
|||||||
"info"
|
"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:
|
if options.rfile:
|
||||||
try:
|
try:
|
||||||
self.load_flows_file(options.rfile)
|
self.load_flows_file(options.rfile)
|
||||||
|
23
test/mitmproxy/addons/test_check_alpn.py
Normal file
23
test/mitmproxy/addons/test_check_alpn.py
Normal 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)
|
19
test/mitmproxy/addons/test_check_ca.py
Normal file
19
test/mitmproxy/addons/test_check_ca.py
Normal 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
|
@ -1,10 +1,13 @@
|
|||||||
import os
|
import os
|
||||||
|
import pytest
|
||||||
|
from unittest import mock
|
||||||
|
|
||||||
from mitmproxy.tools import dump
|
|
||||||
from mitmproxy import proxy
|
from mitmproxy import proxy
|
||||||
from mitmproxy.test import tutils
|
|
||||||
from mitmproxy import log
|
from mitmproxy import log
|
||||||
from mitmproxy import controller
|
from mitmproxy import controller
|
||||||
|
from mitmproxy.tools import dump
|
||||||
|
|
||||||
|
from mitmproxy.test import tutils
|
||||||
from . import mastertest
|
from . import mastertest
|
||||||
|
|
||||||
|
|
||||||
@ -37,3 +40,17 @@ class TestDumpMaster(mastertest.MasterTest):
|
|||||||
ent.reply = controller.DummyReply()
|
ent.reply = controller.DummyReply()
|
||||||
m.log(ent)
|
m.log(ent)
|
||||||
assert m.has_errored
|
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
|
||||||
|
@ -1,13 +1,16 @@
|
|||||||
from mitmproxy.tools.web import master
|
from mitmproxy.tools.web import master
|
||||||
from mitmproxy import proxy
|
from mitmproxy import proxy
|
||||||
from mitmproxy import options
|
from mitmproxy import options
|
||||||
|
from mitmproxy.proxy.config import ProxyConfig
|
||||||
|
|
||||||
from . import mastertest
|
from . import mastertest
|
||||||
|
|
||||||
|
|
||||||
class TestWebMaster(mastertest.MasterTest):
|
class TestWebMaster(mastertest.MasterTest):
|
||||||
def mkmaster(self, **opts):
|
def mkmaster(self, **opts):
|
||||||
o = options.Options(**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):
|
def test_basic(self):
|
||||||
m = self.mkmaster()
|
m = self.mkmaster()
|
||||||
|
Loading…
Reference in New Issue
Block a user