Akamai Bot Manager és una de les solucions anti-bot més comunes del mercat. És utilitzat per molts llocs web d'alt perfil, des de llocs de comerç electrònic fins a llocs de viatges, i, depenent de la seva configuració, pot ser difícil d'obviar. Basant-me en la meva experiència, el patró típic que em trobo quan un lloc web activa la protecció de Akamai Bot Manager és que el rascador (normalment un de Scrapy a la meva pila) penja i temps fora de la primera sol·licitud. Però què és Akamai Bot Manager, i com puc veure si un lloc web l'utilitza? Akamai Bot Manager Revisió general La detecció de bot d'Akamai, com qualsevol altre programari modern de protecció anti-bot, funciona en múltiples capes. és un dels primers: Akamai analitza els detalls de la maniobra i la connexió de TLS (empremta digital de TLS JA3, suites de xifratge, versió de TLS, etc.) per veure si coincideixen amb un navegador real o una eina d'automatització coneguda. Network fingerprinting També inspecciona - Els navegadors reals gairebé sempre utilitzen HTTP/2+ aquests dies, i envien encapçalaments HTTP en un ordre i format determinats. Si un client encara està utilitzant HTTP/1.1 o té encapçalaments en un ordre no navegador, és una bandera vermella. Mirror d'un navegador real és crucial. HTTP/2 usage and header order and their order Un altre llac és Akamai comprova si l'IP del client prové d'una xarxa residencial, una xarxa mòbil o un centre de dades. Les IP residencials i mòbils (el tipus d'usuaris reals) tenen una puntuació alta en confiança, mentre que els rangs d'IP del centre de dades coneguts són automàticament sospitosos. - Sempre semblar venir de diferents ubicacions d'usuari real, no d'una granja de servidors de núvol. IP reputation and analysis residential proxies Finalment, Un sensor de JavaScript a la pàgina web recull una multitud de punts de dades sobre l'entorn i les interaccions del client (com ara el temps, els moviments del ratolí o la seva absència, propietats inusuals en l'objecte del navegador, etc.). els models d'AI d'Akamai crunyen aquestes dades per assignar una puntuació de probabilitat de bot a cada sessió. Aquest aspecte és el més difícil d'obviar i sovint requereix executar un navegador sense cap o replicar la lògica del sensor. (És més enllà del nostre abast aquí - el nostre focus serà passar les comprovacions a nivell de xarxa, que és el cas més comú per a llocs web de comerç electrònic, en la meva experiència.) Ocupació d'Akamai Anàlisi comportamental Utilitzar els scripts del costat del client i els models AI Ocupació d'Akamai Anàlisi comportamental Anàlisi comportamental Utilitzar els scripts del costat del client i els models AI Però com podem detectar que un lloc web està utilitzant Akamai Bot Manager? A més de Si observeu el i Les cookies utilitzades en un lloc web, aquest és el signe més clar que està utilitzant Akamai per protegir-se. the usual Wappalyzer browser extension Abc Títol Bmsc L'extensió del navegador habitual Wappalyzer Abc Abc Títol Bmsc Títol Bmsc Tenint en compte aquestes defenses, molts usuaris de Scrapy han recorregut a la descarregar el gestor per eludir Akamai. Aquest plugin integra el Biblioteca per fingir les signatures de xarxa dels navegadors reals. scrapy-impersonate curl_cffi En la pràctica, Scrapy Impersonate fa que les sol·licituds de Scrapy spider "siguin" com un Chrome o Firefox: ofereix empremtes digitals TLS (JA3) que coincideixen amb aquests navegadors, utilitza HTTP/2, i fins i tot ajusta els encapçalaments de quadres HTTP/2 de baix nivell per imitar els patrons del navegador. Limitacions de Scrapy Impersonate Mentre que Scrapy Impersonate és una eina poderosa, ve amb certes limitacions: Scrapy Impersonate is designed as a Scrapy download handler, which means it only works within Scrapy’s asynchronous framework. If your project doesn’t use Scrapy or you want to switch to a different framework (like a simple script with / or an asyncio pipeline), you can’t directly carry over its capabilities. Migrating away from Scrapy often means a of your HTTP logic, and you’d lose the built-in TLS spoofing unless you implement a new solution from scratch. Locked into Scrapy: requests httpx complete rewrite Using Scrapy Impersonate alongside proxy rotation can be tricky. Under the hood, it replaces Scrapy’s default downloader with one based on , which doesn’t seamlessly integrate with Scrapy’s proxy middleware. Early adopters discovered that HTTPS proxy support was broken because the proxy handling code was bypassed. Although fixes and workarounds (like disabling Scrapy’s built-in proxy handling and configuring directly) exist, it’s harder to rotate proxies or handle proxy authentication with this setup. Robust error handling for proxy failures (e.g., detecting a dead proxy and retrying) is not as straightforward as with Scrapy’s standard downloader, because errors bubble up from the layer and may not trigger Scrapy’s usual retry logic. Proxy Rotation Challenges: curl_cffi curl_cffi curl Scrapy Impersonate currently supports a finite list of browser fingerprints (Chrome, Edge, Safari, etc., up to certain versions). This list can lag behind the latest browser releases. You might be stuck impersonating an older browser version, which could be a problem if a target site specifically requires the nuances of a newer TLS handshake (some advanced WAFs actually check minor details that change between Chrome versions). Maintenance and Flexibility: Perhaps most importantly, even with proper TLS and HTTP/2 impersonation, . For websites that have implemented a higher level of protection, checking also the browser fingerprint, any browserless configuration, including Scrapy Impersonate, isn’t sufficient for Akamai or similar top-tier bot defenses. You might get past the TLS handshake, but fail on other signals (like the absence of the expected sensor data or subtle discrepancies in headers/cookies). In other words, it’s a piece of the puzzle, not a complete solution. Not a Silver Bullet: Akamai Bot Manager can still detect and block you La solució que veurem avui ajuda a resoldre els dos primers punts: ens encadenarem junts , per a una empremta de TLS òptima i un proxy residencial rotatiu per rotar les nostres IP i tenir puntuacions de reputació més altes. Ja3Proxy Ja3Proxy Comprensió de les empremtes digitals TLS i JA3 Abans de submergir-se en la solució, és important entendre què exactament estem falsificant. Aquesta empremta és una combinació de la versió del protocol TLS i un munt d'opcions que el client diu que dóna suport - pensa en això com el "dialecte" del client de parlar TLS. Els components clau inclouen: TLS fingerprint e.g. TLS 1.2 vs TLS 1.3. Modern browsers will offer 1.3 (while still allowing 1.2 for compatibility). Older clients or some libraries might only do 1.2. Supported TLS Version: the list of cryptographic algorithms the client can use, in preferred order. Browsers tend to have long lists including ciphers like AES-GCM, ChaCha20, etc., plus some GREASE (randomized) values to prevent fingerprinting. Cipher Suites: extra features in TLS, like Server Name Indication (SNI), supported groups (elliptic curves), ALPN (which is used for HTTP/2 negotiation), etc. Both the presence of certain extensions and their order matter. Extensions: El concepte de és una manera estandarditzada d'enregistrar aquests detalls del client de TLS. JA3, anomenat després de les inicials dels seus creadors, compon una cadena d'empremtes digitals concatenant els camps anteriors en un ordre específic: JA3 fingerprinting JA3_string = TLSVersion,CipherSuiteIDs,ExtensionIDs,EllipticCurveIDs,EllipticCurveFormatIDs Cada llista (cifres, extensions, etc.) està unida per Les seccions de Per exemple, un navegador de Chrome pot produir una cadena JA3 com: - , 771,4866-4867-4865-....-47-255,0-11-10-16-23-...-21,29-23-30-25-24,0-1-2 Això representa TLS 1.2 (771 és 0x0303), un conjunt específic de suites de xifratge, extensions, corbes suportades i formats de corba (els nombres són ID estandarditzats). Les eines de seguretat sovint registren o comparen el hash MD5 (ja que és més fàcil de manejar que una llarga cadena de nombres). MD5 hashed Per què és important per a la detecció de bot? perquè Chrome versió X en Windows presentar la mateixa empremta JA3 fins a l'ordre de la llista. Firefox tindrà el seu propi JA3 distint. browser TLS stacks are fairly uniform Sempre La biblioteca de sol·licituds de Python (que utilitza OpenSSL sota el capó) té un JA3 que és totalment diferent de qualsevol navegador principal, de manera que és fàcil de detectar. Els serveis anti-bot com Akamai mantenen bases de dades de hash de JA3: si el teu JA3 no està en la llista de "bons coneguts" (browsers comuns) o si està en una llista d'automatització coneguda, t'obté una marca. En resum, per passar les comprovacions d'empremta digital TLS d'Akamai, . we need our client’s JA3 to match a popular browser Això sol significar imitar l'última empremta digital de Chrome o Firefox (ja que aquests són els usuaris legítims més comuns a la web). Simplement canviar la cadena User-Agent no és suficient - hem de modificar la maniobra TLS de baix nivell. (que en si mateix aprofita una construcció especial de biblioteques curl i TLS per imitar navegadors). curl_cffi TLS Impersonation Proxy + cadena de proxy residencial La nostra solució és per fer que el nostre rascador sigui pràcticament indistingible d'un usuari real del navegador: chain two proxies JA3Proxy is an open-source tool that acts as an HTTP(S) proxy that replays traffic with a chosen TLS fingerprint. In other words, you run JA3Proxy locally, configure it to imitate a specific browser’s TLS handshake, and then direct your scraper traffic through it. JA3Proxy will terminate your TLS connection and initiate a new TLS handshake to the target site using the impersonated fingerprint. From the target site’s perspective, it looks like, say, a Chrome browser connecting. The beauty of this approach is that – you can use Python , , cURL, or anything, by simply pointing it at JA3Proxy. You are no longer locked into Scrapy or any particular library to get browser-like TLS; the proxy takes care of it. JA3Proxy for TLS Impersonation: it’s client-agnostic requests httpx Under the hood, JA3Proxy uses (an advanced TLS library in Go) to customize the Client Hello. It supports a variety of client profiles (Chrome, Firefox, Safari, etc., across different versions). You can, for example, configure it to mimic the latest browsers available in the library. For our needs, we’d choose the latest available Chrome fingerprint, Chrome 133. As for Scrapy-Impersonate, the integration of the latest browsers in the library can take some time, but until this gets regularly updated, it’s not an issue. uTLS One thing to note: JA3Proxy focuses on TLS fingerprints (the JA3 part). It doesn’t inherently modify HTTP headers (other than those that relate to TLS, like ALPN for HTTP/2) or handle higher-level browser behaviors. It gets us past the network fingerprinting, which is the hardest to change, but we must still ensure our HTTP headers and usage patterns are correct. Luckily, we can manually set headers in our HTTP client to mimic a browser (User-Agent, etc.), and HTTP/2 can be achieved as long as the TLS negotiation allows it (Chrome’s Client Hello will advertise ALPN support for h2, so if the site supports it, JA3Proxy will negotiate HTTP/2). The second part of the chain is an upstream . This will take care of the IP reputation and distribution. Residential Proxy for IP Rotation: residential proxy The combined effect is powerful: to Akamai, your scraper now looks like Chrome 133 running on a residential IP. The TLS handshake matches Chrome’s JA3, the HTTP/2 and headers can be adjusted to match Chrome, and the source IP is a regular household. This addresses the major fingerprinting vectors at the network level. It doesn’t solve Akamai’s JavaScript-based challenges by itself, but this should be enough to bypass most of the websites you’ll encounter. Instal·lació de JA3Proxy Configureu JA3Proxy i enllaceu-lo amb un proxy residencial. Instal·lació de JA3Proxy JA3Proxy està escrit en Go. Teniu dues opcions fàcils: compilar des de la font o utilitzar un contenidor Docker. git clone https://github.com/LyleMi/ja3proxy.git cd ja3proxy make Això hauria de produir a es pot executar a la carpeta. (Alternativament, es pot executar manualment, ja que el projecte està basat en Go.) ja3proxy go build Si prefereixes Docker, hi ha una imatge pre-construïda al Registre de contenidors de GitHub. docker pull ghcr.io/lylemi/ja3proxy:latest es descarrega l'última imatge. llavors es pot executar amb (Mostrarem el comandament executar en un moment.) Docker és convenient perquè empaqueta tot sense necessitar un entorn local de Go. docker run En la meva experiència personal, la instal·lació va ser una mica un malson. No vaig poder fer que la imatge de Docker funcionés, ja que constantment vaig rebre errors quan intentava connectar-me a ella, ja que no es va reconèixer cap navegador. Llavors vaig decidir construir manualment al meu Mac, i em vaig trobar amb els mateixos errors. No obstant això, després d'hores de debugging, vaig trobar que necessitava actualitzar algunes dependències, especialment l'utLS; hi havia conflictes en les versions de les biblioteques, i tot això estava causant problemes. De totes maneres, vaig aconseguir instal·lar-lo, de manera que si obté alguns errors al principi, no renunciïs. Obtenció o creació de certificats TLS JA3Proxy pot actuar com un proxy HTTPS, el que significa que intercepta TLS i presenta el seu propi certificat al seu client. Per defecte, es busca i Si no en proporcioneu un, podeu executar-lo en mode simple (com un proxy HTTP normal) i simplement ignorar la verificació del certificat en el vostre client (no recomanable per a la producció, però acceptable per a la prova). cert.pem key.pem La millor pràctica és generar un certificat arrel i clau auto-signat, i configurar el rascador per confiar en aquest certificat, de manera que pugui interceptar el trànsit sense advertències de seguretat. openssl req -x509 -newkey rsa:2048 -sha256 -days 365 -nodes -keyout key.pem -out cert.pem -subj "/CN=JA3Proxy" Això crea a / (Per a l'ús de la producció, fins i tot podeu utilitzar un CA intern legítim si teniu aquesta configuració, però per a la majoria de propòsits de raspat, un auto-signat està bé sempre que el vostre client sàpiga confiar en ell.) cert.pem key.pem Iniciar JA3Proxy amb una empremta digital de Chrome Si utilitzeu el binari, executeu una comanda com: ./ja3proxy -port 8080 -client Chrome -version 131 -cert cert.pem -key key.pem -upstream YOURPROXYIP:PORT Hem de trencar aquest comandament: -port 8080 li diu que escolti a la porta 8080 (pot triar un altre port si és necessari). -client Chrome -versió 131 selecciona el perfil d'empremta digital. En aquest exemple, utilitza el perfil integrat per a Chrome 131. Les reemplaçaríeu amb el perfil que coincideixi amb el navegador / versió que desitgeu -per exemple, si Chrome 130 és compatible en l'última versió, podeu utilitzar -client Chrome -versió 130. (Pots trobar la llista d'empremtes digitals disponibles comprovant la documentació de JA3Proxy o la biblioteca uTLS que utilitza. -cert i -key especifiquen els fitxers de certificat TLS que hem generat en l'etapa 2. -upstream 123.45.67.89:1080 és l'adreça del proxy upstream. Això hauria de ser reemplaçat amb el vostre punt final de proxy residencial. Important: JA3Proxy espera que això sigui una adreça de proxy SOCKS5__github.com__. Si el vostre proveïdor us va donar alguna cosa com proxy.provider.com:8000 amb un nom d'usuari / contrasenya, podeu provar el format username:password@proxy.provider.com:8000. (JA3Proxy analitzarà la cadena i ha de gestionar l'autenticació per a SOCKS5 si es dóna en el formulari de l'usuari:pass@host:port. Si això no funciona, podeu configurar el vostre proxy residencial per ser permès per IP o utilitzar una Si utilitzés Docker, l'equivalent seria: docker run -p 8080:8080 \ -v $(pwd)/cert.pem:/app/cert.pem -v $(pwd)/key.pem:/app/key.pem \ ghcr.io/lylemi/ja3proxy:latest \ -client Chrome -version 133 -cert /app/cert.pem -key /app/key.pem \ -upstream YOURPROXYIP:PORT Muntem el cert i la clau al contenidor i exposem el port 8080. Ajusteu el comandament per incloure les credencials de proxy / host real. (o qualsevol host / port que especifiqueu). localhost:8080 Un cas d'ús del món real - MrPorter.com MrPorter.com és un lloc web de comerç electrònic de moda que, juntament amb molts altres en la indústria, es protegeix amb Akamai Bot Manager. Utilitzant una simple sol·licitud de Python, tal com s'especifica en el fitxer En el repositori, vaig trobar un error de temps, com s'esperava. simple_request.py import requests URL = "https://www.mrporter.com/en-gb/mens/product/loewe/clothing/casual-shorts/plus-paula-s-ibiza-wide-leg-printed-cotton-blend-terry-jacquard-shorts/46376663162864673" headers = { "accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8", "accept-language": "en-US,en;q=0.5", "priority": "u=0, i", "sec-ch-ua": "\"Brave\";v=\"135\", \"Not-A.Brand\";v=\"8\", \"Chromium\";v=\"135\"", "sec-ch-ua-mobile": "?0", "sec-ch-ua-platform": "\"macOS\"", "sec-fetch-dest": "document", "sec-fetch-mode": "navigate", "sec-fetch-site": "none", "sec-fetch-user": "?1", "sec-gpc": "1", "service-worker-navigation-preload": "true", "upgrade-insecure-requests": "1", "user-agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/135.0.0.0 Safari/537.36" } def main(): try: response = requests.get(URL, headers=headers, timeout=10) response.raise_for_status() print(response.text) except requests.RequestException as e: print(f"Error fetching the page: {e}") if __name__ == "__main__": main() El resultat: Error fetching the page: HTTPSConnectionPool(host='www.mrporter.com', port=443): Read timed out. (read timeout=10) Per utilitzar , No obstant això, no vaig poder trobar una base de dades que indiqui que les sol·licituds de Python utilitzen comunament aquesta empremta digital. L'eina Scrapfly TLS d'empremta digital Podem veure els resultats L'eina Scrapfly TLS d'empremta digital Podem veure els resultats L'ordre de les Cipher Suites és diferent, i per tant, l'empremta digital també serà diferent. Ara, iniciem el docker JA3Proxy, sense afegir un proxy residencial, i vegem què passa. docker run -p 8080:8080 \ -v $(pwd)/cert.pem:/app/cert.pem -v $(pwd)/key.pem:/app/key.pem \ ghcr.io/lylemi/ja3proxy:latest \ -client Chrome -version 131 -cert /app/cert.pem -key /app/key.pem Hem rebut el missatge HTTP Proxy Server listen at :8080, with tls fingerprint 131 Chrome Així podem utilitzar localhost:8080 com a proxy en el nostre script de sol·licitud de Python. Una altra causa d'errors en la meva configuració va ser que vaig intentar utilitzar Python Requests per connectar-me a JA3Proxy. Després d'escavar durant un temps, vaig trobar que el problema era que la biblioteca de sol·licituds no suporta HTTP/2, mentre que JA3Proxy ho fa quan s'utilitza una versió moderna de Chrome. Per a les meves proves, he d'utilitzar HTTPX, com es mostra en el fitxer . request_with_proxies.py En aquest cas, si torna a cridar l'API Scrapfly TLS, la primera part de la cadena JA3 (l'ordre de xifrat) . és idèntic al del meu navegador és idèntic al del meu navegador Com a prova final, si utilitzem aquest script per sol·licitar la pàgina de MrPorter, podem descarregar-la sense cap problema. Creació d'un proxy residencial Ara que hem resolt la falsificació de l'empremta digital de TLS, només hem de girar l'IP que veurà el lloc web de destinació. JA3Proxy té una opció que ens ajuda en això, anomenada Upstream. En iniciar el comandament JA3Proxy, com segueix: ./ja3proxy -addr 127.0.0.1 -client Chrome -version 131 -cert cert.pem -key key.pem -upstream socks5h://USER:PASS@PROVIDER:PORT -debug Som capaços de tunelitzar les nostres sol·licituds utilitzant el nostre proveïdor de proxy preferit. Tingueu en compte que heu de connectar a través de SOCKS5, així que assegureu-vos que el vostre proveïdor admet aquesta funció. En comprovar la IP després de fer-ho, puc veure que les meves IP de rotació residencial estan en lloc, i puc continuar baixant pàgines MRPorter sense cap problema. pierluigivinciguerra@Mac 85.AKAMAI-JA3PROXY % python3.10 request_with_proxies.py 200 {"ip":"5.49.222.37"} pierluigivinciguerra@Mac 85.AKAMAI-JA3PROXY % python3.10 request_with_proxies.py 200 {"ip":"197.244.237.29"} pierluigivinciguerra@Mac 85.AKAMAI-JA3PROXY % python3.10 request_with_proxies.py 200 {"ip":"41.193.144.67"} pierluigivinciguerra@Mac 85.AKAMAI-JA3PROXY % python3.10 request_with_proxies.py 200 {"ip":"102.217.240.216"} pierluigivinciguerra@Mac 85.AKAMAI-JA3PROXY % python3.10 request_with_proxies.py Conclusions El nivell de protecció del lloc web és mitjà, de manera que no hi ha cap desafiament d'empremta digital del navegador complex per evitar, però, en la meva experiència, és el cas d'ús més comú quan ens trobem amb Akamai en el nostre camí. He triat seguir l'enfocament JA3Proxy per evitar-ho, de manera que aquesta solució es pugui utilitzar en diferents marcs. Si utilitzeu Scrapy, sempre podeu confiar en Scrapy Impersonate, malgrat les seves limitacions, o podeu tractar d'establir els xifres en l'ordre correcte manualment. L'article forma part de la sèrie "The Lab" de Pierluigi Vinciguerra. Consulteu la seva pàgina Substack per obtenir més coneixements sobre el raspat web. L'article forma part de la sèrie "The Lab" de Pierluigi Vinciguerra. Consulteu la seva pàgina Substack per obtenir més coneixements sobre el raspat web. “El laboratori”