mirror of
https://github.com/Grasscutters/mitmproxy.git
synced 2024-11-30 03:14:22 +00:00
Merge pull request #2053 from krsoninikhil/on-issues
Adds --keep-host-header option (#2039)
This commit is contained in:
commit
78fd5a9dad
@ -31,7 +31,8 @@ Host Header
|
||||
|
||||
In reverse proxy mode, mitmproxy automatically rewrites the Host header to match the
|
||||
upstream server. This allows mitmproxy to easily connect to existing endpoints on the
|
||||
open web (e.g. ``mitmproxy -R https://example.com``).
|
||||
open web (e.g. ``mitmproxy -R https://example.com``). You can disable this behaviour
|
||||
by passing ``--keep-host-header`` on the console.
|
||||
|
||||
However, keep in mind that absolute URLs within the returned document or HTTP redirects will
|
||||
NOT be rewritten by mitmproxy. This means that if you click on a link for "http://example.com"
|
||||
@ -39,4 +40,4 @@ in the returned web page, you will be taken directly to that URL, bypassing mitm
|
||||
|
||||
One possible way to address this is to modify the hosts file of your OS so that "example.com"
|
||||
resolves to your proxy's IP, and then access the proxy by going directly to example.com.
|
||||
Make sure that your proxy can still resolve the original IP, or specify an IP in mitmproxy.
|
||||
Make sure that your proxy can still resolve the original IP, or specify an IP in mitmproxy.
|
||||
|
@ -13,6 +13,8 @@ Usage:
|
||||
-s dns_spoofing.py
|
||||
# Used as the target location if neither SNI nor host header are present.
|
||||
-R http://example.com/
|
||||
# To avoid auto rewriting of host header by the reverse proxy target.
|
||||
--keep-host-header
|
||||
mitmdump
|
||||
-p 80
|
||||
-R http://localhost:443/
|
||||
@ -29,13 +31,6 @@ parse_host_header = re.compile(r"^(?P<host>[^:]+|\[.+\])(?::(?P<port>\d+))?$")
|
||||
|
||||
|
||||
class Rerouter:
|
||||
def requestheaders(self, flow):
|
||||
"""
|
||||
The original host header is retrieved early
|
||||
before flow.request is replaced by mitmproxy new outgoing request
|
||||
"""
|
||||
flow.metadata["original_host"] = flow.request.host_header
|
||||
|
||||
def request(self, flow):
|
||||
if flow.client_conn.ssl_established:
|
||||
flow.request.scheme = "https"
|
||||
@ -46,7 +41,7 @@ class Rerouter:
|
||||
sni = None
|
||||
port = 80
|
||||
|
||||
host_header = flow.metadata["original_host"]
|
||||
host_header = flow.request.host_header
|
||||
m = parse_host_header.match(host_header)
|
||||
if m:
|
||||
host_header = m.group("host").strip("[]")
|
||||
|
@ -72,6 +72,7 @@ class Options(optmanager.OptManager):
|
||||
upstream_bind_address: str = "",
|
||||
mode: str = "regular",
|
||||
no_upstream_cert: bool = False,
|
||||
keep_host_header: bool = False,
|
||||
|
||||
http2: bool = True,
|
||||
http2_priority: bool = False,
|
||||
@ -162,6 +163,7 @@ class Options(optmanager.OptManager):
|
||||
self.upstream_bind_address = upstream_bind_address
|
||||
self.mode = mode
|
||||
self.no_upstream_cert = no_upstream_cert
|
||||
self.keep_host_header = keep_host_header
|
||||
|
||||
self.http2 = http2
|
||||
self.http2_priority = http2_priority
|
||||
|
@ -288,7 +288,7 @@ class HttpLayer(base.Layer):
|
||||
request.first_line_format = "relative"
|
||||
|
||||
# update host header in reverse proxy mode
|
||||
if self.config.options.mode == "reverse":
|
||||
if self.config.options.mode == "reverse" and not self.config.options.keep_host_header:
|
||||
f.request.host_header = self.config.upstream_server.address[0]
|
||||
|
||||
# Determine .scheme, .host and .port attributes for inline scripts. For
|
||||
|
@ -112,6 +112,7 @@ def get_common_options(args):
|
||||
replacements=args.replacements,
|
||||
replacement_files=args.replacement_files,
|
||||
setheaders=args.setheaders,
|
||||
keep_host_header=args.keep_host_header,
|
||||
server_replay=args.server_replay,
|
||||
scripts=args.scripts,
|
||||
stickycookie=stickycookie,
|
||||
@ -387,6 +388,11 @@ def proxy_options(parser):
|
||||
action="store", type=str, dest="upstream_bind_address",
|
||||
help="Address to bind upstream requests to (defaults to none)"
|
||||
)
|
||||
group.add_argument(
|
||||
"--keep-host-header",
|
||||
action="store_true", dest="keep_host_header",
|
||||
help="Reverse Proxy: Keep the original host header instead of rewriting it to the reverse proxy target."
|
||||
)
|
||||
|
||||
|
||||
def proxy_ssl_options(parser):
|
||||
|
@ -481,6 +481,26 @@ class TestHTTPSNoCommonName(tservers.HTTPProxyTest):
|
||||
class TestReverse(tservers.ReverseProxyTest, CommonMixin, TcpMixin):
|
||||
reverse = True
|
||||
|
||||
def test_host_header(self):
|
||||
self.config.options.keep_host_header = True
|
||||
p = self.pathoc()
|
||||
with p.connect():
|
||||
resp = p.request("get:/p/200:h'Host'='example.com'")
|
||||
assert resp.status_code == 200
|
||||
|
||||
req = self.master.state.flows[0].request
|
||||
assert req.host_header == "example.com"
|
||||
|
||||
def test_overridden_host_header(self):
|
||||
self.config.options.keep_host_header = False # default value
|
||||
p = self.pathoc()
|
||||
with p.connect():
|
||||
resp = p.request("get:/p/200:h'Host'='example.com'")
|
||||
assert resp.status_code == 200
|
||||
|
||||
req = self.master.state.flows[0].request
|
||||
assert req.host_header == "127.0.0.1"
|
||||
|
||||
|
||||
class TestReverseSSL(tservers.ReverseProxyTest, CommonMixin, TcpMixin):
|
||||
reverse = True
|
||||
|
@ -114,13 +114,11 @@ class TestScripts(tservers.MasterTest):
|
||||
|
||||
# Rewrite by reverse proxy mode
|
||||
f.request.scheme = "https"
|
||||
f.request.host = "mitmproxy.org"
|
||||
f.request.port = 443
|
||||
|
||||
m.request(f)
|
||||
|
||||
assert f.request.scheme == "http"
|
||||
assert f.request.host == original_host
|
||||
assert f.request.port == 80
|
||||
|
||||
assert f.request.headers["Host"] == original_host
|
||||
|
Loading…
Reference in New Issue
Block a user