Added -F http[s]://server:port option that allows MITM to forward traffic to another http server upstream.

This commit is contained in:
JC 2013-08-30 17:14:18 -07:00
parent 8d954d9965
commit 65d1ed1b3c
2 changed files with 21 additions and 2 deletions

View File

@ -189,6 +189,11 @@ def common_options(parser):
action="store", dest="reverse_proxy", default=None, action="store", dest="reverse_proxy", default=None,
help="Reverse proxy to upstream server: http[s]://host[:port]" help="Reverse proxy to upstream server: http[s]://host[:port]"
) )
parser.add_argument(
"-F",
action="store", dest="forward_proxy", default=None,
help="Proxy to unconditionally forward to: http[s]://host[:port]"
)
parser.add_argument( parser.add_argument(
"-q", "-q",
action="store_true", dest="quiet", action="store_true", dest="quiet",

View File

@ -23,13 +23,14 @@ class Log:
class ProxyConfig: class ProxyConfig:
def __init__(self, certfile = None, cacert = None, clientcerts = None, no_upstream_cert=False, body_size_limit = None, reverse_proxy=None, transparent_proxy=None, authenticator=None): def __init__(self, certfile = None, cacert = None, clientcerts = None, no_upstream_cert=False, body_size_limit = None, reverse_proxy=None, forward_proxy=None, transparent_proxy=None, authenticator=None):
self.certfile = certfile self.certfile = certfile
self.cacert = cacert self.cacert = cacert
self.clientcerts = clientcerts self.clientcerts = clientcerts
self.no_upstream_cert = no_upstream_cert self.no_upstream_cert = no_upstream_cert
self.body_size_limit = body_size_limit self.body_size_limit = body_size_limit
self.reverse_proxy = reverse_proxy self.reverse_proxy = reverse_proxy
self.forward_proxy = forward_proxy
self.transparent_proxy = transparent_proxy self.transparent_proxy = transparent_proxy
self.authenticator = authenticator self.authenticator = authenticator
self.certstore = certutils.CertStore() self.certstore = certutils.CertStore()
@ -219,7 +220,12 @@ class ProxyHandler(tcp.BaseHandler):
# the case, we want to reconnect without sending an error # the case, we want to reconnect without sending an error
# to the client. # to the client.
while 1: while 1:
if self.config.forward_proxy:
forward_scheme, forward_host, forward_port = self.config.forward_proxy
sc = self.get_server_connection(cc, forward_scheme, forward_host, forward_port, self.sni)
else:
sc = self.get_server_connection(cc, scheme, host, port, self.sni) sc = self.get_server_connection(cc, scheme, host, port, self.sni)
sc.send(request) sc.send(request)
if sc.requestcount == 1: # add timestamps only for first request (others are not directly affected) if sc.requestcount == 1: # add timestamps only for first request (others are not directly affected)
request.tcp_setup_timestamp = sc.tcp_setup_timestamp request.tcp_setup_timestamp = sc.tcp_setup_timestamp
@ -594,6 +600,13 @@ def process_proxy_options(parser, options):
else: else:
rp = None rp = None
if options.forward_proxy:
fp = utils.parse_proxy_spec(options.forward_proxy)
if not fp:
return parser.error("Invalid forward proxy specification: %s"%options.forward_proxy)
else:
fp = None
if options.clientcerts: if options.clientcerts:
options.clientcerts = os.path.expanduser(options.clientcerts) options.clientcerts = os.path.expanduser(options.clientcerts)
if not os.path.exists(options.clientcerts) or not os.path.isdir(options.clientcerts): if not os.path.exists(options.clientcerts) or not os.path.isdir(options.clientcerts):
@ -623,6 +636,7 @@ def process_proxy_options(parser, options):
body_size_limit = body_size_limit, body_size_limit = body_size_limit,
no_upstream_cert = options.no_upstream_cert, no_upstream_cert = options.no_upstream_cert,
reverse_proxy = rp, reverse_proxy = rp,
forward_proxy = fp,
transparent_proxy = trans, transparent_proxy = trans,
authenticator = authenticator authenticator = authenticator
) )