fix dns_spoofing example, avoid connecting to itself
This commit is contained in:
parent
1e9aef5b1e
commit
7450bef615
|
@ -8,30 +8,43 @@ Similarly, if there's no Host header or a spoofed Host header, we're out of luck
|
|||
Using transparent mode is the better option most of the time.
|
||||
|
||||
Usage:
|
||||
mitmproxy
|
||||
-p 80
|
||||
-R http://example.com/ // Used as the target location if no Host header is present
|
||||
mitmproxy
|
||||
-p 443
|
||||
-R https://example.com/ // Used as the target locaction if neither SNI nor host header are present.
|
||||
-s dns_spoofing.py
|
||||
# Used as the target location if neither SNI nor host header are present.
|
||||
-R http://example.com/
|
||||
mitmdump
|
||||
-p 80
|
||||
-R http://localhost:443/
|
||||
|
||||
mitmproxy will always connect to the default location first, so it must be reachable.
|
||||
As a workaround, you can spawn an arbitrary HTTP server and use that for both endpoints, e.g.
|
||||
mitmproxy -p 80 -R http://localhost:8000
|
||||
mitmproxy -p 443 -R https2http://localhost:8000
|
||||
(Setting up a single proxy instance and using iptables to redirect to it
|
||||
works as well)
|
||||
"""
|
||||
import re
|
||||
|
||||
|
||||
# This regex extracts splits the host header into host and port.
|
||||
# Handles the edge case of IPv6 addresses containing colons.
|
||||
# https://bugzilla.mozilla.org/show_bug.cgi?id=45891
|
||||
parse_host_header = re.compile(r"^(?P<host>[^:]+|\[.+\])(?::(?P<port>\d+))?$")
|
||||
|
||||
|
||||
def request(context, flow):
|
||||
if flow.client_conn.ssl_established:
|
||||
# TLS SNI or Host header
|
||||
flow.request.host = flow.client_conn.connection.get_servername(
|
||||
) or flow.request.pretty_host(hostheader=True)
|
||||
|
||||
# If you use a https2http location as default destination, these
|
||||
# attributes need to be corrected as well:
|
||||
flow.request.port = 443
|
||||
flow.request.scheme = "https"
|
||||
sni = flow.client_conn.connection.get_servername()
|
||||
port = 443
|
||||
else:
|
||||
# Host header
|
||||
flow.request.host = flow.request.pretty_host(hostheader=True)
|
||||
flow.request.scheme = "http"
|
||||
sni = None
|
||||
port = 80
|
||||
|
||||
host_header = flow.request.pretty_host(hostheader=True)
|
||||
m = parse_host_header.match(host_header)
|
||||
if m:
|
||||
host_header = m.group("host").strip("[]")
|
||||
if m.group("port"):
|
||||
port = int(m.group("port"))
|
||||
|
||||
flow.request.host = sni or host_header
|
||||
flow.request.port = port
|
|
@ -1,4 +1,4 @@
|
|||
from __future__ import absolute_import
|
||||
from __future__ import (absolute_import, print_function, division)
|
||||
|
||||
import copy
|
||||
import os
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
from __future__ import absolute_import
|
||||
from __future__ import (absolute_import, print_function, division)
|
||||
import copy
|
||||
import uuid
|
||||
|
||||
|
|
|
@ -103,6 +103,7 @@ class ServerConnectionMixin(object):
|
|||
def __init__(self, server_address=None):
|
||||
super(ServerConnectionMixin, self).__init__()
|
||||
self.server_conn = ServerConnection(server_address)
|
||||
self._check_self_connect()
|
||||
|
||||
def reconnect(self):
|
||||
address = self.server_conn.address
|
||||
|
@ -110,12 +111,30 @@ class ServerConnectionMixin(object):
|
|||
self.server_conn.address = address
|
||||
self.connect()
|
||||
|
||||
def _check_self_connect(self):
|
||||
"""
|
||||
We try to protect the proxy from _accidentally_ connecting to itself,
|
||||
e.g. because of a failed transparent lookup or an invalid configuration.
|
||||
"""
|
||||
address = self.server_conn.address
|
||||
if address:
|
||||
self_connect = (
|
||||
address.port == self.config.port and
|
||||
address.host in ("localhost", "127.0.0.1", "::1")
|
||||
)
|
||||
if self_connect:
|
||||
raise ProtocolException(
|
||||
"Invalid server address: {}\r\n"
|
||||
"The proxy shall not connect to itself.".format(repr(address))
|
||||
)
|
||||
|
||||
def set_server(self, address, server_tls=None, sni=None, depth=1):
|
||||
if depth == 1:
|
||||
if self.server_conn:
|
||||
self._disconnect()
|
||||
self.log("Set new server address: " + repr(address), "debug")
|
||||
self.server_conn.address = address
|
||||
self._check_self_connect()
|
||||
if server_tls:
|
||||
raise ProtocolException(
|
||||
"Cannot upgrade to TLS, no TLS layer on the protocol stack."
|
||||
|
@ -141,7 +160,7 @@ class ServerConnectionMixin(object):
|
|||
self.server_conn.connect()
|
||||
except tcp.NetLibError as e:
|
||||
raise ProtocolException(
|
||||
"Server connection to '%s' failed: %s" % (self.server_conn.address, e), e)
|
||||
"Server connection to %s failed: %s" % (repr(self.server_conn.address), e), e)
|
||||
|
||||
|
||||
class Log(object):
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
from __future__ import (absolute_import, print_function, division)
|
||||
import threading
|
||||
|
||||
from netlib.http import HttpError
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
from __future__ import absolute_import
|
||||
from __future__ import (absolute_import, print_function, division)
|
||||
import collections
|
||||
import os
|
||||
import re
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
from __future__ import absolute_import, print_function
|
||||
from __future__ import (absolute_import, print_function, division)
|
||||
|
||||
import traceback
|
||||
import sys
|
||||
|
|
Loading…
Reference in New Issue