aboutsummaryrefslogtreecommitdiffstats
path: root/libmproxy
diff options
context:
space:
mode:
authorAldo Cortesi <aldo@nullcube.com>2015-06-23 14:01:50 +1200
committerAldo Cortesi <aldo@nullcube.com>2015-06-23 14:01:50 +1200
commit2c928181e841b25d5ae8d1390802900b4cc6834e (patch)
tree5bde55e614557f39821e269061e14516b39f3a54 /libmproxy
parent237e05c823958dc9ea50c648cc98bedc2ef305d3 (diff)
parente2069d52a81a2aef99dcd2da4fbc61e926b024a0 (diff)
downloadmitmproxy-2c928181e841b25d5ae8d1390802900b4cc6834e.tar.gz
mitmproxy-2c928181e841b25d5ae8d1390802900b4cc6834e.tar.bz2
mitmproxy-2c928181e841b25d5ae8d1390802900b4cc6834e.zip
Merge branch 'master' of ssh.github.com:mitmproxy/mitmproxy
Diffstat (limited to 'libmproxy')
-rw-r--r--libmproxy/cmdline.py15
-rw-r--r--libmproxy/protocol/http.py28
-rw-r--r--libmproxy/proxy/config.py21
-rw-r--r--libmproxy/proxy/primitives.py27
-rw-r--r--libmproxy/proxy/server.py15
5 files changed, 101 insertions, 5 deletions
diff --git a/libmproxy/cmdline.py b/libmproxy/cmdline.py
index eb24bed7..08639f6d 100644
--- a/libmproxy/cmdline.py
+++ b/libmproxy/cmdline.py
@@ -370,6 +370,21 @@ def common_options(parser):
default=None,
help="Forward all requests to upstream proxy server: http://host[:port]"
)
+ group.add_argument(
+ "--spoof",
+ action="store_true", dest="spoof_mode", default=False,
+ help="Use Host header to connect to HTTP servers."
+ )
+ group.add_argument(
+ "--ssl-spoof",
+ action="store_true", dest="ssl_spoof_mode", default=False,
+ help="Use TLS SNI to connect to HTTPS servers."
+ )
+ group.add_argument(
+ "--spoofed-port",
+ action="store", dest="spoofed_ssl_port", type=int, default=443,
+ help="Port number of upstream HTTPS servers in SSL spoof mode."
+ )
group = parser.add_argument_group(
"Advanced Proxy Options",
diff --git a/libmproxy/protocol/http.py b/libmproxy/protocol/http.py
index 9c143386..9bce7206 100644
--- a/libmproxy/protocol/http.py
+++ b/libmproxy/protocol/http.py
@@ -1328,8 +1328,34 @@ class HTTPHandler(ProtocolHandler):
# value at flow.server_conn
self.c.set_server_address((request.host, request.port))
flow.server_conn = self.c.server_conn
-
+
+ elif request.form_in == "relative":
+ if self.c.config.mode == "spoof":
+ # Host header
+ h = request.pretty_host(hostheader=True)
+ if h is None:
+ raise http.HttpError(
+ 400,
+ "Invalid request: No host information"
+ )
+ p = http.parse_url("http://" + h)
+ request.scheme = p[0]
+ request.host = p[1]
+ request.port = p[2]
+ self.c.set_server_address((request.host, request.port))
+ flow.server_conn = self.c.server_conn
+
+ if self.c.config.mode == "sslspoof":
+ # SNI is processed in server.py
+ if not (flow.server_conn and flow.server_conn.ssl_established):
+ print ":::::::::::::::"
+ raise http.HttpError(
+ 400,
+ "Invalid request: No host information"
+ )
+
return None
+
raise http.HttpError(
400, "Invalid HTTP request form (expected: %s, got: %s)" % (
self.expected_form_in, request.form_in
diff --git a/libmproxy/proxy/config.py b/libmproxy/proxy/config.py
index 3f579669..07dc5c89 100644
--- a/libmproxy/proxy/config.py
+++ b/libmproxy/proxy/config.py
@@ -4,7 +4,7 @@ import re
from OpenSSL import SSL
from netlib import http_auth, certutils, tcp
from .. import utils, platform, version
-from .primitives import RegularProxyMode, TransparentProxyMode, UpstreamProxyMode, ReverseProxyMode, Socks5ProxyMode
+from .primitives import RegularProxyMode, SpoofMode, SSLSpoofMode, TransparentProxyMode, UpstreamProxyMode, ReverseProxyMode, Socks5ProxyMode
TRANSPARENT_SSL_PORTS = [443, 8443]
CONF_BASENAME = "mitmproxy"
@@ -51,7 +51,8 @@ class ProxyConfig:
certforward=False,
ssl_version_client="secure",
ssl_version_server="secure",
- ssl_ports=TRANSPARENT_SSL_PORTS
+ ssl_ports=TRANSPARENT_SSL_PORTS,
+ spoofed_ssl_port=None
):
self.host = host
self.port = port
@@ -70,6 +71,10 @@ class ProxyConfig:
self.mode = ReverseProxyMode(upstream_server)
elif mode == "upstream":
self.mode = UpstreamProxyMode(upstream_server)
+ elif mode == "spoof":
+ self.mode = SpoofMode()
+ elif mode == "sslspoof":
+ self.mode = SSLSpoofMode(spoofed_ssl_port)
else:
self.mode = RegularProxyMode()
@@ -126,7 +131,7 @@ def process_proxy_options(parser, options):
body_size_limit = utils.parse_size(options.body_size_limit)
c = 0
- mode, upstream_server = None, None
+ mode, upstream_server, spoofed_ssl_port = None, None, None
if options.transparent_proxy:
c += 1
if not platform.resolver:
@@ -144,6 +149,13 @@ def process_proxy_options(parser, options):
c += 1
mode = "upstream"
upstream_server = options.upstream_proxy
+ if options.spoof_mode:
+ c += 1
+ mode = "spoof"
+ if options.ssl_spoof_mode:
+ c += 1
+ mode = "sslspoof"
+ spoofed_ssl_port = options.spoofed_ssl_port
if c > 1:
return parser.error(
"Transparent, SOCKS5, reverse and upstream proxy mode "
@@ -213,7 +225,8 @@ def process_proxy_options(parser, options):
certforward=options.certforward,
ssl_version_client=options.ssl_version_client,
ssl_version_server=options.ssl_version_server,
- ssl_ports=ssl_ports
+ ssl_ports=ssl_ports,
+ spoofed_ssl_port=spoofed_ssl_port
)
diff --git a/libmproxy/proxy/primitives.py b/libmproxy/proxy/primitives.py
index 9e7dae9a..b01ddde3 100644
--- a/libmproxy/proxy/primitives.py
+++ b/libmproxy/proxy/primitives.py
@@ -51,6 +51,33 @@ class RegularProxyMode(ProxyMode):
return None
+class SpoofMode(ProxyMode):
+ http_form_in = "relative"
+ http_form_out = "relative"
+
+ def get_upstream_server(self, client_conn):
+ return None
+
+ @property
+ def name(self):
+ return "spoof"
+
+
+class SSLSpoofMode(ProxyMode):
+ http_form_in = "relative"
+ http_form_out = "relative"
+
+ def __init__(self, sslport):
+ self.sslport = sslport
+
+ def get_upstream_server(self, client_conn):
+ return None
+
+ @property
+ def name(self):
+ return "sslspoof"
+
+
class TransparentProxyMode(ProxyMode):
http_form_in = "relative"
http_form_out = "relative"
diff --git a/libmproxy/proxy/server.py b/libmproxy/proxy/server.py
index e1587df1..71704413 100644
--- a/libmproxy/proxy/server.py
+++ b/libmproxy/proxy/server.py
@@ -117,6 +117,16 @@ class ConnectionHandler:
self.server_conn.address(),
"info")
self.conntype = "tcp"
+
+ elif not self.server_conn and self.config.mode == "sslspoof":
+ port = self.config.mode.sslport
+ self.set_server_address(("-", port))
+ self.establish_ssl(client=True)
+ host = self.client_conn.connection.get_servername()
+ if host:
+ self.set_server_address((host, port))
+ self.establish_server_connection()
+ self.establish_ssl(server=True, sni=host)
# Delegate handling to the protocol handler
protocol_handler(
@@ -308,6 +318,9 @@ class ConnectionHandler:
host = upstream_cert.cn.decode("utf8").encode("idna")
if self.server_conn.sni:
sans.append(self.server_conn.sni)
+ # for ssl spoof mode
+ if hasattr(self.client_conn, "sni"):
+ sans.append(self.client_conn.sni)
ret = self.config.certstore.get_cert(host, sans)
if not ret:
@@ -325,6 +338,8 @@ class ConnectionHandler:
if not sn:
return
sni = sn.decode("utf8").encode("idna")
+ # for ssl spoof mode
+ self.client_conn.sni = sni
if sni != self.server_conn.sni:
self.log("SNI received: %s" % sni, "debug")