Skip to content

Fix broken TLS interception & CacheResponsesPlugin because UID is no longer a UUID #866

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 24 commits into from
Dec 17, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
ddcd0ac
Fix broken TLS interception because uid is now no longer a UUID
abhinavsingh Dec 13, 2021
8bfa07e
Merge branch 'develop' into fix-tls-interception
abhinavsingh Dec 13, 2021
c89d5d4
Give enough context to work id for them to be unique within a `proxy.…
abhinavsingh Dec 13, 2021
9bebef9
Merge branch 'fix-tls-interception' of github.com:abhinavsingh/proxy.…
abhinavsingh Dec 13, 2021
c7fcc0c
Use --port=0 by default within `proxy.TestCase`
abhinavsingh Dec 13, 2021
4fe8917
Attempt to fix weird buildx issue
abhinavsingh Dec 13, 2021
d82be1c
Add makefile targets within workflow
abhinavsingh Dec 13, 2021
0b299f7
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Dec 13, 2021
e22c7ab
Order?
abhinavsingh Dec 13, 2021
079ad81
Merge branch 'fix-tls-interception' of github.com:abhinavsingh/proxy.…
abhinavsingh Dec 13, 2021
0f7259b
Write scm file for make
abhinavsingh Dec 13, 2021
c341594
Fetch depth
abhinavsingh Dec 13, 2021
d33127a
Quote patch
abhinavsingh Dec 14, 2021
0c43445
Try with sudo?
abhinavsingh Dec 14, 2021
39a7e19
https://github.com/docker/buildx/issues/850
abhinavsingh Dec 14, 2021
c6b3a40
Remove sudo hack
abhinavsingh Dec 14, 2021
eedb216
https://github.com/docker/buildx/issues/850\#issuecomment-973270625
abhinavsingh Dec 14, 2021
87c77a3
Add explicit deps
abhinavsingh Dec 17, 2021
f089038
Add `requirements-testing.txt` during linting phase
abhinavsingh Dec 17, 2021
99c37a5
Pin buildx to v0.7.1
abhinavsingh Dec 17, 2021
71f2657
Pin buildx to v0.7.0
abhinavsingh Dec 17, 2021
e2d1de0
Revert back unnecessary change to dockerignore
abhinavsingh Dec 17, 2021
0288c78
Skip container within make workflow (because GHA lacks support for do…
abhinavsingh Dec 17, 2021
46dab11
Repurpose make into developer workflow
abhinavsingh Dec 17, 2021
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 36 additions & 5 deletions .github/workflows/test-library.yml
Original file line number Diff line number Diff line change
Expand Up @@ -631,6 +631,34 @@ jobs:
npm run build
cd ..

developer:
runs-on: ${{ matrix.os }}-latest
name: Developer setup ${{ matrix.node }} @ ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu, macOS]
python: ['3.10']
fail-fast: false
steps:
- uses: actions/checkout@v2
with:
fetch-depth: 0
- name: Setup Python
uses: actions/setup-python@v2
with:
python-version: ${{ matrix.python }}
- name: Install Pip Dependencies
run: |
make lib-dep
- name: Run essentials
run: |
./write-scm-version.sh
python3 check.py
make https-certificates
make sign-https-certificates
make ca-certificates
python3 -m proxy --version

docker:
# TODO: To build our docker container, we must wait for check,
# so that we can use the same distribution available.
Expand Down Expand Up @@ -658,18 +686,20 @@ jobs:
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Download all the dists
uses: actions/download-artifact@v2
with:
name: python-package-distributions
path: dist/
- name: Set up Docker Buildx
id: buildx
uses: docker/setup-buildx-action@v1
with:
# FIXME: See https://github.com/docker/buildx/issues/850#issuecomment-996408167
version: v0.7.0
buildkitd-flags: --debug
config: .github/buildkitd.toml
install: true
- name: Download all the dists
uses: actions/download-artifact@v2
with:
name: python-package-distributions
path: dist/
- name: Enable Multiarch # This slows down arm build by 4-5x
run: |
docker run --rm --privileged multiarch/qemu-user-static --reset -p yes
Expand Down Expand Up @@ -699,6 +729,7 @@ jobs:
- docker
- dashboard
- brew
- developer

runs-on: Ubuntu-latest

Expand Down
14 changes: 7 additions & 7 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -126,11 +126,11 @@ lib-release: lib-package

lib-doc:
python -m tox -e build-docs && \
$(OPEN) .tox/build-docs/docs_out/index.html
$(OPEN) .tox/build-docs/docs_out/index.html || true

lib-coverage:
pytest --cov=proxy --cov=tests --cov-report=html tests/ && \
$(OPEN) htmlcov/index.html
$(OPEN) htmlcov/index.html || true

lib-profile:
ulimit -n 65536 && \
Expand Down Expand Up @@ -177,6 +177,11 @@ dashboard-clean:
container: lib-package
$(MAKE) container-build -e PROXYPY_PKG_PATH=$$(ls dist/*.whl)

container-build:
docker build \
-t $(PROXYPY_CONTAINER_TAG) \
--build-arg PROXYPY_PKG_PATH=$(PROXYPY_PKG_PATH) .

# Usage:
#
# make container-buildx \
Expand All @@ -189,10 +194,5 @@ container-buildx:
-t $(PROXYPY_CONTAINER_TAG) \
--build-arg PROXYPY_PKG_PATH=$(PROXYPY_PKG_PATH) .

container-build:
docker build \
-t $(PROXYPY_CONTAINER_TAG) \
--build-arg PROXYPY_PKG_PATH=$(PROXYPY_PKG_PATH) .

container-run:
docker run -it -p 8899:8899 --rm $(PROXYPY_CONTAINER_TAG)
8 changes: 4 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -1322,10 +1322,10 @@ import proxy

if __name__ == '__main__':
with proxy.Proxy([]) as p:
print(p.acceptors.flags.port)
print(p.flags.port)
```

