I was trying to make a simple proxy server, that can be used to relay any request message to some destination host, and receive the response back and relay it back to the original sender (client). My implementation causes the response of the first request message to get stalled in the server, and it only gets received as the response of the second request message. This causes some errors. I was trying to use this as an http proxy, running a simple http server on localhost, the proxy also on localhost, and used my browser to send GET messages to the proxy.
Below is the code
class Proxy:
def __init__(self,mhost,mport,dhost,dport):
self.mhost = mhost
self.mport = mport
self.dhost = dhost
self.dport = dport
#self.middle_man = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
#self.middle_man.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
self.colorAndFormat = ColorAndFormat() # Just for coloring the output text
def start_listener(self):
colorAndFormat = ColorAndFormat()
middle_man_recv = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
middle_man_recv.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
middle_man_recv.bind((self.mhost, self.mport))
middle_man_recv.listen()
print(colorAndFormat.Blue2("Listening on " + self.mhost + ':' + str(self.mport) + ' ...\n---------------------------------'))
middle_man_forw = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
middle_man_forw.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
#middle_man_forw.connect_ex((self.dhost, self.dport))
while True:
#try:
# Receive data
client_socket,client_addr = middle_man_recv.accept()
data = client_socket.recv(1024)
print(colorAndFormat.Blue2("Data received from client " + client_addr[0] + ':' + str(client_addr[1])))
print(colorAndFormat.Blue2(data.decode()))
# Forward data to dhost:dport
middle_man_forw.connect_ex((self.dhost, self.dport))
middle_man_forw.sendall(data)
print(colorAndFormat.Beige("Data forwarded to " + self.dhost + ':' + str(self.dport)))
# Receive data from dhost:dport
data = middle_man_forw.recv(1024)
print(colorAndFormat.Beige("Data received from " + self.dhost + ':' + str(self.dport)))
print(colorAndFormat.Beige(data.decode()))
# Forward data to client
client_socket.sendall(data)
print(colorAndFormat.Blue2("Data forwarded to client"))
print('---------------------------------')
client_socket.close()
#except
Below is the output on sending a GET request. (index.html exists)
Listening on 127.0.0.1:4444 ...
---------------------------------
Data received from client 127.0.0.1:60032
GET /index.html HTTP/1.1
Host: 127.0.0.1:4444
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:78.0) Gecko/20100101 Firefox/78.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Connection: keep-alive
Upgrade-Insecure-Requests: 1
Data forwarded to 127.0.0.1:8888
Data received from 127.0.0.1:8888
HTTP/1.0 200 OK
Server: SimpleHTTP/0.6 Python/3.8.3
Date: Tue, 17 Nov 2020 20:13:53 GMT
Content-type: text/html
Content-Length: 116
Last-Modified: Tue, 17 Nov 2020 19:49:32 GMT
Data forwarded to client
---------------------------------
Data received from client 127.0.0.1:60036
GET /favicon.ico HTTP/1.1
Host: 127.0.0.1:4444
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:78.0) Gecko/20100101 Firefox/78.0
Accept: image/webp,*/*
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Connection: keep-alive
Data forwarded to 127.0.0.1:8888
Data received from 127.0.0.1:8888
<html>
<head><title>This worksss!!</title></head>
<body>
If you're seeing this, the Proxy works!!
</body>
</html>
Data forwarded to client
---------------------------------
Data received from client 127.0.0.1:60038
GET /index.html HTTP/1.1
Host: 127.0.0.1:4444
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:78.0) Gecko/20100101 Firefox/78.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Connection: keep-alive
Upgrade-Insecure-Requests: 1
Traceback (most recent call last):
File "exposer.py", line 176, in <module>
exposer.start_listener()
File "exposer.py", line 40, in start_listener
middle_man_forw.sendall(data)
BrokenPipeError: [Errno 32] Broken pipe
Is this implementation wrong?