aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--docs/certinstall.rst12
-rw-r--r--docs/features/reverseproxy.rst5
-rw-r--r--examples/complex/dns_spoofing.py11
-rw-r--r--mitmproxy/options.py2
-rw-r--r--mitmproxy/proxy/protocol/http.py2
-rw-r--r--mitmproxy/proxy/protocol/http2.py3
-rw-r--r--mitmproxy/tools/cmdline.py6
-rw-r--r--test/mitmproxy/proxy/protocol/test_http2.py69
-rw-r--r--test/mitmproxy/proxy/test_server.py20
-rw-r--r--test/mitmproxy/test_examples.py2
10 files changed, 41 insertions, 91 deletions
diff --git a/docs/certinstall.rst b/docs/certinstall.rst
index 5d97e92c..1bd6df99 100644
--- a/docs/certinstall.rst
+++ b/docs/certinstall.rst
@@ -42,7 +42,7 @@ iOS
See http://jasdev.me/intercepting-ios-traffic
-and http://web.archive.org/web/20150920082614/http://kb.mit.edu/confluence/pages/viewpage.action?pageId=152600377
+and https://web.archive.org/web/20150920082614/http://kb.mit.edu/confluence/pages/viewpage.action?pageId=152600377
iOS Simulator
^^^^^^^^^^^^^
@@ -52,7 +52,7 @@ See https://github.com/ADVTOOLS/ADVTrustStore#how-to-use-advtruststore
Java
^^^^
-See http://docs.oracle.com/cd/E19906-01/820-4916/geygn/index.html
+See https://docs.oracle.com/cd/E19906-01/820-4916/geygn/index.html
Android/Android Simulator
^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -62,7 +62,7 @@ See http://wiki.cacert.org/FAQ/ImportRootCert#Android_Phones_.26_Tablets
Windows
^^^^^^^
-See http://windows.microsoft.com/en-ca/windows/import-export-certificates-private-keys#1TC=windows-7
+See https://web.archive.org/web/20160612045445/http://windows.microsoft.com/en-ca/windows/import-export-certificates-private-keys#1TC=windows-7
Windows (automated)
^^^^^^^^^^^^^^^^^^^
@@ -79,7 +79,7 @@ See https://support.apple.com/kb/PH7297?locale=en_US
Ubuntu/Debian
^^^^^^^^^^^^^
-See http://askubuntu.com/questions/73287/how-do-i-install-a-root-certificate/94861#94861
+See https://askubuntu.com/questions/73287/how-do-i-install-a-root-certificate/94861#94861
Mozilla Firefox
^^^^^^^^^^^^^^^
@@ -89,7 +89,7 @@ See https://wiki.mozilla.org/MozillaRootCertificate#Mozilla_Firefox
Chrome on Linux
^^^^^^^^^^^^^^^
-See https://code.google.com/p/chromium/wiki/LinuxCertManagement
+See https://stackoverflow.com/a/15076602/198996
The mitmproxy certificate authority
@@ -205,4 +205,4 @@ directory and uses this as the client cert.
-.. _Certificate Pinning: http://security.stackexchange.com/questions/29988/what-is-certificate-pinning/
+.. _Certificate Pinning: https://security.stackexchange.com/questions/29988/what-is-certificate-pinning/
diff --git a/docs/features/reverseproxy.rst b/docs/features/reverseproxy.rst
index 85ad33e8..57b353ae 100644
--- a/docs/features/reverseproxy.rst
+++ b/docs/features/reverseproxy.rst
@@ -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. \ No newline at end of file
+Make sure that your proxy can still resolve the original IP, or specify an IP in mitmproxy.
diff --git a/examples/complex/dns_spoofing.py b/examples/complex/dns_spoofing.py
index acda303d..2fd6b699 100644
--- a/examples/complex/dns_spoofing.py
+++ b/examples/complex/dns_spoofing.py
@@ -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("[]")
diff --git a/mitmproxy/options.py b/mitmproxy/options.py
index 2467b9dd..ff17fbbf 100644
--- a/mitmproxy/options.py
+++ b/mitmproxy/options.py
@@ -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
diff --git a/mitmproxy/proxy/protocol/http.py b/mitmproxy/proxy/protocol/http.py
index 16d04eeb..b6f8463d 100644
--- a/mitmproxy/proxy/protocol/http.py
+++ b/mitmproxy/proxy/protocol/http.py
@@ -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
diff --git a/mitmproxy/proxy/protocol/http2.py b/mitmproxy/proxy/protocol/http2.py
index 019159de..01406798 100644
--- a/mitmproxy/proxy/protocol/http2.py
+++ b/mitmproxy/proxy/protocol/http2.py
@@ -597,9 +597,6 @@ class Http2SingleStreamLayer(httpbase._HttpTransmissionLayer, basethread.BaseThr
def send_response_headers(self, response):
headers = response.headers.copy()
headers.insert(0, ":status", str(response.status_code))
- for forbidden_header in h2.utilities.CONNECTION_HEADERS:
- if forbidden_header in headers:
- del headers[forbidden_header]
with self.connections[self.client_conn].lock:
self.connections[self.client_conn].safe_send_headers(
self.raise_zombie,
diff --git a/mitmproxy/tools/cmdline.py b/mitmproxy/tools/cmdline.py
index bb0bb17a..11558cc3 100644
--- a/mitmproxy/tools/cmdline.py
+++ b/mitmproxy/tools/cmdline.py
@@ -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):
diff --git a/test/mitmproxy/proxy/protocol/test_http2.py b/test/mitmproxy/proxy/protocol/test_http2.py
index 19c2d2ef..871d02fe 100644
--- a/test/mitmproxy/proxy/protocol/test_http2.py
+++ b/test/mitmproxy/proxy/protocol/test_http2.py
@@ -272,75 +272,6 @@ class TestSimple(_Http2Test):
@requires_alpn
-class TestForbiddenHeaders(_Http2Test):
-
- @classmethod
- def handle_server_event(cls, event, h2_conn, rfile, wfile):
- if isinstance(event, h2.events.ConnectionTerminated):
- return False
- elif isinstance(event, h2.events.StreamEnded):
- import warnings
- with warnings.catch_warnings():
- # Ignore UnicodeWarning:
- # h2/utilities.py:64: UnicodeWarning: Unicode equal comparison
- # failed to convert both arguments to Unicode - interpreting
- # them as being unequal.
- # elif header[0] in (b'cookie', u'cookie') and len(header[1]) < 20:
-
- warnings.simplefilter("ignore")
-
- h2_conn.config.validate_outbound_headers = False
- h2_conn.send_headers(event.stream_id, [
- (':status', '200'),
- ('keep-alive', 'foobar'),
- ])
- h2_conn.send_data(event.stream_id, b'response body')
- h2_conn.end_stream(event.stream_id)
- wfile.write(h2_conn.data_to_send())
- wfile.flush()
- return True
-
- def test_forbidden_headers(self):
- client, h2_conn = self._setup_connection()
-
- self._send_request(
- client.wfile,
- h2_conn,
- headers=[
- (':authority', "127.0.0.1:{}".format(self.server.server.address[1])),
- (':method', 'GET'),
- (':scheme', 'https'),
- (':path', '/'),
- ])
-
- done = False
- while not done:
- try:
- raw = b''.join(http2.read_raw_frame(client.rfile))
- events = h2_conn.receive_data(raw)
- except exceptions.HttpException:
- print(traceback.format_exc())
- assert False
-
- client.wfile.write(h2_conn.data_to_send())
- client.wfile.flush()
-
- for event in events:
- if isinstance(event, h2.events.ResponseReceived):
- assert 'keep-alive' not in event.headers
- elif isinstance(event, h2.events.StreamEnded):
- done = True
-
- h2_conn.close_connection()
- client.wfile.write(h2_conn.data_to_send())
- client.wfile.flush()
-
- assert len(self.master.state.flows) == 1
- assert self.master.state.flows[0].response.status_code == 200
- assert self.master.state.flows[0].response.headers['keep-alive'] == 'foobar'
-
-
-@requires_alpn
class TestRequestWithPriority(_Http2Test):
@classmethod
diff --git a/test/mitmproxy/proxy/test_server.py b/test/mitmproxy/proxy/test_server.py
index 8b133085..56b09b9a 100644
--- a/test/mitmproxy/proxy/test_server.py
+++ b/test/mitmproxy/proxy/test_server.py
@@ -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
diff --git a/test/mitmproxy/test_examples.py b/test/mitmproxy/test_examples.py
index f3603fca..668d0d4a 100644
--- a/test/mitmproxy/test_examples.py
+++ b/test/mitmproxy/test_examples.py
@@ -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