`acceptors.flags.port` will give you access to the random port allocated by the kernel.
`flags.port` will give you access to the random port allocated by the kernel.

## Loading Plugins

Expand Down Expand Up @@ -1384,7 +1384,7 @@ Note that:

1. `proxy.TestCase` overrides `unittest.TestCase.run()` method to setup and tear down `proxy.py`.
2. `proxy.py` server will listen on a random available port on the system.
This random port is available as `self.PROXY.acceptors.flags.port` within your test cases.
This random port is available as `self.PROXY.flags.port` within your test cases.
3. Only a single acceptor and worker is started by default (`--num-workers 1 --num-acceptors 1`) for faster setup and tear down.
4. Most importantly, `proxy.TestCase` also ensures `proxy.py` server
is up and running before proceeding with execution of tests. By default,
Expand Down Expand Up @@ -2073,7 +2073,7 @@ usage: -m [-h] [--enable-events] [--enable-conn-pool] [--threadless]
[--filtered-url-regex-config FILTERED_URL_REGEX_CONFIG]
[--cloudflare-dns-mode CLOUDFLARE_DNS_MODE]

proxy.py v2.3.2.dev190+ge60d80d.d20211124
proxy.py v2.4.0rc2.dev21+g20b3eb1.d20211203

options:
-h, --help show this help message and exit
Expand Down
7 changes: 4 additions & 3 deletions check.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,11 +60,12 @@
with open('README.md', 'rb+') as f:
c = f.read()
pre_flags, post_flags = c.split(b'# Flags')
help_text, post_changelog = post_flags.split(b'# Changelog')
f.seek(0)
f.write(
pre_flags + b'# Flags\n\n```console\n\xe2\x9d\xaf proxy -h\n' + lib_help + b'```' +
b'\n\n# Changelog' + post_changelog,
pre_flags +
b'# Flags\n\n```console\n\xe2\x9d\xaf proxy -h\n' +
lib_help +
b'```\n',
)

