Add more context in intro (#713)
* Add more context in intro * Take another pass * Add threadless in log section
This commit is contained in:
parent
fa18129f9b
commit
fec9a14303
276
README.md
276
README.md
|
@ -27,6 +27,7 @@
|
|||
|
||||
- [Features](#features)
|
||||
- [Install](#install)
|
||||
- [Stable vs Develop](#stable-vs-develop)
|
||||
- [Using PIP](#using-pip)
|
||||
- [Stable version](#stable-version-with-pip)
|
||||
- [Development version](#development-version-with-pip)
|
||||
|
@ -119,7 +120,7 @@
|
|||
- Fast & Scalable
|
||||
|
||||
- Scales by using all available cores on the system
|
||||
- Threadless executions using coroutine
|
||||
- Threadless executions using asyncio
|
||||
- Made to handle `tens-of-thousands` connections / sec
|
||||
|
||||
```console
|
||||
|
@ -146,36 +147,56 @@
|
|||
- Uses only `~5-20MB` RAM
|
||||
- No external dependency other than standard Python library
|
||||
- Programmable
|
||||
- Optionally enable builtin Web Server
|
||||
- Customize proxy and http routing via [plugins](https://github.com/abhinavsingh/proxy.py/tree/develop/proxy/plugin)
|
||||
- Enable plugin using command line option e.g. `--plugins proxy.plugin.CacheResponsesPlugin`
|
||||
- Plugin API is currently in development phase, expect breaking changes.
|
||||
- Customize proxy behavior using [Proxy Server Plugins](#http-proxy-plugins). Example:
|
||||
- `--plugins proxy.plugin.ProxyPoolPlugin`
|
||||
- Optionally, enable builtin [Web Server Plugins](#http-web-server-plugins). Example:
|
||||
- `--plugins proxy.plugin.ReverseProxyPlugin`
|
||||
- Plugin API is currently in development phase, expect breaking changes
|
||||
- Realtime Dashboard
|
||||
- Optionally enable bundled dashboard.
|
||||
- Optionally, enable [proxy.py dashboard](#run-dashboard).
|
||||
- Available at `http://localhost:8899/dashboard`.
|
||||
- Inspect, Monitor, Control and Configure `proxy.py` at runtime.
|
||||
- Extend dashboard using plugins.
|
||||
- Dashboard is currently in development phase, expect breaking changes.
|
||||
- [Inspect, Monitor, Control and Configure](#inspect-traffic) `proxy.py` at runtime
|
||||
- [Chrome DevTools Protocol](#chrome-devtools-protocol) support
|
||||
- Extend dashboard using plugins
|
||||
- Dashboard is currently in development phase, expect breaking changes
|
||||
- Secure
|
||||
- Enable end-to-end encryption between clients and `proxy.py` using TLS
|
||||
- Enable end-to-end encryption between clients and `proxy.py`
|
||||
- See [End-to-End Encryption](#end-to-end-encryption)
|
||||
- Private
|
||||
- Everyone deserves privacy. Browse with malware and adult content protection
|
||||
- See [DNS-over-HTTPS](#cloudflarednsresolverplugin)
|
||||
- Man-In-The-Middle
|
||||
- Can decrypt TLS traffic between clients and upstream servers
|
||||
- See [TLS Interception](#tls-interception)
|
||||
- Supported proxy protocols
|
||||
- `http(s)`
|
||||
- `http1`
|
||||
- `http1.1` pipeline
|
||||
- `http1.1` with pipeline
|
||||
- `http2`
|
||||
- `websockets`
|
||||
- Static file server support
|
||||
- See `--enable-static-server` and `--static-server-dir` flags
|
||||
- Optimized for large file uploads and downloads
|
||||
- IPv4 and IPv6 support
|
||||
- See `--client-recvbuf-size` and `--server-recvbuf-size` flag
|
||||
- `IPv4` and `IPv6` support
|
||||
- See `--hostname` flag
|
||||
- Unix domain socket support
|
||||
- See `--unix-socket-path` flag
|
||||
- Basic authentication support
|
||||
- Can serve a [PAC (Proxy Auto-configuration)](https://en.wikipedia.org/wiki/Proxy_auto-config) file
|
||||
- See `--basic-auth` flag
|
||||
- PAC (Proxy Auto-configuration) support
|
||||
- See `--pac-file` and `--pac-file-url-path` flags
|
||||
|
||||
# Install
|
||||
|
||||
## Stable vs Develop
|
||||
|
||||
`master` branch contains latest stable code and is available via `PyPi` repository
|
||||
|
||||
`develop` branch contains cutting edge changes
|
||||
|
||||
Development branch is kept stable *(most of the times)*. But if you want 100% reliability and serving users in production environment, always use stable version from `PyPi` or `Docker` container from `hub.docker.com`.
|
||||
|
||||
## Using PIP
|
||||
|
||||
### Stable Version with PIP
|
||||
|
@ -200,18 +221,17 @@ or from GitHub `master` branch
|
|||
|
||||
## Using Docker
|
||||
|
||||
#### Stable Version from Docker Hub
|
||||
### Stable Version from Docker Hub
|
||||
|
||||
```console
|
||||
❯ docker run -it -p 8899:8899 --rm abhinavsingh/proxy.py:latest
|
||||
```
|
||||
|
||||
#### Build Development Version Locally
|
||||
### Build Development Version Locally
|
||||
|
||||
```console
|
||||
❯ git clone https://github.com/abhinavsingh/proxy.py.git
|
||||
❯ cd proxy.py
|
||||
❯ make container
|
||||
❯ cd proxy.py && make container
|
||||
❯ docker run -it -p 8899:8899 --rm abhinavsingh/proxy.py:latest
|
||||
```
|
||||
|
||||
|
@ -239,38 +259,41 @@ or from GitHub `master` branch
|
|||
When `proxy.py` is installed using `pip`,
|
||||
an executable named `proxy` is placed under your `$PATH`.
|
||||
|
||||
#### Run it
|
||||
### Run it
|
||||
|
||||
Simply type `proxy` on command line to start it with default configuration.
|
||||
Simply type `proxy` on command line to start with default configuration.
|
||||
|
||||
```console
|
||||
❯ proxy
|
||||
...[redacted]... - Loaded plugin proxy.http_proxy.HttpProxyPlugin
|
||||
...[redacted]... - Starting 8 workers
|
||||
...[redacted]... - Starting 8 threadless workers
|
||||
...[redacted]... - Started server on ::1:8899
|
||||
```
|
||||
|
||||
#### Understanding logs
|
||||
### Understanding logs
|
||||
|
||||
Things to notice from above logs:
|
||||
|
||||
- `Loaded plugin` - `proxy.py` will load `proxy.http.proxy.HttpProxyPlugin` by default.
|
||||
As name suggests, this core plugin adds `http(s)` proxy server capabilities to `proxy.py`
|
||||
- `Loaded plugin`
|
||||
- `proxy.py` will load `proxy.http.proxy.HttpProxyPlugin` by default
|
||||
- As name suggests, this core plugin adds `http(s)` proxy server capabilities to `proxy.py` instance
|
||||
|
||||
- `Started N workers` - Use `--num-workers` flag to customize number of worker processes.
|
||||
By default, `proxy.py` will start as many workers as there are CPU cores on the machine.
|
||||
- `Started N threadless workers`
|
||||
- By default, `proxy.py` will start as many workers as there are CPU cores on the machine
|
||||
- Use `--num-workers` flag to customize number of worker processes
|
||||
- See [Threads vs Threadless](#threads-vs-threadless) to understand how to control execution mode
|
||||
|
||||
- `Started server on ::1:8899` - By default, `proxy.py` listens on IPv6 `::1`,
|
||||
which is equivalent of IPv4 `127.0.0.1`. If you want to access `proxy.py` externally,
|
||||
use `--hostname ::` or `--hostname 0.0.0.0` or bind to any other interface available
|
||||
on your machine. See [CustomNetworkInterface](#customnetworkinterface) for how to customize
|
||||
your system public IP as seen by the upstream servers.
|
||||
- `Started server on ::1:8899`
|
||||
- By default, `proxy.py` listens on IPv6 `::1`, which is equivalent of IPv4 `127.0.0.1`
|
||||
- If you want to access `proxy.py` from external host, use `--hostname ::` or `--hostname 0.0.0.0` or bind to any other interface available on your machine.
|
||||
- See [CustomNetworkInterface](#customnetworkinterface) for how to customize `proxy.py` *public IP seen by upstream servers*.
|
||||
|
||||
- `Port 8899` - Use `--port` flag to customize default TCP port.
|
||||
- `Port 8899`
|
||||
- Use `--port` flag to customize default TCP port.
|
||||
|
||||
#### Enable DEBUG logging
|
||||
### Enable DEBUG logging
|
||||
|
||||
All the logs above are `INFO` level logs, default `--log-level` for `proxy.py`.
|
||||
All the logs above are `INFO` level logs, default `--log-level` for `proxy.py`
|
||||
|
||||
Lets start `proxy.py` with `DEBUG` level logging:
|
||||
|
||||
|
@ -282,11 +305,18 @@ Lets start `proxy.py` with `DEBUG` level logging:
|
|||
...[redacted]... - Started server on ::1:8899
|
||||
```
|
||||
|
||||
As we can see, before starting up:
|
||||
You can use single letter to customize log level. Example:
|
||||
- `d = DEBUG`
|
||||
- `i = INFO`
|
||||
- `w = WARNING`
|
||||
- `e = ERROR`
|
||||
- `c = CRITICAL`
|
||||
|
||||
- `proxy.py` also tried to set open file limit `ulimit` on the system.
|
||||
- Default value for `--open-file-limit` used is `1024`.
|
||||
- `--open-file-limit` flag is a no-op on `Windows` operating systems.
|
||||
As we can see from the above logs, before starting up:
|
||||
|
||||
- `proxy.py` tried to set open file limit `ulimit` on the system
|
||||
- Default value for `--open-file-limit` used is `1024`
|
||||
- `--open-file-limit` flag is a no-op on `Windows` operating systems
|
||||
|
||||
See [flags](#flags) for full list of available configuration options.
|
||||
|
||||
|
@ -323,25 +353,24 @@ To start `proxy.py` from source code follow these instructions:
|
|||
❯ make
|
||||
```
|
||||
|
||||
- Run proxy.py
|
||||
- Run `proxy.py`
|
||||
|
||||
```console
|
||||
❯ python -m proxy
|
||||
```
|
||||
|
||||
Also see [Plugin Developer and Contributor Guide](#plugin-developer-and-contributor-guide)
|
||||
See [Plugin Developer and Contributor Guide](#plugin-developer-and-contributor-guide)
|
||||
if you plan to work with `proxy.py` source code.
|
||||
|
||||
## Docker image
|
||||
|
||||
#### Customize startup flags
|
||||
### Customize startup flags
|
||||
|
||||
By default `docker` binary is started with IPv4 networking flags:
|
||||
|
||||
--hostname 0.0.0.0 --port 8899
|
||||
|
||||
To override input flags, start docker image as follows.
|
||||
For example, to check `proxy.py` version within Docker image:
|
||||
You can override flag from command line when starting the docker container. For example, to check `proxy.py` version within the docker container, run:
|
||||
|
||||
❯ docker run -it \
|
||||
-p 8899:8899 \
|
||||
|
@ -1380,32 +1409,30 @@ As a decorator:
|
|||
|
||||
### build_http_request
|
||||
|
||||
#### Generate HTTP GET request
|
||||
- Generate HTTP GET request
|
||||
|
||||
```python
|
||||
>>> build_http_request(b'GET', b'/')
|
||||
b'GET / HTTP/1.1\r\n\r\n'
|
||||
>>>
|
||||
```
|
||||
```python
|
||||
>>> build_http_request(b'GET', b'/')
|
||||
b'GET / HTTP/1.1\r\n\r\n'
|
||||
```
|
||||
|
||||
#### Generate HTTP GET request with headers
|
||||
- Generate HTTP GET request with headers
|
||||
|
||||
```python
|
||||
>>> build_http_request(b'GET', b'/',
|
||||
headers={b'Connection': b'close'})
|
||||
b'GET / HTTP/1.1\r\nConnection: close\r\n\r\n'
|
||||
>>>
|
||||
```
|
||||
```python
|
||||
>>> build_http_request(b'GET', b'/',
|
||||
headers={b'Connection': b'close'})
|
||||
b'GET / HTTP/1.1\r\nConnection: close\r\n\r\n'
|
||||
```
|
||||
|
||||
#### Generate HTTP POST request with headers and body
|
||||
- Generate HTTP POST request with headers and body
|
||||
|
||||
```python
|
||||
>>> import json
|
||||
>>> build_http_request(b'POST', b'/form',
|
||||
headers={b'Content-type': b'application/json'},
|
||||
body=proxy.bytes_(json.dumps({'email': 'hello@world.com'})))
|
||||
b'POST /form HTTP/1.1\r\nContent-type: application/json\r\n\r\n{"email": "hello@world.com"}'
|
||||
```
|
||||
```python
|
||||
>>> import json
|
||||
>>> build_http_request(b'POST', b'/form',
|
||||
headers={b'Content-type': b'application/json'},
|
||||
body=proxy.bytes_(json.dumps({'email': 'hello@world.com'})))
|
||||
b'POST /form HTTP/1.1\r\nContent-type: application/json\r\n\r\n{"email": "hello@world.com"}'
|
||||
```
|
||||
|
||||
### build_http_response
|
||||
|
||||
|
@ -1422,66 +1449,66 @@ build_http_response(
|
|||
|
||||
### API Usage
|
||||
|
||||
#### gen_private_key
|
||||
- gen_private_key
|
||||
|
||||
```python
|
||||
gen_private_key(
|
||||
key_path: str,
|
||||
password: str,
|
||||
bits: int = 2048,
|
||||
timeout: int = 10) -> bool
|
||||
```
|
||||
```python
|
||||
gen_private_key(
|
||||
key_path: str,
|
||||
password: str,
|
||||
bits: int = 2048,
|
||||
timeout: int = 10) -> bool
|
||||
```
|
||||
|
||||
#### gen_public_key
|
||||
- gen_public_key
|
||||
|
||||
```python
|
||||
gen_public_key(
|
||||
public_key_path: str,
|
||||
private_key_path: str,
|
||||
private_key_password: str,
|
||||
subject: str,
|
||||
alt_subj_names: Optional[List[str]] = None,
|
||||
extended_key_usage: Optional[str] = None,
|
||||
validity_in_days: int = 365,
|
||||
timeout: int = 10) -> bool
|
||||
```
|
||||
```python
|
||||
gen_public_key(
|
||||
public_key_path: str,
|
||||
private_key_path: str,
|
||||
private_key_password: str,
|
||||
subject: str,
|
||||
alt_subj_names: Optional[List[str]] = None,
|
||||
extended_key_usage: Optional[str] = None,
|
||||
validity_in_days: int = 365,
|
||||
timeout: int = 10) -> bool
|
||||
```
|
||||
|
||||
#### remove_passphrase
|
||||
- remove_passphrase
|
||||
|
||||
```python
|
||||
remove_passphrase(
|
||||
key_in_path: str,
|
||||
password: str,
|
||||
key_out_path: str,
|
||||
timeout: int = 10) -> bool
|
||||
```
|
||||
```python
|
||||
remove_passphrase(
|
||||
key_in_path: str,
|
||||
password: str,
|
||||
key_out_path: str,
|
||||
timeout: int = 10) -> bool
|
||||
```
|
||||
|
||||
#### gen_csr
|
||||
- gen_csr
|
||||
|
||||
```python
|
||||
gen_csr(
|
||||
csr_path: str,
|
||||
key_path: str,
|
||||
password: str,
|
||||
crt_path: str,
|
||||
timeout: int = 10) -> bool
|
||||
```
|
||||
```python
|
||||
gen_csr(
|
||||
csr_path: str,
|
||||
key_path: str,
|
||||
password: str,
|
||||
crt_path: str,
|
||||
timeout: int = 10) -> bool
|
||||
```
|
||||
|
||||
#### sign_csr
|
||||
- sign_csr
|
||||
|
||||
```python
|
||||
sign_csr(
|
||||
csr_path: str,
|
||||
crt_path: str,
|
||||
ca_key_path: str,
|
||||
ca_key_password: str,
|
||||
ca_crt_path: str,
|
||||
serial: str,
|
||||
alt_subj_names: Optional[List[str]] = None,
|
||||
extended_key_usage: Optional[str] = None,
|
||||
validity_in_days: int = 365,
|
||||
timeout: int = 10) -> bool
|
||||
```
|
||||
```python
|
||||
sign_csr(
|
||||
csr_path: str,
|
||||
crt_path: str,
|
||||
ca_key_path: str,
|
||||
ca_key_password: str,
|
||||
ca_crt_path: str,
|
||||
serial: str,
|
||||
alt_subj_names: Optional[List[str]] = None,
|
||||
extended_key_usage: Optional[str] = None,
|
||||
validity_in_days: int = 365,
|
||||
timeout: int = 10) -> bool
|
||||
```
|
||||
|
||||
See [pki.py](https://github.com/abhinavsingh/proxy.py/blob/develop/proxy/common/pki.py) and
|
||||
[test_pki.py](https://github.com/abhinavsingh/proxy.py/blob/develop/tests/common/test_pki.py)
|
||||
|
@ -1520,8 +1547,7 @@ optional arguments:
|
|||
|
||||
## Internal Documentation
|
||||
|
||||
Browse through internal class hierarchy and documentation using `pydoc3`.
|
||||
Example:
|
||||
Code is well documented. Browse through internal class hierarchy and documentation using `pydoc3`
|
||||
|
||||
```console
|
||||
❯ pydoc3 proxy
|
||||
|
@ -1539,8 +1565,6 @@ FILE
|
|||
|
||||
# Run Dashboard
|
||||
|
||||
**This is a WIP and may not work as documented**
|
||||
|
||||
Dashboard is currently under development and not yet bundled with `pip` packages.
|
||||
To run dashboard, you must checkout the source.
|
||||
|
||||
|
@ -1579,6 +1603,8 @@ Visit dashboard:
|
|||
|
||||
## Inspect Traffic
|
||||
|
||||
***This is a WIP and may not work as documented***
|
||||
|
||||
Wait for embedded `Chrome Dev Console` to load. Currently, detail about all traffic flowing
|
||||
through `proxy.py` is pushed to the `Inspect Traffic` tab. However, received payloads are not
|
||||
yet integrated with the embedded dev console.
|
||||
|
@ -1603,19 +1629,23 @@ Now point your CDT instance to `ws://localhost:8899/devtools`.
|
|||
|
||||
## Threads vs Threadless
|
||||
|
||||
### Pre v2.x
|
||||
### `v1.x`
|
||||
|
||||
`proxy.py` used to spawn new threads for handling client requests.
|
||||
|
||||
### Starting v2.0
|
||||
### `v2.0+`
|
||||
|
||||
`proxy.py` added support for threadless execution of client requests using `asyncio`.
|
||||
|
||||
### Starting v2.4.0
|
||||
### `v2.4.0+`
|
||||
|
||||
Threadless execution was turned ON by default for `Python 3.8+` on `mac` and `linux` environments. `proxy.py` threadless execution has been reported safe on these environments by our users. If you are running into trouble, fallback to threaded mode using `--threaded` flag.
|
||||
Threadless execution was turned ON by default for `Python 3.8+` on `mac` and `linux` environments.
|
||||
|
||||
For `windows` and `Python < 3.8`, you can still try out threadless mode by starting `proxy.py` with `--threadless` flag. If threadless works for you, consider sending a PR by editing `_env_threadless_compliant` method in the `proxy/common/constants.py` file.
|
||||
`proxy.py` threadless execution has been reported safe on these environments by our users. If you are running into trouble, fallback to threaded mode using `--threaded` flag.
|
||||
|
||||
For `windows` and `Python < 3.8`, you can still try out threadless mode by starting `proxy.py` with `--threadless` flag.
|
||||
|
||||
If threadless works for you, consider sending a PR by editing `_env_threadless_compliant` method in the `proxy/common/constants.py` file.
|
||||
|
||||
## SyntaxError: invalid syntax
|
||||
|
||||
|
|
Loading…
Reference in New Issue