Python简单实现HTTP本地代理转发

1.需要了解知识

  1. socket模块

    Fiddler工具HTTP抓包的原理就是设置本地代理然后,获取请求报文—转发报文----获取服务器返回值—请求报文…的一系列操作,前提是设置浏览器的本地代理IP和端口号,一般代理IP都设置为127.0.0.1,端口为8080。IE浏览器中设置代理位置:Internet选项----连接----局域网设置–取消自动检测设置和使用自动配置脚本—勾选“为LAN代理服务器” 并填写地址IP+Port。IE浏览器设置过后便会在本地只要有HTTP/HTTPS请求都要通过这个代理。

## 自动设置本地请求代理IP和端口
```python
import winreg#为操作注册表的库
def disableProxy(proxy):
    proxy = ""
    xpath = "Software\Microsoft\Windows\CurrentVersion\Internet Settings"
    try:
        key = winreg.OpenKey(winreg.HKEY_CURRENT_USER, xpath, 0, winreg.KEY_WRITE)
        winreg.SetValueEx(key, "ProxyEnable", 0, winreg.REG_DWORD, 0)
        winreg.SetValueEx(key, "1ProxyServer", 0, winreg.REG_SZ, proxy)
    except Exception as e:
        print("ERROR: " + str(e.args))
    finally:
        None
proxy=ip+":"+port
disableProxy(proxy)
**winreg*
*读取用的方法是OpenKey方法:打开特定的key

_winreg.OpenKey(key,sub_key,res=0,sam=KEY_READ)

socket模块中有几个函数
server=socket.socket()-----创建套接字
server.bind(("127.0.0.1",8000))----绑定本地这个IP和端口
server.listen(3)------等待客户端连接(这里的客户端是值本地PC所有HTTP请求中都会先到这儿)
c,addr=server.accept()-----建立客户端连接 返回connection 对象 表示已连接到客户端。
while true:
		c..recv(1024)--接收TCP数据,数据以字符串形式返回,bufsize指定要接收的最大数据量。flag提供有关消息的其他信息,通常可以忽略。
		c.sendall(msg)--- 完整发送TCP数据,完整发送TCP数据。将string中的数据发送到连接的套接字,但在返回之前会尝试发送所有数据。成功返回None,失败则抛出异常。
		

```python
import socket
import thread
import urlparse
import select

BUFLEN=8192


class Proxy(object):
    def __init__(self,conn,addr):
        self.source=conn
        self.request=""
        self.headers={}
        self.destnation=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
        self.run()

    def get_headers(self):#获取头部信息
        header=''
        while True:
            header+=self.source.recv(BUFLEN)
            print header
            index=header.find('\n')
            if index >0:
                break
        #firstLine,self.request=header.split('\r\n',1)
        print "header"
        print header
        firstLine=header[:index]
        self.request=header[index+1:]
        self.headers['method'],self.headers['path'],self.headers['protocol']=firstLine.split()

    def conn_destnation(self):
        url=urlparse.urlparse(self.headers['path'])
        hostname=url[1]
        port="80"
        if hostname.find(':') >0:
            addr,port=hostname.split(':')
        else:
            addr=hostname
        port=int(port)
        ip=socket.gethostbyname(addr)
        print ip,port
        try:
                self.destnation.connect((ip, port))# 主动初始化TCP服务器连接,。一般address的格式为元组(hostname,port),如果连接出错,返回socket.error错误。 
                data = "%s %s %s\r\n" % (self.headers['method'], self.headers['path'], self.headers['protocol'])
                self.destnation.send(data + self.request)#发送TCP数据,将string中的数据发送到连接的套接字。返回值是要发送的字节数量,该数量可能小于string的字节大小。
                print "data" + "\n", data
                print  "request" + "\n", self.request
        except Exception as e :
            print  e.message
            pass


    def renderto(self):
        readsocket=[self.destnation]
        while True:
            data=''
            (rlist,wlist,elist)=select.select(readsocket,[],[],3)#第一个参数是我们需要监听可读的套接字, 第二个参数是我们需要监听可写的套接字, 第三个参数使我们需要监听异常的套接字, 第四个则是时间限制设置.
            if rlist:
                data=rlist[0].recv(BUFLEN)#接收TCP数据,数据以字符串形式返回,bufsize指定要接收的最大数据量。flag提供有关消息的其他信息,通常可以忽略。
                if len(data)>0:
                    self.source.send(data)
                else:
                    break
    def run(self):
        self.get_headers()
        self.conn_destnation()
        self.renderto()
    



class Server(object):

    def __init__(self,host,port,handler=Proxy):
        self.host=host
        self.port=port
        self.server=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
        self.server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        self.server.bind((host,port))
        self.server.listen(5)
        self.handler=handler

    def start(self):
        while True:
            try:
                conn,addr=self.server.accept()
                thread.start_new_thread(self.handler,(conn,addr))
            except:
                pass


if __name__=='__main__':
    s=Server('127.0.0.1',5055)
    s.start()

在这里插入图片描述在这里插入图片描述

发布了17 篇原创文章 · 获赞 1 · 访问量 446

猜你喜欢

转载自blog.csdn.net/qq_36495121/article/details/102780934
今日推荐