# Version is also hardcoded in README.md flags section
Expand Down
1 change: 1 addition & 0 deletions proxy/core/acceptor/acceptor.py
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,7 @@ def _start_local(self) -> None:
assert self.sock
self._local_work_queue = NonBlockingQueue()
self._local = LocalExecutor(
iid=self.idd,
work_queue=self._local_work_queue,
flags=self.flags,
event_queue=self.event_queue,
Expand Down
1 change: 1 addition & 0 deletions proxy/core/acceptor/executors.py
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,7 @@ def _start_worker(self, index: int) -> None:
pipe = multiprocessing.Pipe()
self.work_queues.append(pipe[0])
w = RemoteExecutor(
iid=index,
work_queue=pipe[1],
flags=self.flags,
event_queue=self.event_queue,
Expand Down
7 changes: 6 additions & 1 deletion proxy/core/acceptor/threadless.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,11 +59,13 @@ class Threadless(ABC, Generic[T]):

def __init__(
self,
iid: str,
work_queue: T,
flags: argparse.Namespace,
event_queue: Optional[EventQueue] = None,
) -> None:
super().__init__()
self.iid = iid
self.work_queue = work_queue
self.flags = flags
self.event_queue = event_queue
Expand All @@ -84,6 +86,7 @@ def __init__(
] = {}
self.wait_timeout: float = DEFAULT_WAIT_FOR_TASKS_TIMEOUT
self.cleanup_inactive_timeout: float = DEFAULT_INACTIVE_CONN_CLEANUP_TIMEOUT
self._total: int = 0

@property
@abstractmethod
Expand Down Expand Up @@ -122,14 +125,15 @@ def work_on_tcp_conn(
fileno, family=socket.AF_INET if self.flags.hostname.version == 4 else socket.AF_INET6,
type=socket.SOCK_STREAM,
)
uid = '%s-%s-%s' % (self.iid, self._total, fileno)
self.works[fileno] = self.flags.work_klass(
TcpClientConnection(
conn=conn,
addr=addr,
),
flags=self.flags,
event_queue=self.event_queue,
uid=fileno,
uid=uid,
)
self.works[fileno].publish_event(
event_name=eventNames.WORK_STARTED,
Expand All @@ -138,6 +142,7 @@ def work_on_tcp_conn(
)
try:
self.works[fileno].initialize()
self._total += 1
except Exception as e:
logger.exception(
'Exception occurred during initialization',
Expand Down
8 changes: 4 additions & 4 deletions proxy/core/acceptor/work.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
import argparse

from abc import ABC, abstractmethod
from uuid import uuid4, UUID
from uuid import uuid4
from typing import Optional, Dict, Any

from ..event import eventNames, EventQueue
Expand All @@ -31,10 +31,10 @@ def __init__(
work: TcpClientConnection,
flags: argparse.Namespace,
event_queue: Optional[EventQueue] = None,
uid: Optional[UUID] = None,
uid: Optional[str] = None,
) -> None:
# Work uuid
self.uid: UUID = uid if uid is not None else uuid4()
self.uid: str = uid if uid is not None else uuid4().hex
self.flags = flags
# Eventing core queue
self.event_queue = event_queue
Expand Down Expand Up @@ -92,7 +92,7 @@ def publish_event(
return
assert self.event_queue
self.event_queue.publish(
self.uid.hex,
self.uid,
event_name,
event_payload,
publisher_id,
Expand Down
5 changes: 2 additions & 3 deletions proxy/http/plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
import socket
import argparse

from uuid import UUID
from abc import ABC, abstractmethod
from typing import Tuple, List, Union, Optional

Expand Down Expand Up @@ -46,13 +45,13 @@ class HttpProtocolHandlerPlugin(ABC):

def __init__(
self,
uid: UUID,
uid: str,
flags: argparse.Namespace,
client: TcpClientConnection,
request: HttpParser,
event_queue: EventQueue,
):
self.uid: UUID = uid
self.uid: str = uid
self.flags: argparse.Namespace = flags
self.client: TcpClientConnection = client
self.request: HttpParser = request
Expand Down
3 changes: 1 addition & 2 deletions proxy/http/proxy/plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
import argparse

from abc import ABC
from uuid import UUID
from typing import Any, Dict, List, Optional, Tuple

from ..parser import HttpParser
Expand All @@ -28,7 +27,7 @@ class HttpProxyBasePlugin(ABC):

def __init__(
self,
uid: UUID,
uid: str,
flags: argparse.Namespace,
client: TcpClientConnection,
event_queue: EventQueue,
Expand Down
17 changes: 7 additions & 10 deletions proxy/http/proxy/server.py
Original file line number Diff line number Diff line change
Expand Up @@ -307,11 +307,8 @@ async def read_from_descriptors(self, r: Readables) -> bool:
# parse incoming response packet
# only for non-https requests and when
# tls interception is enabled
if not self.request.is_https_tunnel:
# See https://github.com/abhinavsingh/proxy.py/issues/127 for why
# currently response parsing is disabled when TLS interception is enabled.
#
# or self.tls_interception_enabled():
if not self.request.is_https_tunnel \
or self.tls_interception_enabled():
if self.response.is_complete:
self.handle_pipeline_response(raw)
else:
Expand Down Expand Up @@ -733,7 +730,7 @@ def gen_ca_signed_certificate(
ca_key_path = self.flags.ca_key_file
ca_key_password = ''
ca_crt_path = self.flags.ca_cert_file
serial = self.uid.int
serial = self.uid

# Sign generated CSR
if not os.path.isfile(cert_file_path):
Expand Down Expand Up @@ -903,7 +900,7 @@ def emit_request_complete(self) -> None:
return
assert self.request.port
self.event_queue.publish(
request_id=self.uid.hex,
request_id=self.uid,
event_name=eventNames.REQUEST_COMPLETE,
event_payload={
'url': text_(self.request.path)
Expand Down Expand Up @@ -937,7 +934,7 @@ def emit_response_headers_complete(self) -> None:
if not self.flags.enable_events:
return
self.event_queue.publish(
request_id=self.uid.hex,
request_id=self.uid,
event_name=eventNames.RESPONSE_HEADERS_COMPLETE,
event_payload={
'headers': {}
Expand All @@ -954,7 +951,7 @@ def emit_response_chunk_received(self, chunk_size: int) -> None:
if not self.flags.enable_events:
return
self.event_queue.publish(
request_id=self.uid.hex,
request_id=self.uid,
event_name=eventNames.RESPONSE_CHUNK_RECEIVED,
event_payload={
'chunk_size': chunk_size,
Expand All @@ -967,7 +964,7 @@ def emit_response_complete(self) -> None:
if not self.flags.enable_events:
return
self.event_queue.publish(
request_id=self.uid.hex,
request_id=self.uid,
event_name=eventNames.RESPONSE_COMPLETE,
event_payload={
'encoded_response_size': self.response.total_size,
Expand Down
3 changes: 1 addition & 2 deletions proxy/http/server/plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
"""
import argparse

from uuid import UUID
from abc import ABC, abstractmethod
from typing import Any, Dict, List, Optional, Tuple

Expand All @@ -27,7 +26,7 @@ class HttpWebServerBasePlugin(ABC):

def __init__(
self,
uid: UUID,
uid: str,
flags: argparse.Namespace,
client: TcpClientConnection,
event_queue: EventQueue,
Expand Down
4 changes: 2 additions & 2 deletions proxy/plugin/cache/store/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,13 @@
"""
from abc import ABC, abstractmethod
from typing import Optional
from uuid import UUID

from ....http.parser import HttpParser


class CacheStore(ABC):

def __init__(self, uid: UUID) -> None:
def __init__(self, uid: str) -> None:
self.uid = uid

@abstractmethod
Expand Down
Loading