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()

在這裏插入圖片描述在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章