diff --git a/README.md b/README.md index 2d842c452b..cafa99d656 100644 --- a/README.md +++ b/README.md @@ -59,6 +59,7 @@ - [Proxy Pool Plugin](#proxypoolplugin) - [Filter By Client IP Plugin](#filterbyclientipplugin) - [Modify Chunk Response Plugin](#modifychunkresponseplugin) + - [Modify Request Header Plugin](#modifyrequestheaderplugin) - [Cloudflare DNS Resolver Plugin](#cloudflarednsresolverplugin) - [Custom DNS Resolver Plugin](#customdnsresolverplugin) - [Custom Network Interface](#customnetworkinterface) @@ -932,6 +933,31 @@ plugin Modify `ModifyChunkResponsePlugin` to your taste. Example, instead of sending hard-coded chunks, parse and modify the original `JSON` chunks received from the upstream server. +### ModifyRequestHeaderPlugin + +This plugin demonstrate how to modify outgoing HTTPS request headers under TLS interception mode. + +Start `proxy.py` as: + +```console +❯ proxy \ + --plugins proxy.plugin.ModifyRequestHeaderPlugin \ + ... [TLS interception flags] ... +``` + +Verify using `curl -x localhost:8899 --cacert ca-cert.pem https://httpbin.org/get`: + +```console +{ + "args": {}, + "headers": { + ... [redacted] ..., + "X-Proxy-Py-Version": "2.4.4rc6.dev15+gf533c711" + }, + ... [redacted] ... +} +``` + ### CloudflareDnsResolverPlugin This plugin uses `Cloudflare` hosted `DNS-over-HTTPS` [API](https://developers.cloudflare.com/1.1.1.1/encrypted-dns/dns-over-https/make-api-requests/dns-json) (json). diff --git a/proxy/http/server/web.py b/proxy/http/server/web.py index f756494380..f3899e890c 100644 --- a/proxy/http/server/web.py +++ b/proxy/http/server/web.py @@ -217,7 +217,7 @@ def on_client_data(self, raw: memoryview) -> None: self.pipeline_request = None def on_response_chunk(self, chunk: List[memoryview]) -> List[memoryview]: - self._response_size += sum([len(c) for c in chunk]) + self._response_size += sum(len(c) for c in chunk) return chunk def on_client_connection_close(self) -> None: diff --git a/proxy/plugin/__init__.py b/proxy/plugin/__init__.py index c3ad91945b..74c7e8d4ef 100644 --- a/proxy/plugin/__init__.py +++ b/proxy/plugin/__init__.py @@ -32,6 +32,7 @@ from .filter_by_client_ip import FilterByClientIpPlugin from .filter_by_url_regex import FilterByURLRegexPlugin from .modify_chunk_response import ModifyChunkResponsePlugin +from .modify_request_header import ModifyRequestHeaderPlugin from .redirect_to_custom_server import RedirectToCustomServerPlugin @@ -53,4 +54,5 @@ 'CustomDnsResolverPlugin', 'CloudflareDnsResolverPlugin', 'ProgramNamePlugin', + 'ModifyRequestHeaderPlugin', ] diff --git a/proxy/plugin/modify_request_header.py b/proxy/plugin/modify_request_header.py new file mode 100644 index 0000000000..72735c2781 --- /dev/null +++ b/proxy/plugin/modify_request_header.py @@ -0,0 +1,40 @@ +# -*- coding: utf-8 -*- +""" + proxy.py + ~~~~~~~~ + ⚡⚡⚡ Fast, Lightweight, Pluggable, TLS interception capable proxy server focused on + Network monitoring, controls & Application development, testing, debugging. + + :copyright: (c) 2013-present by Abhinav Singh and contributors. + :license: BSD, see LICENSE for more details. +""" +from typing import Optional + +from ..http.proxy import HttpProxyBasePlugin +from ..http.parser import HttpParser +from ..common.utils import bytes_ +from ..common.version import __version__ + + +class ModifyRequestHeaderPlugin(HttpProxyBasePlugin): + """Modify request header before sending to upstream server.""" + + # def before_upstream_connection(self, request: HttpParser) -> Optional[HttpParser]: + # """NOTE: Use this for HTTP only request headers modification.""" + # request.add_header( + # b"x-proxy-py-version", + # bytes_(__version__), + # ) + # return request + + def handle_client_request(self, request: HttpParser) -> Optional[HttpParser]: + """NOTE: This is for HTTPS request headers modification when under TLS interception. + + For HTTPS requests, modification of request under TLS interception WILL NOT WORK + through before_upstream_connection. + """ + request.add_header( + b'x-proxy-py-version', + bytes_(__version__), + ) + return request