400行python 实现httphttps 代理服务器

400行python 实现httphttps 代理服务器,第1张

概述400行python 实现http/https 代理服务器

下面是内存溢出 jb51.cc 通过网络收集整理的代码片段。

内存溢出小编现在分享给大家,也给大家做个参考。

#!/usr/bin/python#-*- Coding:utf-8 -*-import socket,loggingimport select,errnoimport osimport sysimport tracebackimport gzipfrom StringIO import StringIOimport Queueimport threadingimport timeimport threadimport cgifrom cgi import parse_qsimport Jsonimport impfrom os.path import join,getsizeimport reimport ssl##################user config ##################logger = logging.getLogger("network-server")#############################################def getTraceStackMsg():    tb = sys.exc_info()[2]    msg = ''    for i in traceback.format_tb(tb):        msg += i    return msgdef InitLog():    logger.setLevel(logging.DEBUG)    fh = logging.fileHandler("network-server.log")    fh.setLevel(logging.DEBUG)    ch = logging.StreamHandler()    ch.setLevel(logging.ERROR)    formatter = logging.Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s")    ch.setFormatter(formatter)    fh.setFormatter(formatter)    logger.addHandler(fh)    logger.addHandler(ch)def clearfdpro(epoll_fd,params,fd):    try:        fd_check = int(fd)    except Exception,e:        print "fd error"        sys.exit(1)    try:        #print "pID:%s,close fd:%s" % (os.getpID(),fd)        epoll_fd.unregister(fd)    except Exception,e:        #print str(e)+getTraceStackMsg()        pass    try:        param = params[fd]        try:            addr = param["addr"]            if "next" in param:                print "close sock,%s:%s" % (addr[0],addr[1])        except Exception,e:            pass        param["connections"].shutdown(socket.SHUT_RDWR)        param["connections"].close()        f = param.get("f",None)        if f != None:            f.close()        rc = param.get("rc",None)        if rc != None:            rc.close()        if "read_cache_name" in param:            os.remove(param["read_cache_name"])    except Exception,e:        #print str(e)+getTraceStackMsg()        pass    try:        del params[fd]        #logger.error(getTraceStackMsg())        #logger.error("clear fd:%s" % fd)    except Exception,e:        #print str(e)+getTraceStackMsg()        passdef clearfd(epoll_fd,fd):    try:        param = params[fd]        if "nextfd" in param:            nextfd = param["nextfd"]            next_param = params[nextfd]            del param["nextfd"]            del next_param["nextfd"]            if not "next" in param: #masterfd                clearfdpro(epoll_fd,nextfd)            else: # nextfd                if not "writedata" in next_param or len(next_param["writedata"]) == 0:                    clearfdpro(epoll_fd,nextfd)                else:                    next_param["sendandclose"] = "true"        clearfdpro(epoll_fd,fd)    except Exception,e:        #print str(e)+getTraceStackMsg()        passdef FindHostPort(datas):    host_s = -1    host_e = -1    host_str = None    host = ""    port = ""    if not datas.startswith("CONNECT"):        host_s = datas.find("Host:")        if host_s < 0:            host_s = datas.find("host:")        if host_s > 0:            host_e = datas.find("\r\n",host_s)        if host_s > 0 and host_e > 0:            host_str = datas[host_s+5:host_e].strip()            add_List = host_str.split(":")            if len(add_List) == 2:                host = add_List[0]                port = add_List[1]            else:                host = add_List[0]                port = 80            first_seg = datas.find("\r\n")            first_line = datas[0:first_seg]            first_line = first_line.replace(" http://%s" % host_str," ")            datas = first_line + datas[first_seg:]    else:        first_seg = datas.find("\r\n")        head_e = datas.find("\r\n\r\n")        if first_seg > 0 and head_e > 0:            first_line = datas[0:first_seg]            com,host_str,http_version = re.split('\s+',first_line)            add_List = host_str.split(":")            if len(add_List) == 2:                host = add_List[0]                port = add_List[1]            else:                host = add_List[0]                port = 443            host_s = 1            host_e = 1    return host_str,host_s,host_e,host,port,datasdef connect_pro(params,param,epoll_fd,datas,fd,cur_time,port):    try:        nextfd = socket.socket(socket.AF_INET,socket.soCK_STREAM,0)        nextfd.setsockopt(socket.soL_SOCKET,socket.so_REUSEADDR,1)        nextfd.settimeout(5)        try:            nextfd.connect((host,int(port)))        except Exception,e:            print "########%s,%s connect fail" % (host,port)        nextfd.setblocking(0)        next_fileno = nextfd.fileno()        print "pID:%s,connect %s:%s fd:%s" % (os.getpID(),next_fileno)        if next_fileno in params:            print "fileno exist"            sys.exit(1)        if not datas.startswith("CONNECT"):            next_param = {"addr":[host,port],"writelen":0,"connections":nextfd,"time":cur_time,"nextfd":fd}            param["nextfd"] = next_fileno            next_param["writedata"] = datas            next_param["writelen"] = 0            next_param["next"] = "true"            param["read_len"] = 0            param["readdata"] = ""            params[next_fileno] = next_param            epoll_fd.register(next_fileno,select.EPolliN | select.EPolLOUT | select.EPolLERR | select.EPolLHUP)            epoll_fd.modify(fd,select.EPolliN | select.EPolLERR | select.EPolLHUP)        else:            next_param = {"addr":[host,"nextfd":fd}            param["nextfd"] = next_fileno            next_param["next"] = "true"            params[next_fileno] = next_param            epoll_fd.register(next_fileno,select.EPolliN | select.EPolLERR | select.EPolLHUP)            param["read_len"] = 0            param["readdata"] = ""            param["writedata"] = "http/1.1 200 Connection Established\r\nConnection: close\r\n\r\n"            param["writelen"] = 0            param["reuse"] = "true"            epoll_fd.modify(fd,select.EPolliN | select.EPolLOUT | select.EPolLERR | select.EPolLHUP)    except socket.error,msg:        clearfd(epoll_fd,fd)def process_datas(process_status,read_len,cur_time):    if process_status == "close":        clearfd(epoll_fd,fd)    else:        need_connect = False        host_str = None        host_s = -1        host_e = -1        if "reuse" in param and "next" not in param:            if not datas.startswith("CONNECT") and \                    not datas.startswith("GET") and \                    not datas.startswith("POST") and \                    not datas.startswith("PUT"):                del param["reuse"]            else:                host_str,datas = FindHostPort(datas)                host_s = int(host_s)                host_e = int(host_e)                next_fileno = param["nextfd"]                next_param = params[next_fileno]                addr = next_param["addr"]                if host_s > 0 and host_e > 0:                    if host != addr[0] or str(port) != str(addr[1]):                        print "%s,%s neq %s,%s" % (host,addr[0],addr[1])                        need_connect = True                        del param["nextfd"]                        del next_param["nextfd"]                        clearfd(epoll_fd,next_fileno)                    del param["reuse"]                else:                    param["read_len"] = read_len                    param["readdata"] = datas                    return None        if need_connect or not "nextfd" in param:            if host_str == None or not host_s > 0 or not host_e > 0:                host_str,datas = FindHostPort(datas)                host_s = int(host_s)                host_e = int(host_e)            if host_s > 0 and host_e > 0:                if not datas.startswith("CONNECT"):                    epoll_fd.modify(fd,select.EPolLERR | select.EPolLHUP) # 简单处理,http连接时把读去掉,避免内存攻击                thread.start_new_thread(connect_pro,(params,port))            else:                param["read_len"] = read_len                param["readdata"] = datas        else:            next_fileno = param["nextfd"]            next_param = params[next_fileno]            if "next" in param:                next_param["reuse"] = "true"            write_data = next_param.get("writedata","")            write_data += datas            next_param["writedata"] = write_data            param["read_len"] = 0            param["readdata"] = ""            epoll_fd.modify(next_fileno,select.EPolliN | select.EPolLOUT | select.EPolLERR | select.EPolLHUP)        if process_status == "close_after_process":            print "close after process"            clearfd(epoll_fd,fd)def run_main(Listen_fd):    try:        epoll_fd = select.epoll()        epoll_fd.register(Listen_fd.fileno(),select.EPolliN | select.EPolLERR | select.EPolLHUP)        print "Listen_fd:%s" % Listen_fd.fileno()    except select.error,msg:        logger.error(msg)    params = {}    last_min_time = -1    while True:        epoll_List = epoll_fd.poll()        cur_time = time.time()        for fd,events in epoll_List:            if fd == Listen_fd.fileno():                while True:                    try:                        conn,addr = Listen_fd.accept()                        conn.setblocking(0)                        epoll_fd.register(conn.fileno(),select.EPolliN | select.EPolLERR | select.EPolLHUP)                        conn.setsockopt(socket.soL_SOCKET,1)                        #conn.setsockopt(socket.IPPROTO_TCP,socket.TCP_NODELAY,True)                        params[conn.fileno()] = {"addr":addr,"connections":conn,"time":cur_time}                    except socket.error,msg:                        break            elif select.EPolliN & events:                param = params.get(fd,None)                if param == None:                    continue                param["time"] = cur_time                datas = param.get("readdata","")                cur_sock = params[fd]["connections"]                read_len = param.get("read_len",0)                process_status = "close"                while True:                    try:                        data = cur_sock.recv(102400)                        if not data:                            if datas == "":                                break                            else:                                raise Exception("close after process")                        else:                            datas += data                            read_len += len(data)                    except socket.error,msg:                        if msg.errno == errno.EAGAIN:                            process_status = "process"                            break                        else:                            break                    except Exception,e:                        process_status = "close_after_process"                        break                process_datas(process_status,cur_time)            elif select.EPolLHUP & events or select.EPolLERR & events:                clearfd(epoll_fd,fd)                logger.error("sock: %s error" % fd)            elif select.EPolLOUT & events:                param = params.get(fd,None)                if param == None:                    continue                param["time"] = cur_time                sendLen = param.get("writelen",0)                writedata = param.get("writedata","")                total_write_len = len(writedata)                cur_sock = param["connections"]                f = param.get("f",None)                totalsenlen = param.get("totalsenlen",None)                if writedata == "":                    clearfd(epoll_fd,fd)                    continue                while True:                    try:                        sendLen += cur_sock.send(writedata[sendLen:])                        if sendLen == total_write_len:                            if f != None and totalsenlen != None:                                readmorelen = 102400                                if readmorelen > totalsenlen:                                    readmorelen = totalsenlen                                morefiledata = ""                                if readmorelen > 0:                                    morefiledata = f.read(readmorelen)                                if morefiledata != "":                                    writedata = morefiledata                                    sendLen = 0                                    total_write_len = len(writedata)                                    totalsenlen -= total_write_len                                    param["writedata"] = writedata                                    param["totalsenlen"] = totalsenlen                                    continue                                else:                                    f.close()                                    del param["f"]                                    del param["totalsenlen"]                            if not "sendandclose" in param:                                param["writedata"] = ""                                param["writelen"] = 0                                epoll_fd.modify(fd,select.EPolliN | select.EPolLERR | select.EPolLHUP)                            else:                                clearfd(epoll_fd,fd)                            break                    except socket.error,msg:                        if msg.errno == errno.EAGAIN:                            param["writelen"] = sendLen                            break                        clearfd(epoll_fd,fd)                        break            else:                continue        #check time out        if cur_time - last_min_time > 20:            last_min_time = cur_time            obJs = params.items()            for (key_fd,value) in obJs:                fd_time = value.get("time",0)                del_time = cur_time - fd_time                if del_time > 20:                    clearfd(epoll_fd,key_fd)                elif fd_time < last_min_time:                    last_min_time = fd_timeif __name__ == "__main__":    reload(sys)    sys.setdefaultencoding('utf8')    InitLog()    port = int(sys.argv[1])    try:        Listen_fd = socket.socket(socket.AF_INET,0)    except socket.error,msg:        logger.error("create socket Failed")    try:        Listen_fd.setsockopt(socket.soL_SOCKET,1)    except socket.error,msg:        logger.error("setsocketopt SO_REUSEADDR Failed")    try:        Listen_fd.bind(('',port))    except socket.error,msg:        logger.error("bind Failed")    try:        Listen_fd.Listen(10240)        Listen_fd.setblocking(0)    except socket.error,msg:        logger.error(msg)    child_num = 19    c = 0    while c < child_num:        c = c + 1        newpID = os.fork()        if newpID == 0:            run_main(Listen_fd)    run_main(Listen_fd)

以上是内存溢出(jb51.cc)为你收集整理的全部代码内容,希望文章能够帮你解决所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

总结

以上是内存溢出为你收集整理的400行python 实现http/https 代理服务器全部内容,希望文章能够帮你解决400行python 实现http/https 代理服务器所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/1198825.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-06-03
下一篇 2022-06-03

发表评论

登录后才能评论

评论列表(0条)

保存