• Python3 socket通过代理访问web服务实现


    一、说明

    1.1 背景说明

    关于“代理”,从burpsuite到ss这类正向代理,再从nginx到haproxy这类反向代理,也用了好多年配置了好多年了。在日积月累之下也确认了以下几个问题:

    正向代理和反向代理的区别----正常访问路径是client----public network----server,如果代理服务器处于client和public network之间就是正向代理,如果代理服务器处于public network和server之间就是反向代理。

    代理从连接的角度是怎么实现的----A建立一个tcp连接到B发送应用层内容,B另建立一个tcp连接到C转发A应用层的内容。

    socks5是什么和socket库有什关系和区别----socket我们可以认为是“数据链路层+网络层+传输层”的实现库,socks5是传输层之上的一种协议(类比ssl层)

    ssl密钥协商过程是怎样的----SSL密钥协商过程分析

    怎么编写代码实现ssl通信----Python3+ssl实现加密通信

    但是仍是有一种不甚了解的感觉,比如这两天实现socket使用代理访问web服务代码就又费了好多功夫。

    1.2 环境说明

    代理服务----windows本地运行的whistle代理服务,监听端口8899

    实现语言----python3

    实现功能----socket通过代理访问http服务(第二大点)、socket通过代理访问https服务(第三大点)

    二、socket实现通过代理访问http服务

    2.1 实现代码

    import socket
    
    
    # 以http请求www.baidu.com的请求包内容
    # http以换行表示请求头完结,所以最后的空行千万不要删掉
    http_layer_data = """
    GET / HTTP/1.1
    Host: www.baidu.com
    Upgrade-Insecure-Requests: 1
    User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36
    Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3
    
    """
    
    # 第一步,和代理服务器建立连接
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.connect(('127.0.0.1', 8899))
    
    # 第二步,向代理服务器发送请求
    # 代理服务器识别接收到是http协议内容后,会根据Host头进行转发
    s.sendall(http_layer_data.encode())
    
    # 第三步,接收到服务器响应并打印
    response_data = s.recv(1024)
    print(response_data.decode())
    s.close()

    2.2 响应结果

    如下图所示,成功接收到302重定向响应

    三、socket实现通过代理访问https服务

    现在大多数服务都不再使用http协议,而是转而使用https协议。

    如果是代码直接访问https服务,那问题还是比较明朗的,我们只要先与https服务端建立一个ssl连接,然后再发送http层内容即可。

    但是如果中间插入一个代理,这问题就比较棘手:客户端该用socket和代理服务器连接呢还是该用ssl和代理服务器连接、客户端又该如何通知代理服务器使用https向https服务端转发内容。

    3.1 代码实现

    import socket
    import ssl
    
    # 以http请求www.baidu.com的请求包内容
    # http以换行表示请求头完结,所以最后的空行千万不要删掉
    http_layer_data = """
    GET / HTTP/1.1
    Host: www.baidu.com
    Connection: keep-alive
    Pragma: no-cache
    Cache-Control: no-cache
    Upgrade-Insecure-Requests: 1
    User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36
    Sec-Fetch-User: ?1
    Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3
    Sec-Fetch-Site: none
    Sec-Fetch-Mode: navigate
    Accept-Encoding: gzip, deflate, br
    Accept-Language: zh-CN,zh;q=0.9,en;q=0.8
    
    """
    
    # 第一步,和代理服务器建立socket连接
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.connect(("127.0.0.1", 8899))
    
    # 第二步,代理服务器与https服务端进行密钥协商并建立ssl连接,用于后续转发
    connect_request_http_layer_data = """
    CONNECT www.baidu.com:443 HTTP/1.0
    Connection: close
    
    """
    s.sendall(connect_request_http_layer_data.encode())
    response_data = s.recv(1024)
    print(response_data.decode())
    
    # 第三步,建立ssl连接
    context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
    ss = context.wrap_socket(s)
    
    # 第四步,向代理服务器发送请求
    # 代理服务器会解出其中的http层内容,使用先前和https服务端建立的连接,进行转发
    ss.send(http_layer_data.encode())
    
    # 第五步,接收到服务器响应并打印
    response_data = ss.recv(1024)
    print(response_data.decode())
    ss.close()

    3.2 响应结果

    四、不建议使用socket访问应用层服务的原因

    不建议使用socket访问应用层服务的原因,其实除了代理这种功能比较费劲外,还有一个更主要的原因。

    在上边的代码中我们发送一个请求然后接收响应,好像一切都正常没什么毛病,但这只是因为返回的结果比较短;

    当服务端内容比较多时会把结果分成多个包返回来,socket是不管应用层内容的定界的,哪几个tcp包是才一个完整的http响应需要你自己去定界,这是一个很痛苦的事情。http服务如此,其他应用层服务也如此。

    python访问http服务,还是推荐使用requests库

    五、关于只有IDE自己的请求才走IDE代理的说明

    PyCharm这种IDE都有一个代理配置,当我和测试同事说想让他们的测试用例走代理时他第一反应是找IDE的这个代配置,我一时也有点懵了这到底能这么实现的吗。

    回头测试了一下,这个代理设置只能是说让IDE本身的如检查更新这类流量走这个代理,IDE中你自己的编写的代码的请求他是管不到的。

    参考:

    http://www.fridayhaohao.com/articles/24/

  • 相关阅读:
    jQuery火箭图标返回顶部代码
    jQuery火箭图标返回顶部代码
    cookie相关内容:用法,特点,常用功能以及与session的异同
    JSP (一)
    Node.js npm 环境配置
    新老版本vue-cli的安装及创建项目等方式的比较
    npm 代理设置及更换为国内下载源
    for...of的使用
    打印机使用方法
    给OC项目添加icon
  • 原文地址:https://www.cnblogs.com/lsdb/p/14525027.html
Copyright © 2020-2023  润新知