利用雲函數搭建免費代理池


一.前言

雲函數

雲函數(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:


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM