侯体宗的博客
  • 首页
  • Hyperf版
  • beego仿版
  • 人生(杂谈)
  • 技术
  • 关于我
  • 更多分类
    • 文件下载
    • 文字修仙
    • 中国象棋ai
    • 群聊
    • 九宫格抽奖
    • 拼图
    • 消消乐
    • 相册

Python代码实现http/https代理服务器的脚本

Python  /  管理员 发布于 7年前   166

一个几百行代码做出http/https代理服务器的脚本,启动即可做http https透明代理使用

python proxy.py 8992

使用非阻塞io模式,性能还可以。

可以和浏览器一样保持长连接,代码有点乱,不管那么多了能跑就行

几百行代码做出http/https代理服务器代码片段

*1. * [代码] [Python]代码

#!/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, params, 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, params, nextfd)   else: # nextfd    if not "writedata" in next_param or len(next_param["writedata"]) == 0:     clearfdpro(epoll_fd, params, nextfd)    else:     next_param["sendandclose"] = "true"  clearfdpro(epoll_fd, params, 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]36a0   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, host, 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(), host, port, 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,port],"writelen":0, "connections":nextfd, "time":cur_time, "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,params,fd)def process_datas(process_status, params, param, epoll_fd, datas, read_len, fd, cur_time): if process_status == "close":  clearfd(epoll_fd,params,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,host_s,host_e,host,port,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,port,addr[0],addr[1])      need_connect = True      del param["nextfd"]      del next_param["nextfd"]      clearfd(epoll_fd,params,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,host_s,host_e,host,port,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, param, epoll_fd, datas, fd, cur_time, host, 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,params,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, socket.SO_REUSEADDR, 1)      #conn.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, True)      params[conn.fileno()] = {"addr":addr,"writelen":0, "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, params, param, epoll_fd, datas, read_len, fd, cur_time)   elif select.EPOLLHUP & events or select.EPOLLERR & events:    clearfd(epoll_fd,params,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,params,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,params,fd)       break     except socket.error, msg:      if msg.errno == errno.EAGAIN:       param["writelen"] = sendLen       break      clearfd(epoll_fd,params,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,params,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, socket.SOCK_STREAM, 0) except socket.error, msg:  logger.error("create socket failed") try:  listen_fd.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 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)

总结

以上所述是小编给大家介绍的Python代码实现http/https代理服务器,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对站的支持!
如果你觉得本文对你有帮助,欢迎转载,烦请注明出处,谢谢!


  • 上一条:
    Python简易版停车管理系统
    下一条:
    Python简易版图书管理系统
  • 昵称:

    邮箱:

    0条评论 (评论内容有缓存机制,请悉知!)
    最新最热
    • 分类目录
    • 人生(杂谈)
    • 技术
    • linux
    • Java
    • php
    • 框架(架构)
    • 前端
    • ThinkPHP
    • 数据库
    • 微信(小程序)
    • Laravel
    • Redis
    • Docker
    • Go
    • swoole
    • Windows
    • Python
    • 苹果(mac/ios)
    • 相关文章
    • 在python语言中Flask框架的学习及简单功能示例(0个评论)
    • 在Python语言中实现GUI全屏倒计时代码示例(0个评论)
    • Python + zipfile库实现zip文件解压自动化脚本示例(0个评论)
    • python爬虫BeautifulSoup快速抓取网站图片(1个评论)
    • vscode 配置 python3开发环境的方法(0个评论)
    • 近期文章
    • 智能合约Solidity学习CryptoZombie第三课:组建僵尸军队(高级Solidity理论)(0个评论)
    • 智能合约Solidity学习CryptoZombie第二课:让你的僵尸猎食(0个评论)
    • 智能合约Solidity学习CryptoZombie第一课:生成一只你的僵尸(0个评论)
    • 在go中实现一个常用的先进先出的缓存淘汰算法示例代码(0个评论)
    • 在go+gin中使用"github.com/skip2/go-qrcode"实现url转二维码功能(0个评论)
    • 在go语言中使用api.geonames.org接口实现根据国际邮政编码获取地址信息功能(1个评论)
    • 在go语言中使用github.com/signintech/gopdf实现生成pdf分页文件功能(0个评论)
    • gmail发邮件报错:534 5.7.9 Application-specific password required...解决方案(0个评论)
    • 欧盟关于强迫劳动的规定的官方举报渠道及官方举报网站(0个评论)
    • 在go语言中使用github.com/signintech/gopdf实现生成pdf文件功能(0个评论)
    • 近期评论
    • 122 在

      学历:一种延缓就业设计,生活需求下的权衡之选中评论 工作几年后,报名考研了,到现在还没认真学习备考,迷茫中。作为一名北漂互联网打工人..
    • 123 在

      Clash for Windows作者删库跑路了,github已404中评论 按理说只要你在国内,所有的流量进出都在监控范围内,不管你怎么隐藏也没用,想搞你分..
    • 原梓番博客 在

      在Laravel框架中使用模型Model分表最简单的方法中评论 好久好久都没看友情链接申请了,今天刚看,已经添加。..
    • 博主 在

      佛跳墙vpn软件不会用?上不了网?佛跳墙vpn常见问题以及解决办法中评论 @1111老铁这个不行了,可以看看近期评论的其他文章..
    • 1111 在

      佛跳墙vpn软件不会用?上不了网?佛跳墙vpn常见问题以及解决办法中评论 网站不能打开,博主百忙中能否发个APP下载链接,佛跳墙或极光..
    • 2016-10
    • 2016-11
    • 2018-04
    • 2020-03
    • 2020-04
    • 2020-05
    • 2020-06
    • 2022-01
    • 2023-07
    • 2023-10
    Top

    Copyright·© 2019 侯体宗版权所有· 粤ICP备20027696号 PHP交流群

    侯体宗的博客