关闭

Python入门:python实现http透明代理(二)

标签: pythonhttp代理
542人阅读 评论(0) 收藏 举报
分类:

编写此例只是因为个人在学习的过程中遇到了诸多问题,并且没有在网上找到一个比较全面的、浅析的案例,大多案例直接用到了select、queue等等,结构也特别清晰,导致不明白哪些是必要的,业务处理逻辑是什么样,所以在此写出来,作为自己的笔记,同时也可以供初学者参考
浏览器(C)—————-HttpProxy(HP)—————-web服务器(S)
要做http代理,这个代理即要做代理服务端,也要做客户端,要接收两头发来的数据,同时要将两头接收到数据转发至对方
1、C向S发送请求
2、HP拦截(处理)
3、HP处理完拦截的数据转发至S
4、S将返回的数据传递给HP
5、HP再将数据拦截(处理)
6、转交给C
1-6就完成了一次完整的请求

'''
python3.5.2
'''

import socket
import threading
import re


def proxy(ser):                                           #接收线程传递过来的socket对象
    conn,addr = ser.accept()                              #接收一个connection然后返回新的connection和address
    data = conn.recv(1024)                                #接收从conn收到的数据
    #print(data)                                          #查看接收到的内容,收到的数据是byte类型
    path_num = data.decode().find('\r\n')                 #解码byte类型数据为字符串,然后查找第一行的末尾数
    first_line = data.decode()[:path_num]                 #获取第一行数据(后续要用来判断请求的方法《method》和相对路径)
    remain_line = data.decode()[path_num:]                #获取http head及data,即除第一行以外的数据(需要了解http协议就知道为什么这样处理)
    method,path_url,protocol = first_line.split()         #http第一行数据中包含三个内容,用空格分割之后就得到三个(后面需要用)
    #print(method)                                        #查看method
    print(path_url)                                       #查看path_url(即全url)(后续需要用这个url分割相对路径)
    #print(protocol)                                      #查看protocol(即http的请求协议,一般就是“http/1.1”)
    host = re.findall(r'(?<=://).*?(?=/)',path_url)[0]    #从全url中分割出host(这个host是用来作为proxy转发到web服务器时的目标地址用)
    main_url = re.findall(r'.*?://',path_url)[0] + host   #从全url中分割出主url(即http://加host)
    #print(main_url)                                      #查看主url
    path = path_url[len(main_url):]                       #相对路径/shopxx-mobile/goods/list/243.jhtml
    s_data = method + ' ' + path + ' ' + protocol  + remain_line#将抓到的包进行处理,然后合并**作为**后续转发到web服务器的数据
    print(s_data)                                         #打印要发送的数据

    print(host)                                           #打印host
    try:                                                  #判断从抓取到的数据中的host是ip地址类型的,还是域名类型的,然后有不同处理
        r_host = socket.gethostbyname(host)               #尝试使用域名解析ip地址,如果解析成功就将port赋值80(这里不严谨,没有考虑https)
        port = '80'
    except:               
        if ':' in host:                                   #如果host中有“:”说明host就是ip地址,并分割出ip址和port
            r_host,port = host.split(':')
        else:
            port = '80'
    s_s = socket.socket()                                 #再创建一个sockte对象,用于前面分离出的ip与端口进行转发浏览器接收到的数据
    print(r_host,port)
    s_s.connect((r_host,int(port)))                       #连接从浏览器接收到的数据中的目标ip与端口
    print("############################")
    print(s_data)                                         #打印要转发的数据
    s_s.send(s_data.encode())                             #转发要发送的数据
    d = s_s.recv(1024)                                    #接收转发到web服务器的返回数据
    print(d)                                              #打印从web服务器返回的数据
    conn.send(d)                                          #将接收的数据使用最上面socket对象中的conn进行发送
    #ser.close()
    #s_s.close()


SER_ADDR = ('', 8088)           #因为socket中的bind需要一个地址与端口的tuple类型
ser = socket.socket()           #创建一个socket对象
ser.bind(SER_ADDR)              #对socket对象绑定地址和端口
ser.listen(5)                   #设置socket对象同时监听多少个链接

while True:                     #为开启线程循环
    t = threading.Thread(target=proxy(ser))
    t.start()

扩展:
Accept a connection. The socket must be bound to an address and listening for connections. The return value is a pair (conn, address) where conn is a new socket object usable to send and receive data on the connection, and address is the address bound to the socket on the other end of the connection.

0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:148901次
    • 积分:2770
    • 等级:
    • 排名:第13456名
    • 原创:122篇
    • 转载:25篇
    • 译文:10篇
    • 评论:18条
    个人独立博客
    最新评论