mirror of
https://github.com/Grasscutters/mitmproxy.git
synced 2025-01-30 14:58:38 +00:00
Merge pull request #1480 from mhils/reverse-proxy-auth
Add basic auth support for reverse proxy mode
This commit is contained in:
commit
17c65e46cb
@ -132,6 +132,8 @@ class HttpLayer(base.Layer):
|
||||
# We cannot rely on server_conn.tls_established,
|
||||
# see https://github.com/mitmproxy/mitmproxy/issues/925
|
||||
self.__initial_server_tls = None
|
||||
# Requests happening after CONNECT do not need Proxy-Authorization headers.
|
||||
self.http_authenticated = False
|
||||
|
||||
def __call__(self):
|
||||
if self.mode == "transparent":
|
||||
@ -146,7 +148,7 @@ class HttpLayer(base.Layer):
|
||||
# Proxy Authentication conceptually does not work in transparent mode.
|
||||
# We catch this misconfiguration on startup. Here, we sort out requests
|
||||
# after a successful CONNECT request (which do not need to be validated anymore)
|
||||
if self.mode != "transparent" and not self.authenticate(request):
|
||||
if not (self.http_authenticated or self.authenticate(request)):
|
||||
return
|
||||
|
||||
# Make sure that the incoming request matches our expectations
|
||||
@ -239,6 +241,7 @@ class HttpLayer(base.Layer):
|
||||
return self.set_server(address)
|
||||
|
||||
def handle_regular_mode_connect(self, request):
|
||||
self.http_authenticated = True
|
||||
self.set_server((request.host, request.port))
|
||||
self.send_response(models.make_connect_response(request.data.http_version))
|
||||
layer = self.ctx.next_layer(self)
|
||||
@ -397,10 +400,17 @@ class HttpLayer(base.Layer):
|
||||
if self.config.authenticator.authenticate(request.headers):
|
||||
self.config.authenticator.clean(request.headers)
|
||||
else:
|
||||
self.send_response(models.make_error_response(
|
||||
407,
|
||||
"Proxy Authentication Required",
|
||||
http.Headers(**self.config.authenticator.auth_challenge_headers())
|
||||
))
|
||||
if self.mode == "transparent":
|
||||
self.send_response(models.make_error_response(
|
||||
401,
|
||||
"Authentication Required",
|
||||
http.Headers(**self.config.authenticator.auth_challenge_headers())
|
||||
))
|
||||
else:
|
||||
self.send_response(models.make_error_response(
|
||||
407,
|
||||
"Proxy Authentication Required",
|
||||
http.Headers(**self.config.authenticator.auth_challenge_headers())
|
||||
))
|
||||
return False
|
||||
return True
|
||||
|
@ -179,7 +179,13 @@ class ProxyConfig:
|
||||
)
|
||||
except ValueError as v:
|
||||
raise exceptions.OptionsError(str(v))
|
||||
self.authenticator = authentication.BasicProxyAuth(
|
||||
password_manager,
|
||||
"mitmproxy"
|
||||
)
|
||||
if options.mode == "reverse":
|
||||
self.authenticator = authentication.BasicWebsiteAuth(
|
||||
password_manager,
|
||||
self.upstream_server.address
|
||||
)
|
||||
else:
|
||||
self.authenticator = authentication.BasicProxyAuth(
|
||||
password_manager,
|
||||
"mitmproxy"
|
||||
)
|
@ -50,9 +50,9 @@ class NullProxyAuth(object):
|
||||
return {}
|
||||
|
||||
|
||||
class BasicProxyAuth(NullProxyAuth):
|
||||
CHALLENGE_HEADER = 'Proxy-Authenticate'
|
||||
AUTH_HEADER = 'Proxy-Authorization'
|
||||
class BasicAuth(NullProxyAuth):
|
||||
CHALLENGE_HEADER = None
|
||||
AUTH_HEADER = None
|
||||
|
||||
def __init__(self, password_manager, realm):
|
||||
NullProxyAuth.__init__(self, password_manager)
|
||||
@ -80,6 +80,16 @@ class BasicProxyAuth(NullProxyAuth):
|
||||
return {self.CHALLENGE_HEADER: 'Basic realm="%s"' % self.realm}
|
||||
|
||||
|
||||
class BasicWebsiteAuth(BasicAuth):
|
||||
CHALLENGE_HEADER = 'WWW-Authenticate'
|
||||
AUTH_HEADER = 'Authorization'
|
||||
|
||||
|
||||
class BasicProxyAuth(BasicAuth):
|
||||
CHALLENGE_HEADER = 'Proxy-Authenticate'
|
||||
AUTH_HEADER = 'Proxy-Authorization'
|
||||
|
||||
|
||||
class PassMan(object):
|
||||
|
||||
def test(self, username_, password_token_):
|
||||
|
@ -313,6 +313,22 @@ class TestHTTPAuth(tservers.HTTPProxyTest):
|
||||
assert ret.status_code == 202
|
||||
|
||||
|
||||
class TestHTTPReverseAuth(tservers.ReverseProxyTest):
|
||||
def test_auth(self):
|
||||
self.master.options.auth_singleuser = "test:test"
|
||||
assert self.pathod("202").status_code == 401
|
||||
p = self.pathoc()
|
||||
ret = p.request("""
|
||||
get
|
||||
'/p/202'
|
||||
h'%s'='%s'
|
||||
""" % (
|
||||
http.authentication.BasicWebsiteAuth.AUTH_HEADER,
|
||||
authentication.assemble_http_basic_auth("basic", "test", "test")
|
||||
))
|
||||
assert ret.status_code == 202
|
||||
|
||||
|
||||
class TestHTTPS(tservers.HTTPProxyTest, CommonMixin, TcpMixin):
|
||||
ssl = True
|
||||
ssloptions = pathod.SSLOptions(request_client_cert=True)
|
||||
|
Loading…
Reference in New Issue
Block a user