mirror of
https://github.com/Grasscutters/mitmproxy.git
synced 2024-11-26 18:18:25 +00:00
implement passthrough mode, fixes #175
This commit is contained in:
parent
f4a1459ebe
commit
ecf8081ba6
@ -262,9 +262,14 @@ def common_options(parser):
|
||||
help="Address to bind proxy to (defaults to all interfaces)"
|
||||
)
|
||||
group.add_argument(
|
||||
"-U",
|
||||
action="store", type=parse_server_spec, dest="upstream_proxy", default=None,
|
||||
help="Forward all requests to upstream proxy server: http[s]://host[:port]"
|
||||
"-I", "--ignore",
|
||||
action="append", type=str, dest="ignore", default=[],
|
||||
metavar="HOST",
|
||||
help="Ignore host and forward all traffic without processing it. "
|
||||
"In transparent mode, it is recommended to use an IP address (range), not the hostname. "
|
||||
"In regular mode, only SSL traffic is ignored and the hostname should be used. "
|
||||
"The supplied value is interpreted as a regular expression and matched on the ip or the hostname. "
|
||||
"Can be passed multiple times. "
|
||||
)
|
||||
group.add_argument(
|
||||
"-n",
|
||||
@ -286,6 +291,11 @@ def common_options(parser):
|
||||
action="store_true", dest="transparent_proxy", default=False,
|
||||
help="Set transparent proxy mode."
|
||||
)
|
||||
group.add_argument(
|
||||
"-U",
|
||||
action="store", type=parse_server_spec, dest="upstream_proxy", default=None,
|
||||
help="Forward all requests to upstream proxy server: http://host[:port]"
|
||||
)
|
||||
|
||||
group = parser.add_argument_group(
|
||||
"Advanced Proxy Options",
|
||||
|
@ -1,6 +1,7 @@
|
||||
from __future__ import absolute_import
|
||||
import select, socket
|
||||
from .primitives import ProtocolHandler
|
||||
from netlib.utils import cleanBin
|
||||
|
||||
class TCPHandler(ProtocolHandler):
|
||||
"""
|
||||
@ -57,9 +58,9 @@ class TCPHandler(ProtocolHandler):
|
||||
# if one of the peers is over SSL, we need to send bytes/strings
|
||||
if not src.ssl_established: # only ssl to dst, i.e. we revc'd into buf but need bytes/string now.
|
||||
contents = buf[:size].tobytes()
|
||||
self.c.log("%s %s\r\n%s" % (direction, dst_str, contents[:100]), "debug")
|
||||
self.c.log("%s %s\r\n%s" % (direction, dst_str, cleanBin(contents)), "debug")
|
||||
dst.connection.send(contents)
|
||||
else:
|
||||
# socket.socket.send supports raw bytearrays/memoryviews
|
||||
self.c.log("%s %s\r\n%s" % (direction, dst_str, buf[:100]), "debug")
|
||||
self.c.log("%s %s\r\n%s" % (direction, dst_str, cleanBin(buf.tobytes())), "debug")
|
||||
dst.connection.send(buf[:size])
|
@ -1,6 +1,7 @@
|
||||
from __future__ import absolute_import
|
||||
import os
|
||||
from .. import utils, platform
|
||||
import re
|
||||
from netlib import http_auth, certutils
|
||||
from .primitives import ConstUpstreamServerResolver, TransparentUpstreamServerResolver
|
||||
|
||||
@ -13,7 +14,7 @@ class ProxyConfig:
|
||||
def __init__(self, confdir=CONF_DIR, clientcerts=None,
|
||||
no_upstream_cert=False, body_size_limit=None,
|
||||
mode=None, upstream_server=None, http_form_in=None, http_form_out=None,
|
||||
authenticator=None,
|
||||
authenticator=None, ignore=[],
|
||||
ciphers=None, certs=[], certforward=False):
|
||||
self.ciphers = ciphers
|
||||
self.clientcerts = clientcerts
|
||||
@ -40,6 +41,7 @@ class ProxyConfig:
|
||||
self.get_upstream_server = get_upstream_server
|
||||
self.http_form_in = http_form_in
|
||||
self.http_form_out = http_form_out
|
||||
self.ignore = [re.compile(i, re.IGNORECASE) for i in ignore]
|
||||
self.authenticator = authenticator
|
||||
self.confdir = os.path.expanduser(confdir)
|
||||
self.ca_file = os.path.join(self.confdir, CONF_BASENAME + "-ca.pem")
|
||||
@ -118,6 +120,7 @@ def process_proxy_options(parser, options):
|
||||
upstream_server=upstream_server,
|
||||
http_form_in=options.http_form_in,
|
||||
http_form_out=options.http_form_out,
|
||||
ignore=options.ignore,
|
||||
authenticator=authenticator,
|
||||
ciphers=options.ciphers,
|
||||
certs=certs,
|
||||
|
@ -1,4 +1,5 @@
|
||||
from __future__ import absolute_import
|
||||
import re
|
||||
|
||||
import socket
|
||||
from OpenSSL import SSL
|
||||
@ -66,31 +67,34 @@ class ConnectionHandler:
|
||||
self.channel, self.server_version = channel, server_version
|
||||
|
||||
self.close = False
|
||||
self.conntype = None
|
||||
self.conntype = "http"
|
||||
self.sni = None
|
||||
|
||||
def handle(self):
|
||||
self.log("clientconnect", "info")
|
||||
self.channel.ask("clientconnect", self)
|
||||
|
||||
self.determine_conntype()
|
||||
|
||||
try:
|
||||
# Can we already identify the target server and connect to it?
|
||||
client_ssl, server_ssl = False, False
|
||||
if self.config.get_upstream_server:
|
||||
upstream_info = self.config.get_upstream_server(
|
||||
self.client_conn.connection)
|
||||
self.set_server_address(upstream_info[2:], AddressPriority.FROM_SETTINGS)
|
||||
client_ssl, server_ssl = upstream_info[:2]
|
||||
|
||||
self.determine_conntype()
|
||||
self.channel.ask("clientconnect", self)
|
||||
|
||||
if self.server_conn:
|
||||
self.establish_server_connection()
|
||||
if client_ssl or server_ssl:
|
||||
self.establish_server_connection()
|
||||
self.establish_ssl(client=client_ssl, server=server_ssl)
|
||||
|
||||
while not self.close:
|
||||
try:
|
||||
handle_messages(self.conntype, self)
|
||||
except ConnectionTypeChange:
|
||||
self.log("Connection Type Changed: %s" % self.conntype, "info")
|
||||
self.log("Connection type changed: %s" % self.conntype, "info")
|
||||
continue
|
||||
|
||||
except (ProxyError, tcp.NetLibError), e:
|
||||
@ -121,8 +125,11 @@ class ConnectionHandler:
|
||||
self.sni = None
|
||||
|
||||
def determine_conntype(self):
|
||||
#TODO: Add ruleset to select correct protocol depending on mode/target port etc.
|
||||
self.conntype = "http"
|
||||
if self.server_conn and any(rex.search(self.server_conn.address.host) for rex in self.config.ignore):
|
||||
self.log("Ignore host: %s" % self.server_conn.address.host, "info")
|
||||
self.conntype = "tcp"
|
||||
else:
|
||||
self.conntype = "http"
|
||||
|
||||
def set_server_address(self, address, priority):
|
||||
"""
|
||||
@ -135,7 +142,7 @@ class ConnectionHandler:
|
||||
if self.server_conn.priority > priority:
|
||||
self.log("Attempt to change server address, "
|
||||
"but priority is too low (is: %s, got: %s)" % (
|
||||
self.server_conn.priority, priority), "info")
|
||||
self.server_conn.priority, priority), "debug")
|
||||
return
|
||||
if self.server_conn.address == address:
|
||||
self.server_conn.priority = priority # Possibly increase priority
|
||||
@ -171,14 +178,12 @@ class ConnectionHandler:
|
||||
as specified by the parameters. If the target server is on the pass-through list,
|
||||
the conntype attribute will be changed and a ConnTypeChanged exception will be raised.
|
||||
"""
|
||||
# TODO: Implement SSL pass-through handling and change conntype
|
||||
passthrough = [
|
||||
# "echo.websocket.org",
|
||||
# "174.129.224.73" # echo.websocket.org, transparent mode
|
||||
]
|
||||
if self.server_conn.address.host in passthrough or self.sni in passthrough:
|
||||
self.conntype = "tcp"
|
||||
raise ConnectionTypeChange
|
||||
# If the host is on our ignore list, change to passthrough/ignore mode.
|
||||
for host in (self.server_conn.address.host, self.sni):
|
||||
if host and any(rex.search(host) for rex in self.config.ignore):
|
||||
self.log("Ignore host: %s" % host, "info")
|
||||
self.conntype = "tcp"
|
||||
raise ConnectionTypeChange()
|
||||
|
||||
# Logging
|
||||
if client or server:
|
||||
|
Loading…
Reference in New Issue
Block a user