Skip to content

Add --auth-plugin flag to override default basic auth plugin #734

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 6 commits into from
Nov 13, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
188 changes: 87 additions & 101 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -1945,23 +1945,20 @@ for list of tests.

```console
❯ proxy -h
usage: proxy [-h] [--enable-events] [--enable-conn-pool] [--threadless] [--threaded]
[--num-workers NUM_WORKERS] [--backlog BACKLOG] [--hostname HOSTNAME]
[--port PORT] [--unix-socket-path UNIX_SOCKET_PATH]
[--num-acceptors NUM_ACCEPTORS] [--version] [--log-level LOG_LEVEL]
[--log-file LOG_FILE] [--log-format LOG_FORMAT]
usage: -m [-h] [--enable-events] [--enable-conn-pool] [--threadless] [--threaded]
[--num-workers NUM_WORKERS] [--backlog BACKLOG] [--hostname HOSTNAME] [--port PORT]
[--unix-socket-path UNIX_SOCKET_PATH] [--num-acceptors NUM_ACCEPTORS] [--version]
[--log-level LOG_LEVEL] [--log-file LOG_FILE] [--log-format LOG_FORMAT]
[--open-file-limit OPEN_FILE_LIMIT] [--plugins PLUGINS [PLUGINS ...]]
[--enable-dashboard] [--work-klass WORK_KLASS] [--pid-file PID_FILE]
[--client-recvbuf-size CLIENT_RECVBUF_SIZE] [--key-file KEY_FILE]
[--timeout TIMEOUT] [--disable-http-proxy] [--ca-key-file CA_KEY_FILE]
[--ca-cert-dir CA_CERT_DIR] [--ca-cert-file CA_CERT_FILE]
[--ca-file CA_FILE] [--ca-signing-key-file CA_SIGNING_KEY_FILE]
[--cert-file CERT_FILE] [--disable-headers DISABLE_HEADERS]
[--server-recvbuf-size SERVER_RECVBUF_SIZE] [--basic-auth BASIC_AUTH]
[--cache-dir CACHE_DIR]
[--filtered-upstream-hosts FILTERED_UPSTREAM_HOSTS]
[--enable-web-server] [--enable-static-server]
[--static-server-dir STATIC_SERVER_DIR]
[--client-recvbuf-size CLIENT_RECVBUF_SIZE] [--key-file KEY_FILE] [--timeout TIMEOUT]
[--server-recvbuf-size SERVER_RECVBUF_SIZE] [--disable-http-proxy]
[--disable-headers DISABLE_HEADERS] [--ca-key-file CA_KEY_FILE]
[--ca-cert-dir CA_CERT_DIR] [--ca-cert-file CA_CERT_FILE] [--ca-file CA_FILE]
[--ca-signing-key-file CA_SIGNING_KEY_FILE] [--cert-file CERT_FILE]
[--auth-plugin AUTH_PLUGIN] [--basic-auth BASIC_AUTH] [--cache-dir CACHE_DIR]
[--filtered-upstream-hosts FILTERED_UPSTREAM_HOSTS] [--enable-web-server]
[--enable-static-server] [--static-server-dir STATIC_SERVER_DIR]
[--min-compression-length MIN_COMPRESSION_LENGTH] [--pac-file PAC_FILE]
[--pac-file-url-path PAC_FILE_URL_PATH] [--proxy-pool PROXY_POOL]
[--filtered-client-ips FILTERED_CLIENT_IPS]
Expand All @@ -1972,131 +1969,120 @@ proxy.py v2.4.0

options:
-h, --help show this help message and exit
--enable-events Default: False. Enables core to dispatch lifecycle
events. Plugins can be used to subscribe for core events.
--enable-events Default: False. Enables core to dispatch lifecycle events. Plugins can
be used to subscribe for core events.
--enable-conn-pool Default: False. (WIP) Enable upstream connection pooling.
--threadless Default: True. Enabled by default on Python 3.8+ (mac,
linux). When disabled a new thread is spawned to handle
each client connection.
--threaded Default: False. Disabled by default on Python < 3.8 and
windows. When enabled a new thread is spawned to handle
each client connection.
--threadless Default: True. Enabled by default on Python 3.8+ (mac, linux). When
disabled a new thread is spawned to handle each client connection.
--threaded Default: False. Disabled by default on Python < 3.8 and windows. When
enabled a new thread is spawned to handle each client connection.
--num-workers NUM_WORKERS
Defaults to number of CPU cores.
--backlog BACKLOG Default: 100. Maximum number of pending connections to
proxy server
--backlog BACKLOG Default: 100. Maximum number of pending connections to proxy server
--hostname HOSTNAME Default: ::1. Server IP address.
--port PORT Default: 8899. Server port.
--unix-socket-path UNIX_SOCKET_PATH
Default: None. Unix socket path to use. When provided
--host and --port flags are ignored
Default: None. Unix socket path to use. When provided --host and --port
flags are ignored
--num-acceptors NUM_ACCEPTORS
Defaults to number of CPU cores.
--version, -v Prints proxy.py version.
--log-level LOG_LEVEL
Valid options: DEBUG, INFO (default), WARNING, ERROR,
CRITICAL. Both upper and lowercase values are allowed.
You may also simply use the leading character e.g. --log-
level d
Valid options: DEBUG, INFO (default), WARNING, ERROR, CRITICAL. Both
upper and lowercase values are allowed. You may also simply use the
leading character e.g. --log-level d
--log-file LOG_FILE Default: sys.stdout. Log file destination.
--log-format LOG_FORMAT
Log format for Python logger.
--open-file-limit OPEN_FILE_LIMIT
Default: 1024. Maximum number of files (TCP connections)
that proxy.py can open concurrently.
Default: 1024. Maximum number of files (TCP connections) that proxy.py
can open concurrently.
--plugins PLUGINS [PLUGINS ...]
Comma separated plugins. You may use --plugins flag
multiple times.
Comma separated plugins. You may use --plugins flag multiple times.
--enable-dashboard Default: False. Enables proxy.py dashboard.
--work-klass WORK_KLASS
Default: proxy.http.HttpProtocolHandler. Work klass to
use for work execution.
Default: proxy.http.HttpProtocolHandler. Work klass to use for work
execution.
--pid-file PID_FILE Default: None. Save "parent" process ID to a file.
--client-recvbuf-size CLIENT_RECVBUF_SIZE
Default: 1 MB. Maximum amount of data received from the
client in a single recv() operation. Bump this value for
faster uploads at the expense of increased RAM.
--key-file KEY_FILE Default: None. Server key file to enable end-to-end TLS
encryption with clients. If used, must also pass --cert-
file.
--timeout TIMEOUT Default: 10.0. Number of seconds after which an inactive
connection must be dropped. Inactivity is defined by no
data sent or received by the client.
Default: 1 MB. Maximum amount of data received from the client in a
single recv() operation. Bump this value for faster uploads at the
expense of increased RAM.
--key-file KEY_FILE Default: None. Server key file to enable end-to-end TLS encryption with
clients. If used, must also pass --cert-file.
--timeout TIMEOUT Default: 10.0. Number of seconds after which an inactive connection must
be dropped. Inactivity is defined by no data sent or received by the
client.
--server-recvbuf-size SERVER_RECVBUF_SIZE
Default: 1 MB. Maximum amount of data received from the server in a
single recv() operation. Bump this value for faster downloads at the
expense of increased RAM.
--disable-http-proxy Default: False. Whether to disable proxy.HttpProxyPlugin.
--disable-headers DISABLE_HEADERS
Default: None. Comma separated list of headers to remove before
dispatching client request to upstream server.
--ca-key-file CA_KEY_FILE
Default: None. CA key to use for signing dynamically
generated HTTPS certificates. If used, must also pass
--ca-cert-file and --ca-signing-key-file
Default: None. CA key to use for signing dynamically generated HTTPS
certificates. If used, must also pass --ca-cert-file and --ca-signing-
key-file
--ca-cert-dir CA_CERT_DIR
Default: ~/.proxy.py. Directory to store dynamically
generated certificates. Also see --ca-key-file, --ca-
cert-file and --ca-signing-key-file
Default: ~/.proxy.py. Directory to store dynamically generated
certificates. Also see --ca-key-file, --ca-cert-file and --ca-signing-
key-file
--ca-cert-file CA_CERT_FILE
Default: None. Signing certificate to use for signing
dynamically generated HTTPS certificates. If used, must
also pass --ca-key-file and --ca-signing-key-file
--ca-file CA_FILE Default: /Users/abhinavsingh/Dev/proxy.py/venv310/lib/pyt
hon3.10/site-packages/certifi/cacert.pem. Provide path to
custom CA bundle for peer certificate verification
Default: None. Signing certificate to use for signing dynamically
generated HTTPS certificates. If used, must also pass --ca-key-file and
--ca-signing-key-file
--ca-file CA_FILE Default: /Users/abhinavsingh/Dev/proxy.py/venv310/lib/python3.10/site-
packages/certifi/cacert.pem. Provide path to custom CA bundle for peer
certificate verification
--ca-signing-key-file CA_SIGNING_KEY_FILE
Default: None. CA signing key to use for dynamic
generation of HTTPS certificates. If used, must also pass
--ca-key-file and --ca-cert-file
Default: None. CA signing key to use for dynamic generation of HTTPS
certificates. If used, must also pass --ca-key-file and --ca-cert-file
--cert-file CERT_FILE
Default: None. Server certificate to enable end-to-end
TLS encryption with clients. If used, must also pass
--key-file.
--disable-headers DISABLE_HEADERS
Default: None. Comma separated list of headers to remove
before dispatching client request to upstream server.
--server-recvbuf-size SERVER_RECVBUF_SIZE
Default: 1 MB. Maximum amount of data received from the
server in a single recv() operation. Bump this value for
faster downloads at the expense of increased RAM.
Default: None. Server certificate to enable end-to-end TLS encryption
with clients. If used, must also pass --key-file.
--auth-plugin AUTH_PLUGIN
Default: proxy.http.proxy.AuthPlugin. Auth plugin to use instead of
default basic auth plugin.
--basic-auth BASIC_AUTH
Default: No authentication. Specify colon separated
user:password to enable basic authentication.
Default: No authentication. Specify colon separated user:password to
enable basic authentication.
--cache-dir CACHE_DIR
Default: A temporary directory. Flag only applicable when
cache plugin is used with on-disk storage.
Default: A temporary directory. Flag only applicable when cache plugin
is used with on-disk storage.
--filtered-upstream-hosts FILTERED_UPSTREAM_HOSTS
Default: Blocks Facebook. Comma separated list of IPv4
and IPv6 addresses.
--enable-web-server Default: False. Whether to enable
proxy.HttpWebServerPlugin.
Default: Blocks Facebook. Comma separated list of IPv4 and IPv6
addresses.
--enable-web-server Default: False. Whether to enable proxy.HttpWebServerPlugin.
--enable-static-server
Default: False. Enable inbuilt static file server.
Optionally, also use --static-server-dir to serve static
content from custom directory. By default, static file
server serves out of installed proxy.py python module
folder.
Default: False. Enable inbuilt static file server. Optionally, also use
--static-server-dir to serve static content from custom directory. By
default, static file server serves out of installed proxy.py python
module folder.
--static-server-dir STATIC_SERVER_DIR
Default: "public" folder in directory where proxy.py is
placed. This option is only applicable when static server
is also enabled. See --enable-static-server.
Default: "public" folder in directory where proxy.py is placed. This
option is only applicable when static server is also enabled. See
--enable-static-server.
--min-compression-length MIN_COMPRESSION_LENGTH
Default: 20 bytes. Sets the minimum length of a response
that will be compressed (gzipped).
--pac-file PAC_FILE A file (Proxy Auto Configuration) or string to serve when
the server receives a direct file request. Using this
option enables proxy.HttpWebServerPlugin.
Default: 20 bytes. Sets the minimum length of a response that will be
compressed (gzipped).
--pac-file PAC_FILE A file (Proxy Auto Configuration) or string to serve when the server
receives a direct file request. Using this option enables
proxy.HttpWebServerPlugin.
--pac-file-url-path PAC_FILE_URL_PATH
Default: /. Web server path to serve the PAC file.
--proxy-pool PROXY_POOL
List of upstream proxies to use in the pool
--filtered-client-ips FILTERED_CLIENT_IPS
Default: 127.0.0.1,::1. Comma separated list of IPv4 and
IPv6 addresses.
Default: 127.0.0.1,::1. Comma separated list of IPv4 and IPv6 addresses.
--filtered-url-regex-config FILTERED_URL_REGEX_CONFIG
Default: No config. Comma separated list of IPv4 and IPv6
addresses.
Default: No config. Comma separated list of IPv4 and IPv6 addresses.
--cloudflare-dns-mode CLOUDFLARE_DNS_MODE
Default: security. Either "security" (for malware
protection) or "family" (for malware and adult content
protection)
Default: security. Either "security" (for malware protection) or
"family" (for malware and adult content protection)

Proxy.py not working? Report at:
https://github.com/abhinavsingh/proxy.py/issues/new
Proxy.py not working? Report at: https://github.com/abhinavsingh/proxy.py/issues/new
```

