• 利用云函数搭建免费代理池


    一.前言

    云函数

    云函数(Serverless Cloud Function,SCF)是云计算厂商为企业和开发者们提供的无服务器执行环境,可在无需购买和管理服务器的情况下运行代码, 是实时文件处理和数据处理等场景下理想的计算平台。只需使用 SCF 平台支持的语言编写核心代码并设置代码运行的条件,即可在某云基础设施上弹性、安全地运行代码。

    无服务器(Serverless)不是表示没有服务器,而表示在使用 Serverless 时,我们无需关心底层资源,也无需登录服务器和优化服务器,只需关注最核心的代码片段,即可跳过复杂的、繁琐的基本工作。使用云函数(SCF)时,我们只需使用平台支持的语言(Python、Node.js、PHP、Golang、Java 及 Custom Runtime)编写代码,云计算厂商将完全管理底层计算资源,包括服务器 CPU、内存、网络和其他配置/资源维护、代码部署、弹性伸缩、负载均衡、安全升级、资源运行情况监控等

    代理池的构建原理

    云函数(SCF)可通过 API 网关触发器进行触发,接受来自客户端的数据,并将请求转发出去。也就是说利用云厂商提供的云函数(函数计算)功能,将客户端的HTTP请求转发,由于云函数拥有非常多的出口IP,也就不怕封IP了

    流量示意图如下

    二.代理池的实现

    2.1 利用云函数搭建socks代理

    原理是通过vps做中转,vps搭建socks服务端,socks服务端将请求转发至云函数的API网关触发器
    参考某位师傅的项目SCFProxy

    1. vps安装socks服务端
      上传 socks_client 文件夹到 VPS 上,执行安装
    python3 -m venv .venv    //python新建虚拟环境
    source .venv/bin/activate   //进入虚拟环境
    pip3 install -r requirements.txt
    
    1. 配置腾讯云函数
      新建云函数

    选择自定义创建函数,选好IP区域,将socks_client目录中的server.py代码复制到编辑器上。注意bridge_ip和bridge_port参数为vps的socks开启监听的ip和端口

    超时时间设置为最大,这样一个socks会话最多能维持15m

    设置触发器为API网关触发

    1. vps运行socks服务端
    python3 socks5.py -u "API访问路径" -bp 监听端口 -sp socks端口 --user user --passwd pass
    

    1. 效果
      可以看到每请求一次就会换一次IP

    2.2 利用云函数搭建http代理

    1.配置云函数
    代码如下,其中SCF_TOKEN参数用来鉴权随便写,客户端client中SCF_TOKEN参数要与之一致

    # -*- coding: utf8 -*-
    import json
    import pickle
    from base64 import b64decode, b64encode
    
    import requests
    
    
    SCF_TOKEN = "Token"
    
    
    def authorization():
        return {
            "isBase64Encoded": False,
            "statusCode": 401,
            "headers": {},
            "body": "Please provide correct SCF-Token",
        }
    
    
    def main_handler(event: dict, context: dict):
        # Tencent cloud has its own authorization system https://console.cloud.tencent.com/cam/capi
        # But it may be a little overqualified for a simple usage like this
        try:
            token = event["headers"]["scf-token"]
        except KeyError:
            return authorization()
    
        if token != SCF_TOKEN:
            return authorization()
    
        data = event["body"]
        kwargs = json.loads(data)
        kwargs['data'] = b64decode(kwargs['data'])
        # Prohibit automatic redirect to avoid network errors such as connection reset
        r = requests.request(**kwargs, verify=False, allow_redirects=False)
    
    
        # TODO: REFACTOR NEEDED. Return response headers and body directly.
        # There are many errors occured when setting headers to r.headers with some aujustments(https://cloud.tencent.com/document/product/583/12513).
        # and the response `r.content`/`r.raw.read()` to body.(like gzip error)
        serialized_resp = pickle.dumps(r)
    
        return {
            "isBase64Encoded": False,
            "statusCode": 200,
            "headers": {},
            "body": b64encode(serialized_resp).decode("utf-8"),
        }
    

    超时时间设置为最大

    设置触发器为API网关触发

    2.本地配置客户端将流量转发至API网关
    使用mitmproxy提供本地代理,本地运行mitmdump加载配置开启http代理
    pip3安装mitmproxy

    pip3 install mitmproxy
    

    client配置代码如下:
    scf_servers 参数可以添加多个API接口,这样获取的IP地址就会更多

    import json
    import pickle
    from typing import List
    from random import choice
    from urllib.parse import urlparse
    from base64 import b64encode, b64decode
    
    import mitmproxy
    from mitmproxy.net.http import Headers
    
    #API访问地址,可以添加多个,以逗号分隔
    scf_servers: List[str] = []
    
    #授权Token,与云函数中的token配置一致
    SCF_TOKEN = "Token"
    
    
    def request(flow: mitmproxy.http.HTTPFlow):
        scf_server = choice(scf_servers)
        r = flow.request
        data = {
            "method": r.method,
            "url": r.pretty_url,
            "headers": dict(r.headers),
            "cookies": dict(r.cookies),
            "params": dict(r.query),
            "data": b64encode(r.raw_content).decode("ascii"),
        }
    
        flow.request = flow.request.make(
            "POST",
            url=scf_server,
            content=json.dumps(data),
            headers={
                "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
                "Accept-Encoding": "gzip, deflate, compress",
                "Accept-Language": "en-us;q=0.8",
                "Cache-Control": "max-age=0",
                "User-Agent": "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36",
                "Connection": "close",
                "Host": urlparse(scf_server).netloc,
                "SCF-Token": SCF_TOKEN,
            },
        )
    
    
    def response(flow: mitmproxy.http.HTTPFlow):
        if flow.response.status_code != 200:
            mitmproxy.ctx.log.warn("Error")
    
        if flow.response.status_code == 401:
            flow.response.headers = Headers(content_type="text/html;charset=utf-8")
            return
    
        if flow.response.status_code == 433:
            flow.response.headers = Headers(content_type="text/html;charset=utf-8")
            flow.response.text = "<html><body>操作已超过云函数服务最大时间限制,可在函数配置中修改执行超时时间</body></html>"
            return
    
        if flow.response.status_code == 200:
            body = flow.response.content.decode("utf-8")
            resp = pickle.loads(b64decode(body))
    
            r = flow.response.make(
                status_code=resp.status_code,
                headers=dict(resp.headers),
                content=resp.content,
            )
            flow.response = r
    
    

    本地运行mitmdump加载client配置,监听8080端口开启http代理

    mitmdump -s client.py -p 8080
    

    代理https网站浏览器需要安装mitmdump的ca证书
    证书路径在当前用户的.mitmproxy目录下

    最后效果,每次请求都是不同的IP:

  • 相关阅读:
    Linux 4.11 内核变化
    c++设计模式
    【MySQL】undo,redo,2PC,恢复思维导图
    10053
    深入理解MySQL中的Redo、Undo、MVCC
    oracle 博客精选
    Linux内存中的Cache真的能被回收么?
    MySQL性能指标及计算方法 等待show processlist
    HTTP抓包工具Fiddler
    科来网络分析
  • 原文地址:https://www.cnblogs.com/supdon/p/15099742.html
Copyright © 2020-2023  润新知