Http/Https代理Python实现

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

对Python感兴趣,工作之余,参照部分文档初步实现了HTTP/HTTPs代理。(代码比较凌乱,各位留情。大笑

使用Fiddler调试。

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

import socket

import time

import threading
BUFSIZE=1024


class Access_to_Host(object):
         
    def handler(self,conn,addr):
        self.conn=conn
        self.addr=addr
        all_src_data,hostname,port,ssl_flag=self.get_dst_host_from_header(self.conn,self.addr)
        all_dst_data=self.get_data_from_host(hostname,port,all_src_data,ssl_flag)


        if  all_dst_data and not ssl_flag:
            #self.send_data_to_client(self.conn,all_dst_data)
            self.ssl_client_server_client(self.conn,self.conn_dst,all_dst_data)
        elif ssl_flag:
            sample_data_to_client=b"HTTP/1.0 200 Connection Established\r\n\r\n"
           # print("\nSSL_Flag-1")
            #self.send_data_to_client(self.conn,all_dst_data)
            #print("SSL_Flag-2")
            self.ssl_client_server_client(self.conn,self.conn_dst,sample_data_to_client)
            #print("\nSSL_Flag-3")
        else:
            print('pls check network. cannot get hostname:'+hostname)
        #self.conn.close()
    def ssl_client_server(self,src_conn,dst_conn):
        self.src_conn=src_conn
        self.dst_conn=dst_conn        
        while True:
            ###get data from client
            try:
                ssl_client_data=self.src_conn.recv(BUFSIZE)
            except Exception as e:
                print("client disconnct ")
                print(e)
                self.src_conn.close()
                #self.dst_conn.close()
                return False
            
            if ssl_client_data:
                #####send data to server
                try:
                    self.dst_conn.sendall(ssl_client_data)
                except Exception as e:
                    print("server disconnct Err")
                    self.dst_conn.close()
                    return False
            else:
                self.src_conn.close()
                return False
            
    def ssl_server_client(self,src_conn,dst_conn):
        self.src_conn=src_conn
        self.dst_conn=dst_conn
        
        while True:
            ###get data from server
            try:
                ssl_server_data=self.dst_conn.recv(BUFSIZE)
            except Exception as e:
                print("server disconnct ")
                self.dst_conn.close()
                return False
                            
            if ssl_server_data:
                #####send data to client
                try:
                    self.src_conn.sendall(ssl_server_data)
                except Exception as e:
                    print("Client disconnct Err")
                    self.src_conn.close()
                    return False
            else:
                self.dst_conn.close()
                return False
                                    
        
    def ssl_client_server_client(self,src_conn,dst_conn,all_dst_data):
        self.src_conn=src_conn
        self.dst_conn=dst_conn
        try:
            #print(all_dst_data)
            self.src_conn.sendall(all_dst_data)
        except Exception as e:
            print(e)
            print("cannot sent data(HTTP/1.0 200) to SSL client")
            return False
        threadlist=[]


        t1=threading.Thread(target=self.ssl_client_server,args=(self.src_conn,self.dst_conn))
        t2=threading.Thread(target=self.ssl_server_client,args=(self.src_conn,self.dst_conn))
        threadlist.append(t1)
        threadlist.append(t2)
        for t in threadlist:
            t.start()
        #t.join()
            ######线程控制,等待线程结束后,远程主机关闭socket后,客户端到主机的socket也不需要再做任何操作了。
        while not self.dst_conn._closed:
            time.sleep(1)
        self.src_conn.close()


        
    def get_src_client(self):
        self.src_ip=self.s_src.getpeername()
        return  self.src_ip
        
    def send_data_to_client(self,conn_src,data):
        self.conn_src=conn_src
        try:
            self.conn_src.sendall(data)
        except Exception as e:
            print(e)
            print("cannot sent data to client")
            return False
        #self.conn_dst.close()
            
    def get_dst_host_from_header(self,conn_sock,addr):
        
        self.s_src=conn_sock
        self.addr=addr
        header=""
        ssl_flag=False
        while True:
            #print("Loop Loop Loop")
            header=self.s_src.recv(BUFSIZE)
            if header :
                #####header的一行含有CONNECT,即为SSL(HTTPS)
                indexssl=header.split(b"\n")[0].find(b"CONNECT")
               # print("indexsll:"+str(indexssl))
                if indexssl>-1:
                    #####CONNECT===7  +8 前面一个空格
                    hostname=str(header.split(b"\n")[0].split(b":")[0].decode())
                    hostname=hostname[indexssl+8:]
                    port=443
                    ssl_flag=True
                    return header,hostname,port,ssl_flag
                index1=header.find(b"Host:")
                index2=header.find(b"GET http")
                index3=header.find(b"POST http")
                if index1>-1:
                    indexofn=header.find(b"\n",index1)
                    ##host:===5
                    host=header[index1+5:indexofn]
                elif index2>-1 or index3>-1:
                    ###no host sample :'GET http://saxn.sina.com.cn/mfp/view?......
                    host=header.split(b"/")[2]
                else:                        
                    print("src socket host:")
                    print(self.s_src.getpeername())
                    print("cannot find out host!!:"+repr(header))
                    return 
                break
        host=str(host.decode().strip("\r").lstrip())
        if len(host.split(":"))==2:
            port=host.split(":")[1]
            hostname=host.split(":")[0].strip("")
        else:
            port=80
            hostname=host.split(":")[0].strip("")
        ssl_flag=False
        return header,hostname,int(port),ssl_flag


    def get_data_from_host(self,host,port,sdata,ssl_flag):
        self.conn_dst=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
        all_dst_data=""
        try:
            self.conn_dst.connect((str(host),port))
        except Exception as e:
            print(e)
            print("get_data_from_host: cannot get host:"+host)
            self.conn_dst.close()
            return False
        #con_string="("+server+","+port+")"
        ############https只建立链接
        try:
            if ssl_flag:
                return all_dst_data
            else:
                self.conn_dst.sendall(sdata)
        except Exception as e:
            print(e)
            print("cannot send data to host:"+host)
            self.conn_dst.close()
            return False
       # buffer=[]
        rc_data=self.conn_dst.recv(BUFSIZE)
        #####剩下的data交给线程去获取
        return rc_data


         
class Server(object):


    def Handle_Rec(conn_socket,addr):
        print("This is Handler Fun")
        pass
    
    def __init__(self,host,port):
        print("Server starting......")
        self.host=host
        self.port=port
        self.s_s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
        self.s_s.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
        self.s_s.bind((host,port))
        self.s_s.listen(20)


    def start(self):
        while True:
            try:
                conn,addr=self.s_s.accept()
                threading.Thread(target=Access_to_Host().handler,args=(conn,addr)).start()
            except Exception  as e:
                print(str(e))
                print("\nExcept happend")




          
if  __name__=="__main__":
    svr=Server("127.0.0.1",8080)
    svr.start()

  • 4
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 11
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值