Skip to content

Commit 50046d3

Browse files
abhinavsinghd4xfepre-commit-ci[bot]
authored
TLS intercept self-signed servers using --insecure-tls-interception (#1446)
* Disable mandatory TLS verification with --insecure * Fix lint issues * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Fix type issues with `cert_der_to_dict` * Flake8 exception * Fix `cert_der_to_dict` where file may not be writter before it is gets used by `_test_decode_cert` * Silence lint issue due to pylint bug * Rename flag to `--insecure-tls-interception` * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Reuse `DEFAULT_SSL_CONTEXT_OPTIONS` * # noqa: WPS436 --------- Co-authored-by: d4x <[email protected]> Co-authored-by: d4xfe <[email protected]> Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
1 parent 39854e1 commit 50046d3

File tree

8 files changed

+142
-47
lines changed

8 files changed

+142
-47
lines changed

README.md

+42-33
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@
7171
- [Plugin Ordering](#plugin-ordering)
7272
- [End-to-End Encryption](#end-to-end-encryption)
7373
- [TLS Interception](#tls-interception)
74+
- [Insecure TLS Interception](#insecure-tls-interception)
7475
- [TLS Interception With Docker](#tls-interception-with-docker)
7576
- [GROUT (NGROK Alternative)](#grout-ngrok-alternative)
7677
- [Grout Usage](#grout-usage)
@@ -1241,6 +1242,13 @@ cached file instead of plain text.
12411242
Now use CA flags with other
12421243
[plugin examples](#plugin-examples) to see them work with `https` traffic.
12431244

1245+
## Insecure TLS Interception
1246+
1247+
To intercept TLS traffic from a server using a self-signed certificate
1248+
add the `--insecure-tls-interception` flag to disable mandatory TLS certificate validation.
1249+
1250+
NOTE: This flag disables certificate check for all servers.
1251+
12441252
## TLS Interception With Docker
12451253

12461254
Important notes about TLS Interception with Docker container:
@@ -2510,17 +2518,16 @@ To run standalone benchmark for `proxy.py`, use the following command from repo
25102518

25112519
```console
25122520
proxy -h
2513-
usage: -m [-h] [--enable-proxy-protocol] [--threadless] [--threaded]
2514-
[--num-workers NUM_WORKERS] [--enable-events] [--enable-conn-pool]
2515-
[--key-file KEY_FILE] [--cert-file CERT_FILE]
2516-
[--client-recvbuf-size CLIENT_RECVBUF_SIZE]
2517-
[--server-recvbuf-size SERVER_RECVBUF_SIZE]
2518-
[--max-sendbuf-size MAX_SENDBUF_SIZE] [--timeout TIMEOUT]
2519-
[--tunnel-hostname TUNNEL_HOSTNAME] [--tunnel-port TUNNEL_PORT]
2521+
usage: -m [-h] [--tunnel-hostname TUNNEL_HOSTNAME] [--tunnel-port TUNNEL_PORT]
25202522
[--tunnel-username TUNNEL_USERNAME]
25212523
[--tunnel-ssh-key TUNNEL_SSH_KEY]
25222524
[--tunnel-ssh-key-passphrase TUNNEL_SSH_KEY_PASSPHRASE]
2523-
[--tunnel-remote-port TUNNEL_REMOTE_PORT]
2525+
[--tunnel-remote-port TUNNEL_REMOTE_PORT] [--threadless]
2526+
[--threaded] [--num-workers NUM_WORKERS] [--enable-events]
2527+
[--enable-proxy-protocol] [--enable-conn-pool] [--key-file KEY_FILE]
2528+
[--cert-file CERT_FILE] [--client-recvbuf-size CLIENT_RECVBUF_SIZE]
2529+
[--server-recvbuf-size SERVER_RECVBUF_SIZE]
2530+
[--max-sendbuf-size MAX_SENDBUF_SIZE] [--timeout TIMEOUT]
25242531
[--local-executor LOCAL_EXECUTOR] [--backlog BACKLOG]
25252532
[--hostname HOSTNAME] [--hostnames HOSTNAMES [HOSTNAMES ...]]
25262533
[--port PORT] [--ports PORTS [PORTS ...]] [--port-file PORT_FILE]
@@ -2533,9 +2540,9 @@ usage: -m [-h] [--enable-proxy-protocol] [--threadless] [--threaded]
25332540
[--work-klass WORK_KLASS] [--pid-file PID_FILE] [--openssl OPENSSL]
25342541
[--data-dir DATA_DIR] [--ssh-listener-klass SSH_LISTENER_KLASS]
25352542
[--disable-http-proxy] [--disable-headers DISABLE_HEADERS]
2536-
[--ca-key-file CA_KEY_FILE] [--ca-cert-dir CA_CERT_DIR]
2537-
[--ca-cert-file CA_CERT_FILE] [--ca-file CA_FILE]
2538-
[--ca-signing-key-file CA_SIGNING_KEY_FILE]
2543+
[--ca-key-file CA_KEY_FILE] [--insecure-tls-interception]
2544+
[--ca-cert-dir CA_CERT_DIR] [--ca-cert-file CA_CERT_FILE]
2545+
[--ca-file CA_FILE] [--ca-signing-key-file CA_SIGNING_KEY_FILE]
25392546
[--auth-plugin AUTH_PLUGIN] [--cache-requests]
25402547
[--cache-by-content-type] [--cache-dir CACHE_DIR]
25412548
[--proxy-pool PROXY_POOL] [--enable-web-server]
@@ -2549,13 +2556,25 @@ usage: -m [-h] [--enable-proxy-protocol] [--threadless] [--threaded]
25492556
[--filtered-client-ips FILTERED_CLIENT_IPS]
25502557
[--filtered-url-regex-config FILTERED_URL_REGEX_CONFIG]
25512558

2552-
proxy.py v2.4.4rc6.dev191+gef5a8922
2559+
proxy.py v2.4.5
25532560

25542561
options:
25552562
-h, --help show this help message and exit
2556-
--enable-proxy-protocol
2557-
Default: False. If used, will enable proxy protocol.
2558-
Only version 1 is currently supported.
2563+
--tunnel-hostname TUNNEL_HOSTNAME
2564+
Default: None. Remote hostname or IP address to which
2565+
SSH tunnel will be established.
2566+
--tunnel-port TUNNEL_PORT
2567+
Default: 22. SSH port of the remote host.
2568+
--tunnel-username TUNNEL_USERNAME
2569+
Default: None. Username to use for establishing SSH
2570+
tunnel.
2571+
--tunnel-ssh-key TUNNEL_SSH_KEY
2572+
Default: None. Private key path in pem format
2573+
--tunnel-ssh-key-passphrase TUNNEL_SSH_KEY_PASSPHRASE
2574+
Default: None. Private key passphrase
2575+
--tunnel-remote-port TUNNEL_REMOTE_PORT
2576+
Default: 8899. Remote port which will be forwarded
2577+
locally for proxy.
25592578
--threadless Default: True. Enabled by default on Python 3.8+ (mac,
25602579
linux). When disabled a new thread is spawned to
25612580
handle each client connection.
@@ -2567,6 +2586,9 @@ options:
25672586
--enable-events Default: False. Enables core to dispatch lifecycle
25682587
events. Plugins can be used to subscribe for core
25692588
events.
2589+
--enable-proxy-protocol
2590+
Default: False. If used, will enable proxy protocol.
2591+
Only version 1 is currently supported.
25702592
--enable-conn-pool Default: False. (WIP) Enable upstream connection
25712593
pooling.
25722594
--key-file KEY_FILE Default: None. Server key file to enable end-to-end
@@ -2588,21 +2610,6 @@ options:
25882610
--timeout TIMEOUT Default: 10.0. Number of seconds after which an
25892611
inactive connection must be dropped. Inactivity is
25902612
defined by no data sent or received by the client.
2591-
--tunnel-hostname TUNNEL_HOSTNAME
2592-
Default: None. Remote hostname or IP address to which
2593-
SSH tunnel will be established.
2594-
--tunnel-port TUNNEL_PORT
2595-
Default: 22. SSH port of the remote host.
2596-
--tunnel-username TUNNEL_USERNAME
2597-
Default: None. Username to use for establishing SSH
2598-
tunnel.
2599-
--tunnel-ssh-key TUNNEL_SSH_KEY
2600-
Default: None. Private key path in pem format
2601-
--tunnel-ssh-key-passphrase TUNNEL_SSH_KEY_PASSPHRASE
2602-
Default: None. Private key passphrase
2603-
--tunnel-remote-port TUNNEL_REMOTE_PORT
2604-
Default: 8899. Remote port which will be forwarded
2605-
locally for proxy.
26062613
--local-executor LOCAL_EXECUTOR
26072614
Default: 1. Enabled by default. Use 0 to disable. When
26082615
enabled acceptors will make use of local (same
@@ -2668,6 +2675,8 @@ options:
26682675
Default: None. CA key to use for signing dynamically
26692676
generated HTTPS certificates. If used, must also pass
26702677
--ca-cert-file and --ca-signing-key-file
2678+
--insecure-tls-interception
2679+
Default: False. Disables certificate verification
26712680
--ca-cert-dir CA_CERT_DIR
26722681
Default: ~/.proxy/certificates. Directory to store
26732682
dynamically generated certificates. Also see --ca-key-
@@ -2676,9 +2685,9 @@ options:
26762685
Default: None. Signing certificate to use for signing
26772686
dynamically generated HTTPS certificates. If used,
26782687
must also pass --ca-key-file and --ca-signing-key-file
2679-
--ca-file CA_FILE Default: /Users/abhinavsingh/Dev/proxy.py/.venv31013/l
2680-
ib/python3.10/site-packages/certifi/cacert.pem.
2681-
Provide path to custom CA bundle for peer certificate
2688+
--ca-file CA_FILE Default: /Users/abhinavsingh/Dev/proxy.py/.venv3118/li
2689+
b/python3.11/site-packages/certifi/cacert.pem. Provide
2690+
path to custom CA bundle for peer certificate
26822691
verification
26832692
--ca-signing-key-file CA_SIGNING_KEY_FILE
26842693
Default: None. CA signing key to use for dynamic

proxy/common/constants.py

+1
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@ def _env_threadless_compliant() -> bool:
9191
DEFAULT_MAX_SEND_SIZE = 64 * 1024
9292
DEFAULT_BUFFER_SIZE = 128 * 1024
9393
DEFAULT_CA_CERT_DIR = None
94+
DEFAULT_INSECURE_TLS_INTERCEPTION = False
9495
DEFAULT_CA_CERT_FILE = None
9596
DEFAULT_CA_KEY_FILE = None
9697
DEFAULT_CA_SIGNING_KEY_FILE = None

proxy/common/utils.py

+21
Original file line numberDiff line numberDiff line change
@@ -12,17 +12,21 @@
1212
1313
utils
1414
"""
15+
import os
1516
import ssl
1617
import sys
1718
import socket
1819
import logging
1920
import argparse
21+
import tempfile
2022
import functools
2123
import ipaddress
2224
import contextlib
2325
from types import TracebackType
2426
from typing import Any, Dict, List, Type, Tuple, Callable, Optional
2527

28+
import _ssl # noqa: WPS436
29+
2630
from .types import HostPort
2731
from .constants import (
2832
CRLF, COLON, HTTP_1_1, IS_WINDOWS, WHITESPACE, DEFAULT_TIMEOUT,
@@ -36,6 +40,23 @@
3640
logger = logging.getLogger(__name__)
3741

3842

43+
def cert_der_to_dict(der: Optional[bytes]) -> Dict[str, Any]:
44+
"""Parse a DER formatted certificate to a python dict"""
45+
if not der:
46+
return {}
47+
with tempfile.NamedTemporaryFile(delete=False) as cert_file:
48+
pem = ssl.DER_cert_to_PEM_cert(der)
49+
cert_file.write(pem.encode())
50+
cert_file.flush()
51+
cert_file.seek(0)
52+
try:
53+
certificate = _ssl._test_decode_cert(cert_file.name)
54+
finally:
55+
cert_file.close()
56+
os.remove(cert_file.name)
57+
return certificate or {}
58+
59+
3960
def tls_interception_enabled(flags: argparse.Namespace) -> bool:
4061
return flags.ca_key_file is not None and \
4162
flags.ca_cert_dir is not None and \

proxy/core/connection/server.py

+6-5
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
from .connection import TcpConnection, TcpConnectionUninitializedException
1616
from ...common.types import HostPort, TcpOrTlsSocket
1717
from ...common.utils import new_socket_connection
18+
from ...common.constants import DEFAULT_SSL_CONTEXT_OPTIONS
1819

1920

2021
class TcpServerConnection(TcpConnection):
@@ -51,12 +52,12 @@ def wrap(
5152
# Ref https://github.com/PyCQA/pylint/issues/3691
5253
verify_mode: ssl.VerifyMode = ssl.VerifyMode.CERT_REQUIRED, # pylint: disable=E1101
5354
) -> None:
54-
ctx = ssl.create_default_context(
55-
ssl.Purpose.SERVER_AUTH,
56-
cafile=ca_file,
55+
ctx = ssl.create_default_context(ssl.Purpose.SERVER_AUTH, cafile=ca_file)
56+
ctx.options |= DEFAULT_SSL_CONTEXT_OPTIONS
57+
# pylint: disable=E1101
58+
ctx.check_hostname = (
59+
False if verify_mode == ssl.VerifyMode.CERT_NONE else hostname is not None
5760
)
58-
ctx.options |= ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3 | ssl.OP_NO_TLSv1 | ssl.OP_NO_TLSv1_1
59-
ctx.check_hostname = hostname is not None
6061
ctx.verify_mode = verify_mode
6162
self.connection.setblocking(True)
6263
self._conn = ctx.wrap_socket(

proxy/http/proxy/server.py

+19-4
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
import logging
2222
import threading
2323
import subprocess
24-
from typing import Any, Dict, List, Union, Optional, cast
24+
from typing import Any, Dict, List, Union, Optional
2525

2626
from .plugin import HttpProxyBasePlugin
2727
from ..parser import HttpParser, httpParserTypes, httpParserStates
@@ -35,15 +35,16 @@
3535
from ...core.event import eventNames
3636
from ...common.flag import flags
3737
from ...common.types import Readables, Writables, Descriptors
38-
from ...common.utils import text_
38+
from ...common.utils import text_, cert_der_to_dict
3939
from ...core.connection import (
4040
TcpServerConnection, TcpConnectionUninitializedException,
4141
)
4242
from ...common.constants import (
4343
COMMA, DEFAULT_CA_FILE, PLUGIN_PROXY_AUTH, DEFAULT_CA_CERT_DIR,
4444
DEFAULT_CA_KEY_FILE, DEFAULT_CA_CERT_FILE, DEFAULT_DISABLE_HEADERS,
4545
PROXY_AGENT_HEADER_VALUE, DEFAULT_DISABLE_HTTP_PROXY,
46-
DEFAULT_CA_SIGNING_KEY_FILE, DEFAULT_HTTP_PROXY_ACCESS_LOG_FORMAT,
46+
DEFAULT_CA_SIGNING_KEY_FILE, DEFAULT_INSECURE_TLS_INTERCEPTION,
47+
DEFAULT_HTTP_PROXY_ACCESS_LOG_FORMAT,
4748
DEFAULT_HTTPS_PROXY_ACCESS_LOG_FORMAT,
4849
)
4950

@@ -74,6 +75,13 @@
7475
'HTTPS certificates. If used, must also pass --ca-cert-file and --ca-signing-key-file',
7576
)
7677

78+
flags.add_argument(
79+
'--insecure-tls-interception',
80+
action='store_true',
81+
default=DEFAULT_INSECURE_TLS_INTERCEPTION,
82+
help='Default: False. Disables certificate verification',
83+
)
84+
7785
flags.add_argument(
7886
'--ca-cert-dir',
7987
type=str,
@@ -760,10 +768,17 @@ def wrap_server(self) -> bool:
760768
assert isinstance(self.upstream.connection, socket.socket)
761769
do_close = False
762770
try:
771+
# pylint: disable=E1101
772+
verify_mode = (
773+
ssl.VerifyMode.CERT_NONE
774+
if self.flags.insecure_tls_interception
775+
else ssl.VerifyMode.CERT_REQUIRED
776+
)
763777
self.upstream.wrap(
764778
text_(self.request.host),
765779
self.flags.ca_file,
766780
as_non_blocking=True,
781+
verify_mode=verify_mode,
767782
)
768783
except ssl.SSLCertVerificationError: # Server raised certificate verification error
769784
# When --disable-interception-on-ssl-cert-verification-error flag is on,
@@ -802,7 +817,7 @@ def wrap_client(self) -> bool:
802817
try:
803818
# TODO: Perform async certificate generation
804819
generated_cert = self.generate_upstream_certificate(
805-
cast(Dict[str, Any], self.upstream.connection.getpeercert()),
820+
cert_der_to_dict(self.upstream.connection.getpeercert(True)),
806821
)
807822
self.client.wrap(self.flags.ca_signing_key_file, generated_cert)
808823
except subprocess.TimeoutExpired as e: # Popen communicate timeout

tests/certificates/test_cert_data.py

+45
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
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 typing import Any
12+
13+
14+
# pylint: disable=line-too-long
15+
test_cert_bytes = b"0\x82\x03\xa30\x82\x02\x8b\xa0\x03\x02\x01\x02\x02\x14PE\x01\x8c\xa6\xea\xd8#\xcf\x90\xb0D\xc7\x04\xde\x9b9Y\xf3 0\r\x06\t*\x86H\x86\xf7\r\x01\x01\x0b\x05\x000a1\x0b0\t\x06\x03U\x04\x06\x13\x02as1\x0b0\t\x06\x03U\x04\x08\x0c\x02as1\x0b0\t\x06\x03U\x04\x07\x0c\x02as1\x0b0\t\x06\x03U\x04\n\x0c\x02as1\x0b0\t\x06\x03U\x04\x0b\x0c\x02as1\x0b0\t\x06\x03U\x04\x03\x0c\x02as1\x110\x0f\x06\t*\x86H\x86\xf7\r\x01\t\x01\x16\x02as0\x1e\x17\r240429125057Z\x17\r250429125057Z0a1\x0b0\t\x06\x03U\x04\x06\x13\x02as1\x0b0\t\x06\x03U\x04\x08\x0c\x02as1\x0b0\t\x06\x03U\x04\x07\x0c\x02as1\x0b0\t\x06\x03U\x04\n\x0c\x02as1\x0b0\t\x06\x03U\x04\x0b\x0c\x02as1\x0b0\t\x06\x03U\x04\x03\x0c\x02as1\x110\x0f\x06\t*\x86H\x86\xf7\r\x01\t\x01\x16\x02as0\x82\x01\"0\r\x06\t*\x86H\x86\xf7\r\x01\x01\x01\x05\x00\x03\x82\x01\x0f\x000\x82\x01\n\x02\x82\x01\x01\x00\xee\xcbU\xe3\xc4]\x83\xb9\x9d\xb1(v0\x18\x18\xc3\x00\x96\xc0\x0f\xc29\x84\xe7/W\xc7\x0b\xec\xdf\x9d-\xec\xd9\x876\xe5m\xda\x96\xea\xb0\xc6\x00\x7f\xb6\x93;\xd6\x1bK`\xd4Hc<\xa0g\xe5Q[\xe3\xe1\xd1DD5\x9b\x12\xdf\xd0\xd0\xc6X\xc9\x98\xc9\xb1\x81\xf5\xa2\x12\xaa\xc1\xb0\x80\xe8)R\xa7\xed\xe3P6\x82\x05\xbcA4\x91\xbcs?\xc2\xf2\xfd-\xe65'};\xa7E\xb2yN\x0fiO7\x82-`CX\xdb\xe0\x9c\xd7\x8e\x00N\nAu\xac/\xb3o\xcaG;\xa4\x8d\xca\x92\xe3F\x96\xe5\xbd\x1dq\xf6\xa5\x9f\xc5@I=\xfc\x1cl\x81\xb3y\x93FaPa^\x08\x0f\x80t\xb8J\xfd\xb8]\xd52\xf5\x9bE\xe8J:\x08\x8c\x98m0\xba\x85\x1b\xb6\x97\xe5\xba4\xe3nU\xa5\xc7\xeb\xde_z\x1a(j\xa7\xeb\x8a\xb4\xe1'?\x91\x80MhG=y\xc7\xf1|\xcaJ@\xae\xc4'\xd6\xd6}L\xf4\x91NV`\x98\x80\xef%\xa2hq\x05s\x02\x03\x01\x00\x01\xa3S0Q0\x1d\x06\x03U\x1d\x0e\x04\x16\x04\x14\xc6\xa4,\xe5\xe3\x15j\x18\x15@Xw!\xdd\xbf\xc6\xe5\xf0vG0\x1f\x06\x03U\x1d#\x04\x180\x16\x80\x14\xc6\xa4,\xe5\xe3\x15j\x18\x15@Xw!\xdd\xbf\xc6\xe5\xf0vG0\x0f\x06\x03U\x1d\x13\x01\x01\xff\x04\x050\x03\x01\x01\xff0\r\x06\t*\x86H\x86\xf7\r\x01\x01\x0b\x05\x00\x03\x82\x01\x01\x00\xacx\xeb\x02\x8a\xd3\x966\xb73\xfb\n\x1eb\ng\xda\x84\x18\x97P\xb4\x7f\x8a\xbd\x82\xf3\x1b\xe8k%\xcc\x0f\xbd\x7fB\xb9\x1df|-k\x01\xf3\x89\x08r\xb9\x93\xf5?Z\x16\xff\x0f\x97\x91b#\xef$I\x11\x9e\x16\xb2J\x97\xd1\x0e\xd6\xabD\xca@\xe7\xb3\xbe\x84S\x1e\xdb;\x9b\xc4\xf4\x18\xf4\x9a\x1b\xcej\xe0qmx\xe4N?K\n.p\xa8\xa6\xfa\xb0\xf7y\xe8\x0f\xbd\x0c216\xb0\xa1d\x1f\x7f3\xa1l?\xbe\x9a\x06\xed]\x1a\x00\xab\xb4e\x13:\x17\x1b\x88\x8e\xcaqp\"\x8f\xa6\xf7\x06J?`\xe0\xf7\xce\xf8K\x08\x15\x18\xa1\xc4\xb5\xd9hB\xb0\xc6\\\xae?\xa9\x83FL\x8cm\xd1\xad^\xf0\xa5:\x8e\x97\x07\xd2\xd0l\x0e\x9d\x01\xa00c)\xae\xd0@\xefr\xe7,\xb7[\xd3H\xfe1\xfb\xa9|\xd0\xac\xc6i\x98\xe5\xd5\xd1\xf2\x97<\xf9\xe1?=\x93\xfaM\x86\xa2\x9dy\xdeZj\x93&\xa6\x84d\x07a\xbf\xd6\xdde\xaa)\t\xd6\x0e\x99\x85K" # noqa: WPS342, E501
16+
17+
18+
def mock_cert(_: Any) -> Any:
19+
return test_cert_bytes
20+
21+
22+
cert_dict = {
23+
'subject': (
24+
(('countryName', 'as'),),
25+
(('stateOrProvinceName', 'as'),),
26+
(('localityName', 'as'),),
27+
(('organizationName', 'as'),),
28+
(('organizationalUnitName', 'as'),),
29+
(('commonName', 'as'),),
30+
(('emailAddress', 'as'),),
31+
),
32+
'issuer': (
33+
(('countryName', 'as'),),
34+
(('stateOrProvinceName', 'as'),),
35+
(('localityName', 'as'),),
36+
(('organizationName', 'as'),),
37+
(('organizationalUnitName', 'as'),),
38+
(('commonName', 'as'),),
39+
(('emailAddress', 'as'),),
40+
),
41+
'version': 3,
42+
'serialNumber': '5045018CA6EAD823CF90B044C704DE9B3959F320',
43+
'notBefore': 'Apr 29 12:50:57 2024 GMT',
44+
'notAfter': 'Apr 29 12:50:57 2025 GMT',
45+
}

tests/http/proxy/test_http_proxy_tls_interception.py

+4-2
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
from proxy.core.connection import TcpServerConnection
3131
from proxy.common.constants import DEFAULT_CA_FILE
3232
from ...test_assertions import Assertions
33+
from ...certificates.test_cert_data import mock_cert
3334

3435

3536
class TestHttpProxyTlsInterception(Assertions):
@@ -59,6 +60,7 @@ async def test_e2e(self, mocker: MockerFixture) -> None:
5960
# Used for server side wrapping
6061
self.mock_ssl_context = mocker.patch('ssl.create_default_context')
6162
upstream_tls_sock = mock.MagicMock(spec=ssl.SSLSocket)
63+
upstream_tls_sock.getpeercert = mock_cert
6264
self.mock_ssl_context.return_value.wrap_socket.return_value = upstream_tls_sock
6365

6466
# Used for client wrapping
@@ -75,8 +77,8 @@ def mock_connection() -> Any:
7577

7678
# Do not mock the original wrap method
7779
self.mock_server_conn.return_value.wrap.side_effect = \
78-
lambda x, y, as_non_blocking: TcpServerConnection.wrap(
79-
self.mock_server_conn.return_value, x, y, as_non_blocking=as_non_blocking,
80+
lambda x, y, as_non_blocking, verify_mode: TcpServerConnection.wrap(
81+
self.mock_server_conn.return_value, x, y, as_non_blocking=as_non_blocking, verify_mode=verify_mode,
8082
)
8183

8284
type(self.mock_server_conn.return_value).connection = \

tests/plugin/test_http_proxy_plugins_with_tls_interception.py

+4-3
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
from proxy.core.connection import TcpServerConnection
3030
from .utils import get_plugin_by_test_name
3131
from ..test_assertions import Assertions
32+
from ..certificates.test_cert_data import mock_cert
3233

3334

3435
class TestHttpProxyPluginExamplesWithTlsInterception(Assertions):
@@ -78,8 +79,8 @@ def _setUp(self, request: Any, mocker: MockerFixture) -> None:
7879
self.protocol_handler.initialize()
7980

8081
self.server = self.mock_server_conn.return_value
81-
8282
self.server_ssl_connection = mocker.MagicMock(spec=ssl.SSLSocket)
83+
self.server_ssl_connection.getpeercert = mock_cert
8384
self.mock_ssl_context.return_value.wrap_socket.return_value = self.server_ssl_connection
8485
self.client_ssl_connection = mocker.MagicMock(spec=ssl.SSLSocket)
8586
self.mock_ssl_wrap.return_value.wrap_socket.return_value = self.client_ssl_connection
@@ -97,8 +98,8 @@ def mock_connection() -> Any:
9798

9899
# Do not mock the original wrap method
99100
self.server.wrap.side_effect = \
100-
lambda x, y, as_non_blocking: TcpServerConnection.wrap(
101-
self.server, x, y, as_non_blocking=as_non_blocking,
101+
lambda x, y, as_non_blocking, verify_mode: TcpServerConnection.wrap(
102+
self.server, x, y, as_non_blocking=as_non_blocking, verify_mode=verify_mode,
102103
)
103104

104105
self.server.has_buffer.side_effect = has_buffer

0 commit comments

Comments
 (0)