So I'm trying to create a web proxy to intercept the browser traffic, however working with http was easy and I was able to do easily but when it comes to https I get this not informative error and I don't know what is wrong, all I can find is that the exception is triggered when this line is executed (client_socket, address) = ssl_socket.accept()
import socket
import thread
import ssl
def proxy_server():
server_scoket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# http_listener(server_scoket)
https_listener(server_scoket)
# server_scoket.close()
def https_listener(server_scoket):
ssl_socket = ssl.wrap_socket(server_scoket,keyfile='localhost.key',certfile='localhost.crt',server_side=1)
ssl_socket.bind(('127.0.0.1',9000))
ssl_socket.listen(50)
while True:
try :
(client_socket, address) = ssl_socket.accept()
thread.start_new_thread(proxy_thread, (client_socket, address))
except Exception as e:
print "Error {}".format(e)
to test the code I tried to browse to the python website : www.python.org and here is the output :
Error [SSL: HTTPS_PROXY_REQUEST] https proxy request (_ssl.c:727)
UPDATE 1 :
the full code :
import socket
import thread
import ssl
def proxy_server():
server_scoket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
http_listener(server_scoket)
# https_listener(server_scoket)
# server_scoket.close()
def https_listener(server_scoket):
context = ssl.SSLContext(ssl.PROTOCOL_TLS)
context.load_cert_chain('localhost.crt', 'localhost.key')
server_scoket.bind(('127.0.0.1',9000))
server_scoket.listen(5)
ssl_socket = context.wrap_socket(server_scoket,server_side=True)
while True:
try :
(client_socket, address) = ssl_socket.accept()
thread.start_new_thread(proxy_thread, (client_socket, address))
except Exception as e:
print "Error {}".format(e)
def http_listener(server_scoket):
try :
server_scoket.bind(('127.0.0.1',9000))
server_scoket.listen(50)
while True:
(client_socket, address) = server_scoket.accept()
thread.start_new_thread(proxy_thread, (client_socket, address))
except KeyboardInterrupt :
print "\n shutting down"
except Exception as e :
print "Error : {}".format(e)
def proxy_thread(connection, client_address):
request = connection.recv(5000)
url = request.split('\n')[0].split(' ')[1]
splited_request = request.split('\r\n\r\n')
headers = splited_request[0].split('\n')
body = splited_request[1]
port = 0
print "---------"
print request
print "---------"
splitted_url = url.split(':')
url = splitted_url[1][2:]
base_url = url.split('/')[0]
path_url = url[len(base_url):]
if (len(splitted_url) < 3):
port = 80
else:
port = splitted_url[2]
try :
splited_line = headers[0].split(' ')
if (splited_line[0] != "CONNECT"):
headers[0] = "{} {} {}".format(splited_line[0],path_url,splited_line[2])
else:
base_url = headers[0].split(' ')[1]
new_headers = ""
for index,header in enumerate(headers) :
if (index != len(headers) - 1):
headers[index] = "{}\n".format(header)
new_headers = "".join(headers)
request = "{} \r\n\r\n {}".format(new_headers,body)
if (splitted_url[0] == "https"):
https_proxy(base_url,443,request,connection)
else:
http_proxy(base_url,443,request,connection)
connection.close()
except OSError, message:
if s:
s.close()
if connection:
connection.clos()
print "Error messgae : "+ message
except Exception as e:
print "Error : {}".format(e)
def http_proxy(base_url,port,request,connection):
print "------ http request start -----"
print request
print "------ request ends -----"
print port
if(request.split(' ')[0] == 'CONNECT'):
reply = "HTTP/1.1 200 OK\r\n\r\n"
connection.sendall(reply)
print request.split(' ')[0]
print "replied HTTP/1.1 200 OK\r\n\r\n"
return
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((base_url,port))
s.sendall(request)
while True:
data = s.recv(50000)
if (len(data) > 0):
connection.sendall(data)
else:
break
s.close()
def https_proxy(base_url,port,request,connection):
print "------ https request start -----"
print request
print "------ request ends -----"
print port
sp_base_url = base_url.split(':')
base_url = sp_base_url[0] if len(sp_base_url) > 1 else base_url
context = ssl.create_default_context()
sock = socket.create_connection(("cdn.sstatic.net",443))
print port
context.load_verify_locations('/etc/ssl/certs/ca-certificates.crt')
ssock = context.wrap_socket(sock, server_hostname="cdn.sstatic.net")
print ssock.version()
ssock.sendall(request)
while True:
data = ssock.recv(5000)
if (len(data) > 0):
print data
connection.sendall(data)
else:
break
sock.close()
connection.close()
print "You can use the following proxy : \n host : 127.0.0.1 \n port : 9000 \n"
proxy_server()
the execution output :
You can use the following proxy :
host : 127.0.0.1
port : 9000
---------
CONNECT www.pythonconverter.com:443 HTTP/1.1
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:68.0) Gecko/20100101 Firefox/68.0
Proxy-Connection: keep-alive
Connection: keep-alive
Host: www.pythonconverter.com:443
---------
------ http request start -----
CONNECT www.pythonconverter.com:443 HTTP/1.1
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:68.0) Gecko/20100101 Firefox/68.0
Proxy-Connection: keep-alive
Connection: keep-alive
Host: www.pythonconverter.com:443
------ request ends -----
443
CONNECT
replied HTTP/1.1 200 OK
but then from my understanding I should get a new connection or at least a request on the same socket from the browser, however that does not happen !
Related
if i running this code in console, it running an got response from the server, but it doesn't running and get null response while trying write that code in Odoo addons
xml_data = xml_formatter()
if xml_data != 'pas':
content_length = len(xml_data)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
request = '''
POST /{service} HTTP/1.1
Content-Type: text/xml
Content-Length: {content_length}
{xml}'''.format(service=service, xml=xml_data, content_length=content_length)
if bytes != str: # Testing if is python2 or python3
request = bytes(request, 'utf-8')
buffer = b""
try:
client.connect((target_host, target_port))
try:
client.send(request)
while True:
chunk = client.recv(2048)
if len(chunk) == 0:
break
buffer = buffer + chunk
except socket.error as msg:
_logger.error("Caught exception socket.error : %s" %msg )
finally:
client.close()
except socket.error as msg:
_logger.error("Caught exception socket.error : %s" %msg )
else:
print('NAH!')
I created a HTTP proxy using this tutorial https://null-byte.wonderhowto.com/how-to/sploit-make-proxy-server-python-0161232/.
I am using this proxy with firefox browser. When I open a website in browser. The connection between firefox-proxy and proxy-webserver is successful and the proxy successfully receives data from webserver. But when I sent the data back to browser it doesn't render any page (I don't see webpage in browser). What may be the issue here ?
import socket, sys
from thread import *
try:
listening_port = int(raw_input("[*] Enter Listening Port Number: "))
except KeyboardInterrupt:
print "\n[*] User Requested An Interrupt"
print "[*] Application Exiting ..."
sys.exit()
max_conn = 20 #Max Connections in Queue
buffer_size = 262144 # Max socket Buffer size
def start():
try:
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # initiates socket
s.bind(('', listening_port)) # Bind socket for listen
s.listen(max_conn) # start listening for incoming connections
print "[*] Initializing Sockets ... Done"
print "[*] Sockets Binded succesfully ..."
print("[*] Server started succesfully [ %d ]\n" % (listening_port))
except Exception, e:
print "[*] Unable to initialize socket", e
sys.exit(2)
while 1:
try:
conn, addr = s.accept() # Accept connection From client browser
print "Connection accepted from browser"
data = conn.recv(buffer_size) # Receive CLient Data
print "Received request from browser"
start_new_thread(conn_string, (conn, data, addr)) # start a thread
except KeyboardInterrupt:
print "\n[*] Proxy Server Shutting down ..."
sys.exit(1)
s.close()
def conn_string(conn, data, addr):
# Client Browser Request Appears Here
try:
first_line = data.split('\n')[0]
url = first_line.split(' ')[1]
print "URL ", url
http_pos = url.find("://") # find the position of ://
if (http_pos == -1):
temp = url
else:
temp = url[(http_pos+3):] # get the rest of the URL
print "http pos, Temp", http_pos, temp
port_pos = temp.find(":") # Find the postion of port (if any)
webserver_pos = temp.find("/") # Find the end of the web server
if webserver_pos == -1:
webserver_pos = len(temp)
webserver = ""
port = -1
#print "Port pos, webserver_pos", port_pos, webserver_pos
if (port_pos == -1 or webserver_pos < port_pos): # default port
port = 80
webserver = temp[:webserver_pos]
else:
# Specific port
port = int((temp[(port_pos+1):])[:webserver_pos-port_pos-1])
webserver = temp[:port_pos]
# print "WEB server", webserver
print "Data extracted from request Request"
proxy_server(webserver, port, conn, addr, data)
except Exception, e:
pass
def proxy_server(webserver, port, conn, addr, data):
try:
print "starting connection towebserver"
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
#print "connecing host", webserver, port
s.connect((webserver, port))
print "connected"
#print "data", data
s.send(data)
print "Request sent"
while 1:
# Read reply or data to from end web server
reply = s.recv(buffer_size)
print "Reply Received ", reply
if (len(reply) > 0):
conn.send(reply) # send reply back to client
# Send notification to proxy Server [script itself]
dar = float(len(reply))
dar = float(dar / 1024)
dar = "%.3s" % (str(dar))
dar = "%s KB" % (dar)
print "[*] Request Done: %s => %s <=" % (str(addr[0]), str(dar))
else:
break
s.close()
conn.close()
print "Conn CLosed ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++"
except socket.error, (value, message):
print "Error", message
s.close()
conn.close()
sys.exit(1)
start()
I'm trying to create a HTTP proxy with Python.
Although, when I configure my browser with this proxy and try to connect to a http website, the loading is very slow.
This is my proxy code :
#!/usr/bin/env python
import socket
import thread
import sys
def get_line(field, data) :
lines = data.split("\n")
for line in lines :
if line.split(":")[0] == field :
return line
return ""
def get_host(data) :
host_line = get_line("Host", data);
port = 80
if len(host_line.split(" ")) > 1 :
host = host_line.split(" ")[1]
arr = host.split(":")
if len(arr) > 1 :
host = arr[0]
port = arr[1]
else :
host = host[:-1]
else :
host = ""
port = 0
return (host, port)
def http_proxy(conn, data, client_addr) :
(host, port) = get_host(data)
if host != "" :
try :
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((socket.gethostbyname(host), int(port)))
s.send(data)
while 1 :
reply = s.recv(8192)
test = reply
if (len(reply) > 0) :
conn.send(reply)
print "Send %d bytes from %s" % (len(reply), host)
else :
conn.close()
s.close()
break
except socket.error, (value, message) :
s.close()
conn.close()
print value, message
sys.exit(1)
def main():
try :
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind(('', 8080))
s.listen(100)
except socket.error, (value, message) :
if s :
s.close()
print "Socket error : ", message
while 1 :
conn, client_addr = s.accept()
data = conn.recv(8192)
thread.start_new_thread(http_proxy, (conn, data, client_addr))
s.close()
if __name__ == "__main__" :
main()
I think these delays are caused by the fact that some HTTP requests are not taken into account by my proxy, so the browser waits a certain time before sending them back.
If that's the problem, I don't understand why that happens.
I entered http://127.0.0.1:443/www.google.com and I got 'Illegal request' on the command prompt.
It doesn't work from connecting to port 80 in that code.
what is wrong and How can I get this web site using proxy server?
(I already set proxy setting of internet browser-127.0.0.1 (ip), 443(port)
` Hello.py
from socket import *
import sys
from idlelib.rpc import response_queue
if len(sys.argv) <= 1:
print ('Usage : "python ProxyServer.py server_ip"\n [server_ip : It is the IP Address Of Proxy Server')
sys.exit(2)
# Create a server socket, bind it to a port and start listening
tcpSerSock = socket(AF_INET, SOCK_STREAM)
port = 443
max_connections = 2
tcpSerSock = socket(AF_INET, SOCK_STREAM)
tcpSerSock.bind((sys.argv[1],port))
tcpSerSock.listen(max_connections)
while 1:
# Start receiving data from the client
print ('Ready to serve...')
tcpCliSock, addr = tcpSerSock.accept()
print ('Received a connection from:', addr)
message = tcpCliSock.recv(1024)
print ('Msg: ' ,message)
# Extract the filename from the given message
print ('Msg decoded: ', message.decode().split()[1])
filename = message.decode().split()[1].partition("/")[2]
print ('File name: ', filename)
fileExist = "false"
filetouse = "/" + filename
print ('File touse: ', filetouse)
try:
# Check whether the file exist in the cache
f = open(filetouse[1:], "r")
outputdata = f.readlines()
fileExist = "true"
print ('File exists')
# ProxyServer finds a cache hit and generates a response message
tcpCliSock.send("HTTP/1.0 200 OK\r\n")
tcpCliSock.send("Content-Type:text/html\r\n")
resp = ""
for s in outputdata:
resp += s
tcpCliSock.send(resp)
print ('Read from cache')
# Error handling for file not found in cache
except IOError:
if fileExist == "false":
# Create a socket on the proxy server
c = socket(AF_INET, SOCK_STREAM)
hostn = filename.replace("www.","",1)
print ('File doesn\'t exist')
print (hostn)
try:
# Connect to the socket to port 80
c.connect((hostn, 80))
# Create a temporary file on this socket and ask port 80
# for the file requested by the client
fileobj = c.makefile('r', 0)
fileobj.write("GET " + "http://" + filename + " HTTP/1.0\n\n")
# Read the response into buffer
resp = c.recv(4096)
response = ""
while resp:
response += resp
resp = c.recv(4096)
# Create a new file in the cache for the requested file.
# Also send the response in the buffer to client socket and the corresponding file in the cache
tmpFile = open("./" + filename,"w")
tmpFile.write(response)
tmpFile.close()
tcpCliSock.close()
except:
print ("Illegal request")
else:
# HTTP response message for file not found
pass
# Close the client and the server sockets
tcpCliSock.close()`
I try to do simple async http client with asyncore:
This code works fine and output is (fast enought):
www.gmail.com : recv http code: 301
www.yandex.ru : recv http code: 200
www.python.org : recv http code: 200
www.google.ru : recv http code: 200
www.gravatar.com : recv http code: 302
www.com.com : recv http code: 302
www.yahoo.com : recv http code: 302
www.bom.com : recv http code: 301
But than i uncomment line with not exist host:
#c = AsyncHTTP('http://www.no-such-host.ru') #!this line breaks execution!
The execution breaks, code hangs for some time, output part of data and hangs with no last data output:
connection error: [Errno -5] No address associated with hostname
www.gmail.com : recv http code: 301
www.yandex.ru : recv http code: 200
www.yahoo.com : recv http code: 302
www.com.com : recv http code: 302
www.bom.com : recv http code: 301
www.gravatar.com : recv http code: 302
...
some hosts are lost here and long delay at start.
Why this happen and how to fix this?
# coding=utf-8
import asyncore
import string, socket
import StringIO
import mimetools, urlparse
class AsyncHTTP(asyncore.dispatcher):
# HTTP requestor
def __init__(self, uri):
asyncore.dispatcher.__init__(self)
self.uri = uri
# turn the uri into a valid request
scheme, host, path, params, query, fragment = urlparse.urlparse(uri)
assert scheme == "http", "only supports HTTP requests"
try:
host, port = string.split(host, ":", 1)
port = int(port)
except (TypeError, ValueError):
port = 80 # default port
if not path:
path = "/"
if params:
path = path + ";" + params
if query:
path = path + "?" + query
self.request = "GET %s HTTP/1.0\r\nHost: %s\r\n\r\n" % (path, host)
self.host = host
self.port = port
self.status = None
self.header = None
self.http_code = None
self.data = ""
# get things going!
self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
#self.connect((host, port))
#return
try:
self.connect((host, port))
except Exception,e:
self.close()
self.handle_connect_expt(e)
def handle_connect(self):
self.send(self.request)
def handle_expt(self):
print "handle_expt error!"
self.close()
def handle_error(self):
print "handle_error error!"
self.close()
def handle_connect_expt(self,expt):
print "connection error:",expt
def handle_code(self):
print self.host," : ","recv http code: ",self.http_code
def handle_read(self):
data = self.recv(2048)
#print data
if not self.header:
self.data = self.data + data
try:
i = string.index(self.data, "\r\n\r\n")
except ValueError:
return # continue
else:
# parse header
fp = StringIO.StringIO(self.data[:i+4])
# status line is "HTTP/version status message"
status = fp.readline()
self.status = string.split(status, " ", 2)
self.http_code = self.status[1]
self.handle_code()
# followed by a rfc822-style message header
self.header = mimetools.Message(fp)
# followed by a newline, and the payload (if any)
data = self.data[i+4:]
self.data = ""
#header recived
#self.close()
def handle_close(self):
self.close()
c = AsyncHTTP('http://www.python.org')
c = AsyncHTTP('http://www.yandex.ru')
c = AsyncHTTP('http://www.google.ru')
c = AsyncHTTP('http://www.gmail.com')
c = AsyncHTTP('http://www.gravatar.com')
c = AsyncHTTP('http://www.yahoo.com')
c = AsyncHTTP('http://www.com.com')
c = AsyncHTTP('http://www.bom.com')
#c = AsyncHTTP('http://www.no-such-host.ru') #!this line breaks execution!
asyncore.loop()
ps: My system ubuntu 11.10 + python 2.7.2
You invoke a blocking name-resolution when you do self.connect((host, port)). Combined with your local DNS configuration, this is why your program has a long delay at startup.
An alternative to asyncore and figuring out how to do non-blocking name resolution yourself, you might think about using Twisted. Twisted's TCP connection setup API (mainly reactor.connectTCP or one of the APIs built on top of it) does not block. So a naive use of it will remain properly asynchronous.