mirror of
https://github.com/Grasscutters/mitmproxy.git
synced 2024-11-27 02:24:18 +00:00
Add a basic built-in web app.
This commit is contained in:
parent
98e4421a90
commit
e3fd0e838d
8
libmproxy/app.py
Normal file
8
libmproxy/app.py
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
import flask
|
||||||
|
|
||||||
|
mapp = flask.Flask(__name__)
|
||||||
|
|
||||||
|
@mapp.route("/")
|
||||||
|
def hello():
|
||||||
|
return "mitmproxy"
|
||||||
|
|
@ -163,7 +163,7 @@ def get_common_options(options):
|
|||||||
|
|
||||||
def common_options(parser):
|
def common_options(parser):
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
"-a",
|
"-b",
|
||||||
action="store", type = str, dest="addr", default='',
|
action="store", type = str, dest="addr", default='',
|
||||||
help = "Address to bind proxy to (defaults to all interfaces)"
|
help = "Address to bind proxy to (defaults to all interfaces)"
|
||||||
)
|
)
|
||||||
@ -261,6 +261,13 @@ def common_options(parser):
|
|||||||
help="Don't connect to upstream server to look up certificate details."
|
help="Don't connect to upstream server to look up certificate details."
|
||||||
)
|
)
|
||||||
|
|
||||||
|
group = parser.add_argument_group("Web App")
|
||||||
|
group.add_argument(
|
||||||
|
"-a",
|
||||||
|
action="store_true", dest="app", default=False,
|
||||||
|
help="Enable the mitmproxy web app."
|
||||||
|
)
|
||||||
|
|
||||||
group = parser.add_argument_group("Client Replay")
|
group = parser.add_argument_group("Client Replay")
|
||||||
group.add_argument(
|
group.add_argument(
|
||||||
"-c",
|
"-c",
|
||||||
|
@ -23,6 +23,7 @@ import tnetstring, filt, script, utils, encoding, proxy
|
|||||||
from email.utils import parsedate_tz, formatdate, mktime_tz
|
from email.utils import parsedate_tz, formatdate, mktime_tz
|
||||||
from netlib import odict, http, certutils
|
from netlib import odict, http, certutils
|
||||||
import controller, version
|
import controller, version
|
||||||
|
import app
|
||||||
|
|
||||||
HDR_FORM_URLENCODED = "application/x-www-form-urlencoded"
|
HDR_FORM_URLENCODED = "application/x-www-form-urlencoded"
|
||||||
CONTENT_MISSING = 0
|
CONTENT_MISSING = 0
|
||||||
@ -42,13 +43,13 @@ class ReplaceHooks:
|
|||||||
|
|
||||||
def add(self, fpatt, rex, s):
|
def add(self, fpatt, rex, s):
|
||||||
"""
|
"""
|
||||||
Add a replacement hook.
|
add a replacement hook.
|
||||||
|
|
||||||
fpatt: A string specifying a filter pattern.
|
fpatt: a string specifying a filter pattern.
|
||||||
rex: A regular expression.
|
rex: a regular expression.
|
||||||
s: The replacement string
|
s: the replacement string
|
||||||
|
|
||||||
Returns True if hook was added, False if the pattern could not be
|
returns true if hook was added, false if the pattern could not be
|
||||||
parsed.
|
parsed.
|
||||||
"""
|
"""
|
||||||
cpatt = filt.parse(fpatt)
|
cpatt = filt.parse(fpatt)
|
||||||
@ -1352,6 +1353,7 @@ class FlowMaster(controller.Master):
|
|||||||
self.setheaders = SetHeaders()
|
self.setheaders = SetHeaders()
|
||||||
|
|
||||||
self.stream = None
|
self.stream = None
|
||||||
|
app.mapp.config["PMASTER"] = self
|
||||||
|
|
||||||
def add_event(self, e, level="info"):
|
def add_event(self, e, level="info"):
|
||||||
"""
|
"""
|
||||||
|
@ -17,8 +17,11 @@ import shutil, tempfile, threading
|
|||||||
import SocketServer
|
import SocketServer
|
||||||
from OpenSSL import SSL
|
from OpenSSL import SSL
|
||||||
from netlib import odict, tcp, http, wsgi, certutils, http_status, http_auth
|
from netlib import odict, tcp, http, wsgi, certutils, http_status, http_auth
|
||||||
import utils, flow, version, platform, controller
|
import utils, flow, version, platform, controller, app
|
||||||
|
|
||||||
|
|
||||||
|
APP_DOMAIN = "mitm"
|
||||||
|
APP_IP = "1.1.1.1"
|
||||||
KILL = 0
|
KILL = 0
|
||||||
|
|
||||||
|
|
||||||
@ -36,8 +39,8 @@ class Log:
|
|||||||
|
|
||||||
|
|
||||||
class ProxyConfig:
|
class ProxyConfig:
|
||||||
def __init__(self, certfile = None, cacert = None, clientcerts = None, no_upstream_cert=False, body_size_limit = None, reverse_proxy=None, transparent_proxy=None, certdir = None, authenticator=None):
|
def __init__(self, app=False, certfile = None, cacert = None, clientcerts = None, no_upstream_cert=False, body_size_limit = None, reverse_proxy=None, transparent_proxy=None, certdir = None, authenticator=None):
|
||||||
assert not (reverse_proxy and transparent_proxy)
|
self.app = app
|
||||||
self.certfile = certfile
|
self.certfile = certfile
|
||||||
self.cacert = cacert
|
self.cacert = cacert
|
||||||
self.clientcerts = clientcerts
|
self.clientcerts = clientcerts
|
||||||
@ -85,6 +88,7 @@ class ServerConnection(tcp.TCPClient):
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class RequestReplayThread(threading.Thread):
|
class RequestReplayThread(threading.Thread):
|
||||||
def __init__(self, config, flow, masterq):
|
def __init__(self, config, flow, masterq):
|
||||||
self.config, self.flow, self.channel = config, flow, controller.Channel(masterq)
|
self.config, self.flow, self.channel = config, flow, controller.Channel(masterq)
|
||||||
@ -497,6 +501,17 @@ class ProxyServer(tcp.TCPServer):
|
|||||||
raise ProxyServerError('Error starting proxy server: ' + v.strerror)
|
raise ProxyServerError('Error starting proxy server: ' + v.strerror)
|
||||||
self.channel = None
|
self.channel = None
|
||||||
self.apps = AppRegistry()
|
self.apps = AppRegistry()
|
||||||
|
if config.app:
|
||||||
|
self.apps.add(
|
||||||
|
app.mapp,
|
||||||
|
APP_DOMAIN,
|
||||||
|
80
|
||||||
|
)
|
||||||
|
self.apps.add(
|
||||||
|
app.mapp,
|
||||||
|
APP_IP,
|
||||||
|
80
|
||||||
|
)
|
||||||
|
|
||||||
def start_slave(self, klass, channel):
|
def start_slave(self, klass, channel):
|
||||||
slave = klass(channel, self)
|
slave = klass(channel, self)
|
||||||
@ -629,6 +644,7 @@ def process_proxy_options(parser, options):
|
|||||||
authenticator = http_auth.NullProxyAuth(None)
|
authenticator = http_auth.NullProxyAuth(None)
|
||||||
|
|
||||||
return ProxyConfig(
|
return ProxyConfig(
|
||||||
|
app = options.app,
|
||||||
certfile = options.cert,
|
certfile = options.cert,
|
||||||
cacert = cacert,
|
cacert = cacert,
|
||||||
clientcerts = options.clientcerts,
|
clientcerts = options.clientcerts,
|
||||||
|
@ -53,7 +53,16 @@ class CommonMixin:
|
|||||||
assert "Bad Request" in t.rfile.readline()
|
assert "Bad Request" in t.rfile.readline()
|
||||||
|
|
||||||
|
|
||||||
class TestHTTP(tservers.HTTPProxTest, CommonMixin):
|
|
||||||
|
class AppMixin:
|
||||||
|
def test_app(self):
|
||||||
|
ret = self.app("/")
|
||||||
|
assert ret.status_code == 200
|
||||||
|
assert "mitmproxy" in ret.content
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class TestHTTP(tservers.HTTPProxTest, CommonMixin, AppMixin):
|
||||||
def test_app_err(self):
|
def test_app_err(self):
|
||||||
p = self.pathoc()
|
p = self.pathoc()
|
||||||
ret = p.request("get:'http://errapp/'")
|
ret = p.request("get:'http://errapp/'")
|
||||||
@ -135,6 +144,7 @@ class TestHTTP(tservers.HTTPProxTest, CommonMixin):
|
|||||||
assert req.status_code == 400
|
assert req.status_code == 400
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class TestHTTPAuth(tservers.HTTPProxTest):
|
class TestHTTPAuth(tservers.HTTPProxTest):
|
||||||
authenticator = http_auth.BasicProxyAuth(http_auth.PassManSingleUser("test", "test"), "realm")
|
authenticator = http_auth.BasicProxyAuth(http_auth.PassManSingleUser("test", "test"), "realm")
|
||||||
def test_auth(self):
|
def test_auth(self):
|
||||||
|
@ -84,6 +84,7 @@ class ProxTestBase:
|
|||||||
no_upstream_cert = cls.no_upstream_cert,
|
no_upstream_cert = cls.no_upstream_cert,
|
||||||
cacert = tutils.test_data.path("data/serverkey.pem"),
|
cacert = tutils.test_data.path("data/serverkey.pem"),
|
||||||
authenticator = cls.authenticator,
|
authenticator = cls.authenticator,
|
||||||
|
app = True,
|
||||||
**pconf
|
**pconf
|
||||||
)
|
)
|
||||||
tmaster = cls.masterclass(cls.tqueue, config)
|
tmaster = cls.masterclass(cls.tqueue, config)
|
||||||
@ -156,6 +157,17 @@ class HTTPProxTest(ProxTestBase):
|
|||||||
q = "get:'%s/p/%s'"%(self.server.urlbase, spec)
|
q = "get:'%s/p/%s'"%(self.server.urlbase, spec)
|
||||||
return p.request(q)
|
return p.request(q)
|
||||||
|
|
||||||
|
def app(self, page):
|
||||||
|
if self.ssl:
|
||||||
|
p = libpathod.pathoc.Pathoc("127.0.0.1", self.proxy.port, True)
|
||||||
|
print "PRE"
|
||||||
|
p.connect((proxy.APP_IP, 80))
|
||||||
|
print "POST"
|
||||||
|
return p.request("get:'/%s'"%page)
|
||||||
|
else:
|
||||||
|
p = self.pathoc()
|
||||||
|
return p.request("get:'http://%s/%s'"%(proxy.APP_DOMAIN, page))
|
||||||
|
|
||||||
|
|
||||||
class TResolver:
|
class TResolver:
|
||||||
def __init__(self, port):
|
def __init__(self, port):
|
||||||
@ -234,3 +246,6 @@ class ReverseProxTest(ProxTestBase):
|
|||||||
q = "get:'/p/%s'"%spec
|
q = "get:'/p/%s'"%spec
|
||||||
return p.request(q)
|
return p.request(q)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user