diff options
author | Maximilian Hils <git@maximilianhils.com> | 2014-08-09 03:03:21 +0200 |
---|---|---|
committer | Maximilian Hils <git@maximilianhils.com> | 2014-08-09 03:03:21 +0200 |
commit | ecf8081ba63f15ec283979a3418951711ec30071 (patch) | |
tree | d5503f87ddb94045609921eac5f0348bac8aaea9 /libmproxy | |
parent | f4a1459ebeca7c72419bce17d931f8b2c846df5e (diff) | |
download | mitmproxy-ecf8081ba63f15ec283979a3418951711ec30071.tar.gz mitmproxy-ecf8081ba63f15ec283979a3418951711ec30071.tar.bz2 mitmproxy-ecf8081ba63f15ec283979a3418951711ec30071.zip |
implement passthrough mode, fixes #175
Diffstat (limited to 'libmproxy')
-rw-r--r-- | libmproxy/cmdline.py | 16 | ||||
-rw-r--r-- | libmproxy/protocol/tcp.py | 5 | ||||
-rw-r--r-- | libmproxy/proxy/config.py | 5 | ||||
-rw-r--r-- | libmproxy/proxy/server.py | 39 |
4 files changed, 42 insertions, 23 deletions
diff --git a/libmproxy/cmdline.py b/libmproxy/cmdline.py index c9c0c75e..500337a7 100644 --- a/libmproxy/cmdline.py +++ b/libmproxy/cmdline.py @@ -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", diff --git a/libmproxy/protocol/tcp.py b/libmproxy/protocol/tcp.py index 33c9ff05..a77a9096 100644 --- a/libmproxy/protocol/tcp.py +++ b/libmproxy/protocol/tcp.py @@ -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])
\ No newline at end of file diff --git a/libmproxy/proxy/config.py b/libmproxy/proxy/config.py index a6a962ea..afa7440c 100644 --- a/libmproxy/proxy/config.py +++ b/libmproxy/proxy/config.py @@ -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, diff --git a/libmproxy/proxy/server.py b/libmproxy/proxy/server.py index 345e1507..d4a97e6a 100644 --- a/libmproxy/proxy/server.py +++ b/libmproxy/proxy/server.py @@ -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: |