-
Notifications
You must be signed in to change notification settings - Fork 19
/
tcp_proxy.py
154 lines (126 loc) · 4.33 KB
/
tcp_proxy.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
from twisted.internet import protocol, reactor
from twisted.internet import ssl as twisted_ssl
import dns.resolver
import netifaces as ni
# Adapted from http://stackoverflow.com/a/15645169/221061
class TCPProxyProtocol(protocol.Protocol):
"""
TCPProxyProtocol listens for TCP connections from a
client (eg. a phone) and forwards them on to a
specified destination (eg. an app's API server) over
a second TCP connection, using a ProxyToServerProtocol.
It assumes that neither leg of this trip is encrypted.
"""
def __init__(self):
self.buffer = None
self.proxy_to_server_protocol = None
def connectionMade(self):
"""
Called by twisted when a client connects to the
proxy. Makes an connection from the proxy to the
server to complete the chain.
"""
print("Connection made from CLIENT => PROXY")
proxy_to_server_factory = protocol.ClientFactory()
proxy_to_server_factory.protocol = ProxyToServerProtocol
proxy_to_server_factory.server = self
reactor.connectTCP(DST_IP, DST_PORT,
proxy_to_server_factory)
def dataReceived(self, data):
"""
Called by twisted when the proxy receives data from
the client. Sends the data on to the server.
CLIENT ===> PROXY ===> DST
"""
print("")
print("CLIENT => SERVER")
print(FORMAT_FN(data))
print("")
if self.proxy_to_server_protocol:
self.proxy_to_server_protocol.write(data)
else:
self.buffer = data
def write(self, data):
self.transport.write(data)
class ProxyToServerProtocol(protocol.Protocol):
"""
ProxyToServerProtocol connects to a server over TCP.
It sends the server data given to it by an
TCPProxyProtocol, and uses the TCPProxyProtocol to
send data that it receives back from the server on
to a client.
"""
def connectionMade(self):
"""
Called by twisted when the proxy connects to the
server. Flushes any buffered data on the proxy to
server.
"""
print("Connection made from PROXY => SERVER")
self.factory.server.proxy_to_server_protocol = self
self.write(self.factory.server.buffer)
self.factory.server.buffer = ''
def dataReceived(self, data):
"""
Called by twisted when the proxy receives data
from the server. Sends the data on to to the client.
DST ===> PROXY ===> CLIENT
"""
print("")
print("SERVER => CLIENT")
print(FORMAT_FN(data))
print("")
self.factory.server.write(data)
def write(self, data):
if data:
self.transport.write(data)
def _noop(data):
return data
def get_local_ip(iface):
ni.ifaddresses(iface)
return ni.ifaddresses(iface)[ni.AF_INET][0]['addr']
FORMAT_FN = _noop
LISTEN_PORT = 80
DST_PORT = 80
DST_HOST = "nonhttps.com"
local_ip = get_local_ip('en0')
# Look up the IP address of the target
print("Querying DNS records for %s..." % DST_HOST)
a_records = dns.resolver.query(DST_HOST, 'A')
print("Found %d A records:" % len(a_records))
for r in a_records:
print("* %s" % r.address)
print("")
assert(len(a_records) > 0)
# THe target may have multiple IP addresses - we
# simply choose the first one.
DST_IP = a_records[0].address
print("Choosing to proxy to %s" % DST_IP)
print("""
#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#
-#-#-#-#-#-RUNNING TCP PROXY-#-#-#-#-#-
#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#
Dst IP:\t%s
Dst port:\t%d
Dst hostname:\t%s
Listen port:\t%d
Local IP:\t%s
""" % (DST_IP, DST_PORT, DST_HOST, LISTEN_PORT, local_ip))
print("""
Next steps:
1. Make sure you are spoofing DNS requests from the
device you are trying to proxy request from so that they
return your local IP (%s).
2. Make sure you have set the destination and listen ports
correctly (they should generally be the same).
3. Use the device you are proxying requests from to make
requests to %s and check that they are logged in this
terminal.
4. Look at the requests, write more code to replay them,
fiddle with them, etc.
Listening for requests on %s:%d...
""" % (local_ip, DST_HOST, local_ip, LISTEN_PORT))
factory = protocol.ServerFactory()
factory.protocol = TCPProxyProtocol
reactor.listenTCP(LISTEN_PORT, factory)
reactor.run()