简体   繁体   中英

Write proxy web server using socket in python

This is my code for my seminar at university in computer network course.

Require: write a proxy web server. Receive HTTP request from the browser port 8888 and send HTTP request to web server port 80. It seems like I had trouble sending request to web server.

Could you show me my error in this situation?

Many thanks

import socket
import sys
import _thread
import traceback
import ssl
def CreateServer(host, port): 
    Server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    Server.bind((host,port))
    Server.listen(5)
    return Server

def ReadRequest(Client):
    re = ""
    Client.settimeout(10.0)
try:
    re = Client.recv(1024).decode()
    while (re):
        re = re + Client.recv(1024).decode()
except socket.timeout: # fail after 1 second of no activity
    if not re:
        print("Didn't receive data! [Timeout]")
finally:
    return re

#2. Client connect Server + 3. Read HTTP Request
def ReadHTTPRequest(Server): 
    re = ""
    while (re == ""):
        Client, address = Server.accept()
        print("Client: ", address," da ket noi toi Server")
        re = ReadRequest(Client)
    return Client,address, re

def proxy_server(webserver, port, conn, data, addr):
    print("{} {} {} {}".format(webserver, port, conn, addr))
    try:
        s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        s.settimeout(10.0)
        s.connect((webserver, port))
        s.sendall(data)
        while 1:
            reply = s.recv(1024)
            if len(reply) > 0:
                conn.send(reply)
                print("[*] Request sent: {} > {}".format(addr[0],webserver))
            else:
                break        
    
        s.close()
        conn.close()
    
    except Exception as e:
        print(e)
        traceback.print_exc()
        s.close()
        conn.close()
        sys.exit(1)

def conn_string(Client,Request,addr):
    try:
        #print(addr)
        first_line=Request.split('\n')[0]
        url=first_line.split(" ")[1]
        http_pos=url.find("://")
        if http_pos==-1:
            temp=url
        else:
            temp=url[(http_pos+3):]
        port_pos=temp.find(":")
        webserver_pos=temp.find("/")
        if webserver_pos == -1:
            webserver_pos = len(temp)
        webserver = ""
        port = -1
        if port_pos == -1 or webserver_pos < port_pos:
            port = 80
            webserver = temp[:webserver_pos]
        else:
            port = 80
            #port = int(temp[(port_pos + 1):][:webserver_pos - port_pos -1])
            webserver = temp[:port_pos]
        proxy_server(webserver,port,Client,Request.encode(),addr)
    except Exception as e:
        print (e)
        traceback.print_exc()



if __name__=="__main__":
    try:
        Server=CreateServer("",8888)
        print("[*] Intializing socket. Done.")
        print("[*] Socket binded successfully...")
        print("[*] Server started successfully [{}]".format(8888))
    except Exception as e:
        print(e)
        sys.exit(2)
    while True:
        try:
             Client,addr,Request=ReadHTTPRequest(Server)
             print("---------HTTP request: ")
             print(Request)
             _thread.start_new_thread(conn_string,(Client,Request,addr))
        except KeyboardInterrupt:
            Server.close()
            print("\n[*] Shutting down..")
            sys.exit()
    Server.close()


  [1]: https://i.stack.imgur.com/216ZO.png

You are simply forwarding the original request to the server, ie with the full URL inside the request:

GET http://ktdbcl.hcmus.edu.vn/ HTTP/1.1
Host: ktdbcl.hcmus.edu.vn
...

Instead only the path should be forwarded:

GET / HTTP/1.1
Host: ktdbcl.hcmus.edu.vn
...

Apart from that the reading of request and response is severely broken. You don't properly parse the HTTP protocol but instead simply wait some time and treat no data for some seconds as end of message. Since today multiple requests and responses will be done over the same connection your code will thus severely slow down any browsing.

Instead of waiting for multiple seconds for no data as the marker for end of request/response you should properly parse the HTTP protocol and wait for the appropriate end of request marker defined by the HTTP standard - see RFC 7230 .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM