Skip to content

Commit f5f18e4

Browse files
authored
TLS Intercept conditionally (#1476)
* TLS intercept conditionally * Lint fixes * Fix test assertions * Fix tests * Bump `sphinxcontrib-spelling == 8.0.0` due to deprecated pypi XML APIs, ref pypi/warehouse#16642 * Disable spellcheck-docs for now until we have a clear path forward
1 parent a51ddaa commit f5f18e4

File tree

5 files changed

+43
-21
lines changed

5 files changed

+43
-21
lines changed

.github/workflows/test-library.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -340,7 +340,7 @@ jobs:
340340
- build-docs
341341
- doctest-docs
342342
- linkcheck-docs
343-
- spellcheck-docs
343+
# - spellcheck-docs
344344
fail-fast: false
345345

346346
env:

proxy/http/proxy/server.py

Lines changed: 18 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -281,10 +281,7 @@ async def read_from_descriptors(self, r: Readables) -> bool:
281281
# only for non-https requests and when
282282
# tls interception is enabled
283283
if raw is not None:
284-
if (
285-
not self.request.is_https_tunnel
286-
or self.tls_interception_enabled
287-
):
284+
if not self.request.is_https_tunnel or self._tls_intercept_enabled:
288285
if self.response.is_complete:
289286
self.handle_pipeline_response(raw)
290287
else:
@@ -429,8 +426,7 @@ def on_client_data(self, raw: memoryview) -> None:
429426
# We also handle pipeline scenario for https proxy
430427
# requests is TLS interception is enabled.
431428
if self.request.is_complete and (
432-
not self.request.is_https_tunnel or
433-
self.tls_interception_enabled
429+
not self.request.is_https_tunnel or self._tls_intercept_enabled
434430
):
435431
if self.pipeline_request is not None and \
436432
self.pipeline_request.is_connection_upgrade:
@@ -474,6 +470,20 @@ def on_client_data(self, raw: memoryview) -> None:
474470
else:
475471
self.upstream.queue(raw)
476472

473+
@property
474+
def _tls_intercept_enabled(self) -> bool:
475+
do_intercept = self.tls_interception_enabled
476+
if not do_intercept:
477+
return do_intercept
478+
# If enabled by flags, check if a plugin wants us to bypass
479+
# interception for this particular request
480+
for plugin in self.plugins.values():
481+
do_intercept = plugin.do_intercept(self.request)
482+
# A plugin requested to not intercept the request
483+
if do_intercept is False:
484+
break
485+
return do_intercept
486+
477487
def on_request_complete(self) -> Union[socket.socket, bool]:
478488
self.emit_request_complete()
479489

@@ -510,19 +520,8 @@ def on_request_complete(self) -> Union[socket.socket, bool]:
510520
if self.upstream:
511521
if self.request.is_https_tunnel:
512522
self.client.queue(PROXY_TUNNEL_ESTABLISHED_RESPONSE_PKT)
513-
if self.tls_interception_enabled:
514-
# Check if any plugin wants to
515-
# disable interception even
516-
# with flags available
517-
do_intercept = True
518-
for plugin in self.plugins.values():
519-
do_intercept = plugin.do_intercept(self.request)
520-
# A plugin requested to not intercept
521-
# the request
522-
if do_intercept is False:
523-
break
524-
if do_intercept:
525-
return self.intercept()
523+
if self._tls_intercept_enabled:
524+
return self.intercept()
526525
# If an upstream server connection was established for http request,
527526
# queue the request for upstream server.
528527
else:

proxy/plugin/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
from .modify_chunk_response import ModifyChunkResponsePlugin
3535
from .modify_request_header import ModifyRequestHeaderPlugin
3636
from .redirect_to_custom_server import RedirectToCustomServerPlugin
37+
from .tls_intercept_conditionally import TlsInterceptConditionallyPlugin
3738

3839

3940
__all__ = [
@@ -55,4 +56,5 @@
5556
'CloudflareDnsResolverPlugin',
5657
'ProgramNamePlugin',
5758
'ModifyRequestHeaderPlugin',
59+
'TlsInterceptConditionallyPlugin',
5860
]
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
# -*- coding: utf-8 -*-
2+
"""
3+
proxy.py
4+
~~~~~~~~
5+
⚡⚡⚡ Fast, Lightweight, Pluggable, TLS interception capable proxy server focused on
6+
Network monitoring, controls & Application development, testing, debugging.
7+
8+
:copyright: (c) 2013-present by Abhinav Singh and contributors.
9+
:license: BSD, see LICENSE for more details.
10+
"""
11+
from ..http.proxy import HttpProxyBasePlugin
12+
from ..http.parser import HttpParser
13+
14+
15+
class TlsInterceptConditionallyPlugin(HttpProxyBasePlugin):
16+
"""TLS intercept conditionally."""
17+
18+
def do_intercept(self, request: HttpParser) -> bool:
19+
if request.host == b'httpbin.org':
20+
return False
21+
return super().do_intercept(request)

tests/http/proxy/test_http_proxy_tls_interception.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -297,7 +297,7 @@ async def asyncReturn(val: T) -> T:
297297
self.proxy_plugin.return_value.handle_client_request.call_count,
298298
2,
299299
)
300-
self.proxy_plugin.return_value.do_intercept.assert_called_once()
300+
self.assertEqual(self.proxy_plugin.return_value.do_intercept.call_count, 2)
301301

302302
callback_request = \
303303
self.proxy_plugin.return_value.handle_client_request.call_args_list[1][0][0]

0 commit comments

Comments
 (0)