# Changelog
Expand Down
28 changes: 21 additions & 7 deletions proxy/common/flag.py
Original file line number Diff line number Diff line change
Expand Up @@ -135,18 +135,34 @@ def initialize(

# Generate auth_code required for basic authentication if enabled
auth_code = None
if args.basic_auth:
auth_code = base64.b64encode(bytes_(args.basic_auth))
basic_auth = opts.get('basic_auth', args.basic_auth)
# Destroy passed credentials via flags or options
args.basic_auth = None
if 'basic_auth' in opts:
del opts['basic_auth']

# Resolve auth module.
auth_plugins = []
auth_plugin = opts.get('auth_plugin', args.auth_plugin)
if basic_auth:
auth_code = base64.b64encode(bytes_(basic_auth))
if basic_auth or auth_plugin != PLUGIN_PROXY_AUTH:
# No basic auth provided
# Here auth_plugin is set to default plugin
# We want to avoid loading the auth plugin (w/o basic auth)
# unless user overrides the default auth plugin.
auth_plugins.append(auth_plugin)

# Load default plugins along with user provided --plugins
default_plugins = [
bytes_(p)
for p in FlagParser.get_default_plugins(args)
]
requested_plugins = Plugins.resolve_plugin_flag(
args.plugins, opts.get('plugins', None),
)
plugins = Plugins.load(
default_plugins + Plugins.resolve_plugin_flag(
args.plugins, opts.get('plugins', None),
),
default_plugins + auth_plugins + requested_plugins,
)

# https://github.com/python/mypy/issues/5865
Expand Down Expand Up @@ -339,8 +355,6 @@ def get_default_plugins(
--enable-*, --disable-* and --basic-auth flags.
"""
default_plugins: List[str] = []
if args.basic_auth is not None:
default_plugins.append(PLUGIN_PROXY_AUTH)
if hasattr(args, 'enable_dashboard') and args.enable_dashboard:
default_plugins.append(PLUGIN_WEB_SERVER)
args.enable_static_server = True
Expand Down
10 changes: 5 additions & 5 deletions proxy/common/plugins.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
import itertools
import importlib

from typing import Any, List, Dict, Optional, Union
from typing import Any, List, Dict, Optional, Tuple, Union

from .utils import bytes_, text_
from .constants import DOT, DEFAULT_ABC_PLUGINS, COMMA
Expand Down Expand Up @@ -46,11 +46,11 @@ def resolve_plugin_flag(flag_plugins: Any, opt_plugins: Optional[Any] = None) ->

@staticmethod
def discover(input_args: List[str]) -> None:
"""Search for plugin and plugins flag in command line arguments,
then iterates over each value and discovers the plugin.
"""Search for external plugin found in command line arguments,
then iterates over each value and discover/import the plugin.
"""
for i, f in enumerate(input_args):
if f in ('--plugin', '--plugins'):
if f in ('--plugin', '--plugins', '--auth-plugin'):
v = input_args[i + 1]
parts = v.split(',')
for part in parts:
Expand Down Expand Up @@ -83,7 +83,7 @@ def load(
return p

@staticmethod
def importer(plugin: Union[bytes, type]) -> Any:
def importer(plugin: Union[bytes, type]) -> Tuple[type, str]:
"""Import and returns the plugin."""
if isinstance(plugin, type):
return (plugin, '__main__')
Expand Down
6 changes: 5 additions & 1 deletion proxy/core/connection/server.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,11 @@ def connection(self) -> Union[ssl.SSLSocket, socket.socket]:
raise TcpConnectionUninitializedException()
return self._conn

def connect(self, addr: Optional[Tuple[str, int]] = None, source_address: Optional[Tuple[str, int]] = None) -> None:
def connect(
self,
addr: Optional[Tuple[str, int]] = None,
source_address: Optional[Tuple[str, int]] = None,
) -> None:
if self._conn is None:
self._conn = new_socket_connection(
addr or self.addr, source_address=source_address,
Expand Down
Loading